Node實現(xiàn)前端本地開發(fā)接口代理服務
背景
我們在前端開發(fā)的接口聯(lián)調(diào)階段,經(jīng)常會遇到跨域問題,因為本地通常使用localhost
域名來啟動項目,當然我們可以通過配置host解決這個問題,但當需要訪問線上頁面的時候,又必須關閉host;我們也可以通過webpack的插件dev-server
來配置代理(Proxy),但有時需要和多個服務端研發(fā)進行接口聯(lián)調(diào),因此就需要配置多個Proxy,設置多個虛擬接口前綴,還要考慮發(fā)布后線上如何不走代理,整體來說,配置工作是比較麻煩的。
目標
針對以上背景,我們需要一個更加簡單靈活的接口代理方案,我們的目標是:
- 接入簡單,只需在前端項目中增加少量代碼;
- 環(huán)境隔離,只針對本地開發(fā)環(huán)境使用代理,對線上無影像,發(fā)布時也無需修改代碼;
- 配置靈活:可針對不同接口進行差異化配置,可同時對接多個服務端研發(fā)進行聯(lián)調(diào);
方案
我們在使用webpack的插件dev-server
時,本質是本地運行了一個代理服務,前端頁面發(fā)送的網(wǎng)絡請求,實際都是請求了這個代理服務,再由代理服務轉發(fā)到實際的接口URL上,最后代理服務再將接口返回的數(shù)據(jù)透傳給前端頁面。
根據(jù)這個原理,我們來自行搭建一個代理服務,也將它在本地運行,來實現(xiàn)同dev-server
插件一樣的代理過程,但我們會在本方案中引入更加靈活的一種配置方式,也就是通過修改config.json
配置文件,來實現(xiàn)更加簡化的配置,以及隨用隨改的靈活特性。
實施
創(chuàng)建NodeJS項目
首先在本地創(chuàng)建一個NodeJS項目(需要安裝NodeJS環(huán)境,版本建議12+),命名為api-proxy-server
,具體步驟略。
溫馨提示:本文的代理服務項目源代碼,筆者免費提供!只需 點贊+關注 即可在評論區(qū)留言索要,留下您的郵箱,筆者會在看到的第一時間發(fā)送,項目源代碼README
文件詳細描述了如何使用,方便您快速接入。
編寫Express服務
我們的代理服務使用Express
框架來開發(fā)(需要安裝依賴),也可以根據(jù)個人習慣使用其他框架,比如KOA
、Egg.js
等。
首先在項目主文件中導入相關依賴:
const express = require('express'); const http = require('http'); const bodyParser = require('body-parser'); const app = express();
然后使用bodyParser
對請求數(shù)據(jù)進行解析:
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
進程守衛(wèi)插件(需要安裝依賴)來啟動服務,這樣做的好處是可以在程序報錯時,保證服務不會停止。
啟動腳本配置如下:
"scripts": { "start": "pm2 start ./src/server.js", "stop": "pm2 stop ./src/server.js", "dev": "node ./src/server.js" },
編寫代理接口
在上述步驟中,我們已經(jīng)可以啟動代理服務,并編寫了一個默認的GET
路由(接口),接下來我們來實現(xiàn)本文的核心內(nèi)容,編寫一個POST
類型的接口,用于對前端接口請求進行代理。
為了方便后續(xù)的維護和擴展,我們將代理接口的源代碼編寫到一個獨立的文件中,目錄為src/routes/api
,文件名為index.js
,然后在主文件中導入并掛載路由即可,代碼如下:
const api = require('./routes/api'); // ...... app.post('/api', api);
注意:代理接口的路由我們定義為/api
,因此在前端項目中調(diào)用這個服務的完整路徑就是http://127.0.0.1:8080/api
,這個接口只能通過axios
來訪問,因為它是POST
類型的,不支持瀏覽器訪問驗證。
我們打開src/routes/api/index.js
文件來編寫具體的代碼,首先導出一個基本的路由函數(shù):
const axios = require("axios"); const qs = require("qs"); const fs = require("fs"); const fspath = require("path"); module.exports = (req, res) => { // ...... }
在這個函數(shù)內(nèi),我們來處理前端請求,先從請求體中獲取參數(shù):
const { path, params } = req.body;
其中path
指定了要訪問哪個服務端接口路徑,params
是要透傳給服務端的實際入?yún)ⅰ?/p>
然后我們在src/routes/api/
目錄下,創(chuàng)建一個接口配置文件config.json
,這個配置文件維護了默認的服務端接口域名或IP地址,以及默認的請求方式和數(shù)據(jù)類型。具體定義如下:
屬性名 | 說明 | 示例 |
---|---|---|
baseUrl | 服務端接口默認地址 | http://192.168.1.17 |
method | 請求方式,默認是POST | GET / POST |
contentType | 數(shù)據(jù)類型,默認是json | form / json |
繼續(xù)編寫代碼,來讀取這個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;
代碼寫到這里,我們已經(jīng)拿到了真實的服務端接口地址、請求類型以及數(shù)據(jù)類型,然后就可以通過axios
來發(fā)送請求了,但這樣并不支持個別請求的差異化,比如有的接口需要跟另外的服務端研發(fā)聯(lián)調(diào),也就是baseUrl
不同、有的接口請求類型是GET
,有的接口請求的數(shù)據(jù)類型是application/x-www-form-urlencoded
,因此我們需要一種機制來實現(xiàn)對差異化接口的配置,我們繼續(xù)改寫config.json
文件,加入extra
數(shù)組,在這個數(shù)組中,我們放入一組對象,來定義個別接口的差異化屬性,具體定義如下:
屬性名 | 說明 | 示例 |
---|---|---|
path | 接口路徑(必填),需要差異化配置的接口 | /user/permision |
baseUrl | 服務端接口地址(選填) | http://192.168.1.16 |
method | 請求方式(選填) | GET / POST |
contentType | 數(shù)據(jù)類型(選填) | form / json |
有了以上配置,我們就可以遍歷extra
數(shù)組,如果當前接口請求的path
在其中,就需要按照差異化的配置發(fā)送請求,具體代碼如下:
// 獲取額外的接口配置 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
來發(fā)送請求到實際的服務端接口地址,然后將返回的數(shù)據(jù)下發(fā)給前端頁面即可。代碼如下:
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: '網(wǎng)絡錯誤' }); Log.api(url, params, '網(wǎng)絡錯誤'); });
代碼中的Log
是用來記錄日志的,方便我們追蹤代理服務的運行情況,具體實現(xiàn)可查看本項目源代碼。
至此我們的代理服務就開發(fā)完成了,運行這個服務,我們就可以在前端項目中接入并使用它了。**注意:**當我們修改了config.json
文件后,保存即可,不需要重啟服務。如果電腦關機重啟了,則需要手動啟動代理服務。
前端項目接入
在前端項目封裝axios請求的地方,判斷如果是本地開發(fā)環(huán)境,則將URL指向此服務,并對入?yún)⑦M行簡單包裝即可。由于我們只對本地環(huán)境做了接口代理,因此發(fā)布項目時無需任何修改,發(fā)布后的版本仍會調(diào)用實際的服務端接口。
代碼示例:
let baseUrl = 'http://api.xyz.com'; // 線上接口域名 let data = { a: 1 } // 接口入?yún)? 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 } } // 發(fā)送請求 axios({ url, data })
以上就是實現(xiàn)前端本地開發(fā)接口代理服務的完整思路和過程,更多相關Node 本地開發(fā)接口代理 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Ubuntu中搭建Nodejs開發(fā)環(huán)境過程分享
這篇文章主要介紹了Ubuntu中搭建Nodejs開發(fā)環(huán)境過程,比較郁悶的是apt-get安裝失敗了,如果有遇到一樣問題的朋友,可以參考一下本文2014-06-06windows 下安裝nodejs 環(huán)境變量設置
windows 下安裝nodejs 了,也安裝了npm, 但是有時候切不能直接用request(‘ws’)這一類的東西.我覺得是確實環(huán)境變量或其他設置有問題,能否給個完整的設置方案:2017-02-02Node.js實現(xiàn)批量替換文件內(nèi)容示例
這篇文章主要為大家介紹了Node.js實現(xiàn)批量替換文件內(nèi)容示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08淺析nodejs實現(xiàn)Websocket的數(shù)據(jù)接收與發(fā)送
WebSocket是HTML5開始提供的一種瀏覽器與服務器間進行全雙工通訊的網(wǎng)絡技術,本文給大家介紹nodejs實現(xiàn)websocket的數(shù)據(jù)庫接收與發(fā)送,小伙伴們一起學習吧2015-11-11NodeJS?基于?Dapr?構建云原生微服務應用快速入門教程
Dapr?是一個可移植的、事件驅動的運行時,它使任何開發(fā)人員能夠輕松構建出彈性的、無狀態(tài)和有狀態(tài)的應用程序,并可運行在云平臺或邊緣計算中,它同時也支持多種編程語言和開發(fā)框架,本文重點介紹NodeJS云原生微服務應用,感興趣的朋友一起看看吧2022-07-07Nodejs下用submit提交表單提示cannot post錯誤的解決方法
這篇文章主要介紹了Nodejs下用submit提交表單提示cannot post錯誤的解決方法,非常不錯,具有參考借鑒價值,感興趣的朋友一起看看吧2016-11-11