亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Node怎么實現前端本地開發接口代理服務

發布時間:2022-05-05 10:00:32 來源:億速云 閱讀:141 作者:iii 欄目:開發技術

本篇內容介紹了“Node怎么實現前端本地開發接口代理服務”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

背景

我們在前端開發的接口聯調階段,經常會遇到跨域問題,因為本地通常使用localhost域名來啟動項目,當然我們可以通過配置host解決這個問題,但當需要訪問線上頁面的時候,又必須關閉host;我們也可以通過webpack的插件dev-server來配置代理(Proxy),但有時需要和多個服務端研發進行接口聯調,因此就需要配置多個Proxy,設置多個虛擬接口前綴,還要考慮發布后線上如何不走代理,整體來說,配置工作是比較麻煩的。

目標

針對以上背景,我們需要一個更加簡單靈活的接口代理方案,我們的目標是:

  • 接入簡單,只需在前端項目中增加少量代碼;

  • 環境隔離,只針對本地開發環境使用代理,對線上無影像,發布時也無需修改代碼;

  • 配置靈活:可針對不同接口進行差異化配置,可同時對接多個服務端研發進行聯調;

方案

我們在使用webpack的插件dev-server時,本質是本地運行了一個代理服務,前端頁面發送的網絡請求,實際都是請求了這個代理服務,再由代理服務轉發到實際的接口URL上,最后代理服務再將接口返回的數據透傳給前端頁面。

根據這個原理,我們來自行搭建一個代理服務,也將它在本地運行,來實現同dev-server插件一樣的代理過程,但我們會在本方案中引入更加靈活的一種配置方式,也就是通過修改config.json配置文件,來實現更加簡化的配置,以及隨用隨改的靈活特性。

實施

創建NodeJS項目

首先在本地創建一個NodeJS項目(需要安裝NodeJS環境,版本建議12+),命名為api-proxy-server,具體步驟略。

溫馨提示:本文的代理服務項目源代碼,筆者免費提供!只需 點贊+關注 即可在評論區留言索要,留下您的郵箱,筆者會在看到的第一時間發送,項目源代碼README文件詳細描述了如何使用,方便您快速接入。

編寫Express服務

我們的代理服務使用Express框架來開發(需要安裝依賴),也可以根據個人習慣使用其他框架,比如KOAEgg.js等。

首先在項目主文件中導入相關依賴:

const express = require('express');
const http = require('http');
const bodyParser = require('body-parser');
const app = express();

然后使用bodyParser對請求數據進行解析:

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

接下來這一步很關鍵,就是要允許跨域,我們要允許所有域名和請求的訪問,具體設置如下:

app.all('*', (req, res, next) => {
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With');
  res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTION');
  res.header('Access-Control-Allow-Credentials', 'true');
  res.header('X-Powered-By', '3.2.1');
  next();
});

然后我們給這個服務編寫默認的路由(也可以理解為接口,對于前端來說,服務端提供的路由都可以視為接口),默認的路由我們定義為GET請求,方便我們在瀏覽器直接訪問,來驗證服務是否成功啟動。

Express掛載路由的方式如下:

app.get('/', (req, res) => {
  res.send('Hello, Welcome use api proxy.');
});

最后,我們來編寫啟動服務的代碼,如下:

const port = 8080;
http.createServer(app).listen(port);
console.log(`http://127.0.0.1:${port} 服務已啟動`);

按照以上步驟編寫完代碼后,啟動服務,在瀏覽器中訪問http://127.0.0.1:8080,如果看到瀏覽器顯示“Hello, Welcome use api proxy.”說起服務啟動成功了。

關于如何啟動服務,筆者的做法是,在package.json中配置啟動腳本dev,然后運行npm run dev即可,也可以通過pm2進程守衛插件(需要安裝依賴)來啟動服務,這樣做的好處是可以在程序報錯時,保證服務不會停止。

啟動腳本配置如下:

"scripts": {
    "start": "pm2 start ./src/server.js",
    "stop": "pm2 stop ./src/server.js",
    "dev": "node ./src/server.js"
},

編寫代理接口

在上述步驟中,我們已經可以啟動代理服務,并編寫了一個默認的GET路由(接口),接下來我們來實現本文的核心內容,編寫一個POST類型的接口,用于對前端接口請求進行代理。

為了方便后續的維護和擴展,我們將代理接口的源代碼編寫到一個獨立的文件中,目錄為src/routes/api,文件名為index.js,然后在主文件中導入并掛載路由即可,代碼如下:

const api = require('./routes/api');
// ......
app.post('/api', api);

注意:代理接口的路由我們定義為/api,因此在前端項目中調用這個服務的完整路徑就是http://127.0.0.1:8080/api,這個接口只能通過axios來訪問,因為它是POST類型的,不支持瀏覽器訪問驗證。

我們打開src/routes/api/index.js文件來編寫具體的代碼,首先導出一個基本的路由函數:

const axios = require("axios");
const qs = require("qs");
const fs = require("fs");
const fspath = require("path");

module.exports = (req, res) => {
  // ......
}

在這個函數內,我們來處理前端請求,先從請求體中獲取參數:

const { path, params } = req.body;

其中path指定了要訪問哪個服務端接口路徑,params是要透傳給服務端的實際入參。

然后我們在src/routes/api/目錄下,創建一個接口配置文件config.json,這個配置文件維護了默認的服務端接口域名或IP地址,以及默認的請求方式和數據類型。具體定義如下:

屬性名說明示例
baseUrl服務端接口默認地址http://192.168.1.17
method請求方式,默認是POSTGET / POST
contentType數據類型,默認是jsonform / json

繼續編寫代碼,來讀取這個config.json配置文件,代碼如下:

// 讀取接口配置文件
const configPath = fspath.resolve(process.cwd(), './src/routes/api/config.json');
if (!fs.existsSync(configPath)) {
  res.json({ code: '-1', msg: '接口配置文件不存在!' });
  return;
}
const configStr = fs.readFileSync(configPath, { encoding: 'utf-8' });
let config = null;
try {
  config = JSON.parse(configStr);
} catch (error) {
  res.json({ code: '-1', msg: '接口配置文件格式有誤,解析失敗!' });
  return;
}
// 獲取接口默認配置
let { baseUrl, method='POST', contentType='json', extra=[] } = config;

代碼寫到這里,我們已經拿到了真實的服務端接口地址、請求類型以及數據類型,然后就可以通過axios來發送請求了,但這樣并不支持個別請求的差異化,比如有的接口需要跟另外的服務端研發聯調,也就是baseUrl不同、有的接口請求類型是GET,有的接口請求的數據類型是application/x-www-form-urlencoded,因此我們需要一種機制來實現對差異化接口的配置,我們繼續改寫config.json文件,加入extra數組,在這個數組中,我們放入一組對象,來定義個別接口的差異化屬性,具體定義如下:

屬性名說明示例
path接口路徑(必填),需要差異化配置的接口/user/permision
baseUrl服務端接口地址(選填)http://192.168.1.16
method請求方式(選填)GET / POST
contentType數據類型(選填)form / json

有了以上配置,我們就可以遍歷extra數組,如果當前接口請求的path在其中,就需要按照差異化的配置發送請求,具體代碼如下:

// 獲取額外的接口配置
if (extra.length > 0) {
  const extraCfg = extra.find(item => item.path === path);
  if (extraCfg) {
    baseUrl = extraCfg.baseUrl || baseUrl;
    method = extraCfg.method || method;
    contentType = extraCfg.contentType || contentType;
  }
}

最后我們使用axios來發送請求到實際的服務端接口地址,然后將返回的數據下發給前端頁面即可。代碼如下:

const url = baseUrl + path;
const headers = {};
if (contentType === 'form') {
  headers['Content-Type'] = 'application/x-www-form-urlencoded';
}
axios({
  method,
  url,
  headers,
  timeout: 3000,
  data: contentType === 'form' ? qs.stringify(params) : params
}).then(result => {
  res.json(result.data);
  Log.api(url, params, result.data);
}).catch(error => {
  res.json({ code: '-1', msg: '網絡錯誤' });
  Log.api(url, params, '網絡錯誤');
});

代碼中的Log是用來記錄日志的,方便我們追蹤代理服務的運行情況,具體實現可查看本項目源代碼。

至此我們的代理服務就開發完成了,運行這個服務,我們就可以在前端項目中接入并使用它了。**注意:**當我們修改了config.json文件后,保存即可,不需要重啟服務。如果電腦關機重啟了,則需要手動啟動代理服務。

前端項目接入

在前端項目封裝axios請求的地方,判斷如果是本地開發環境,則將URL指向此服務,并對入參進行簡單包裝即可。由于我們只對本地環境做了接口代理,因此發布項目時無需任何修改,發布后的版本仍會調用實際的服務端接口。

代碼示例:

let baseUrl = 'http://api.xyz.com'; // 線上接口域名
let data = { a: 1 } // 接口入參
let path = '/user/permision'; // 實際的接口路徑
let url = baseUrl + path; // 請求的完整接口url

if (process.env.NODE_ENV === 'development') {
  url = 'http://127.0.0.1:8080/api';
  data = { path, params: data }
}

// 發送請求
axios({ url, data })

“Node怎么實現前端本地開發接口代理服務”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武穴市| 阿拉善盟| 聂拉木县| 光泽县| 青浦区| 东乡族自治县| 巴青县| 平果县| 淮北市| 天峻县| 平江县| 湟源县| 睢宁县| 延长县| 喀喇沁旗| 西昌市| 西充县| 苏尼特左旗| 灵台县| 阳东县| 庆元县| 延安市| 锡林郭勒盟| 永善县| 崇文区| 大城县| 车险| 水富县| 泌阳县| 康平县| 稷山县| 广西| 江川县| 醴陵市| 阿鲁科尔沁旗| 定远县| 中卫市| 涟源市| 巢湖市| 水城县| 古浪县|