您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關(guān)node和express如何搭建代理服務器,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
本例用node和express搭建的代理服務器。期望目標如下:
1、開啟某服務A,該服務可實現(xiàn)若干功能,例如普通的restful請求,文件上傳,靜態(tài)資源訪問等等。
2、開啟node代理服務B,指向服務A,訪問代理服務B,可訪問服務A的任意功能。
就如下圖所示:
圖中上半部分是直接訪問服務,下班部分是通過代理服務器訪問服務。
使用代理服務器時,瀏覽器向代理服務器請求數(shù)據(jù),代理服務器轉(zhuǎn)發(fā)請求,并將接收到的數(shù)據(jù)返回給瀏覽器,即所有的數(shù)據(jù)都通過代理服務器轉(zhuǎn)發(fā)。
帶著這個目標,我們就講述下如何實現(xiàn)該功能。
既然是請求和響應轉(zhuǎn)發(fā),那我們就了解一下,什么是請求。
http請求和響應主要右報文頭部、空行和報文主體三個部分組成。
空行我們不用關(guān)心,其實對我們來說,只要完成報文頭部和報文主體的轉(zhuǎn)發(fā),就可以說實現(xiàn)了代理功能。
請求和響應通過代理的整個過程如下:
1、代理服務器接收請求后,在將目標服務數(shù)據(jù)返回給瀏覽器前要保持請求。
2、提取請求路徑、請求頭、請求主體等數(shù)據(jù)。
3、以2中提取的數(shù)據(jù)為參數(shù),向目標服務器發(fā)送請求。
4、接收目標服務器返回數(shù)據(jù),提取響應頭,響應主體等數(shù)據(jù)。
5、將4中的提取出來的數(shù)據(jù)返回給客戶端(瀏覽器)。
6、斷開連接。
經(jīng)過這幾個步驟,就實現(xiàn)了代理。
下面直接上代碼,然后做一些講解。代理函數(shù)如下:
const http = require('http'); const querystring = require('querystring'); //獲取請求的cookie和query等 let getHeader = (reqClient) => { let headers = reqClient.headers; headers.path = reqClient.path; headers.query = reqClient.query; headers.cookie = reqClient.get('cookie') || ''; return headers; } //代理函數(shù),options是代理設置,包括目標服務器ip,port等 let proxy = (options) => { let reqOptions = { hostname: options.host, port: options.port } //返回請求處理函數(shù),reqClient瀏覽器的請求,resClient是響應瀏覽器的對象 return function (reqClient, resClient) { //設置目標服務器的請求參數(shù),頭中的各項參數(shù) let headers = getHeader(reqClient); reqOptions.headers = reqClient.headers; let query = []; if (headers.query) { Object.keys(headers.query).map(key => { query.push(key + '=' + headers.query[key]); }); reqOptions.path = headers.path + (query.length === 0 ? '' : ('?' + query.join('&'))); } reqOptions.cookie = headers.cookie; reqOptions.method = reqClient.method; //向目標服務器發(fā)送請求,reqProxy是向目標服務器的請求,resProxy是目標服務器的響應。 let reqProxy = http.request(reqOptions, (resProxy) => { resProxy.setEncoding('utf8'); //設置返回http頭 resClient.set(resProxy.headers); resClient.status(resProxy.statusCode); //接收從目標服務器返回的數(shù)據(jù) resProxy.on('data', (chunk) => { //接收目標服務器數(shù)據(jù)后,以流的方式向瀏覽器返回數(shù)據(jù) resClient.write(chunk); }); //接收目標服務器數(shù)據(jù)結(jié)束 resProxy.on('end', () => { //向瀏覽器寫數(shù)據(jù)結(jié)束。 resClient.end(); }); //目標服務器響應錯誤 resProxy.on('error', () => { //響應錯誤,結(jié)束向瀏覽器返回數(shù)據(jù) resClient.end(); }); }); //接收瀏覽器數(shù)據(jù) reqClient.on('data', (chunk) => { //以流的方式向目標服務器發(fā)送數(shù)據(jù) reqProxy.write(chunk); }); //接收數(shù)據(jù)結(jié)束 reqClient.on('end', () => { //向目標服務器寫數(shù)據(jù)結(jié)束 reqProxy.end(); }); //普通JSON數(shù)據(jù)代理 if (Object.keys(reqClient.body).length) { reqProxy.write(querystring.stringify(reqClient.body)); reqProxy.end(); } } } module.exports = proxy;
上面就是node代理的核心代碼。支持普通的請求,靜態(tài)資源代理,文件上傳下載代理等功能。
git 地址:https://github.com/xubaodian/...
demo中,核心代碼在common/proxy.js里,我還實現(xiàn)了兩個測試服務。
在server文件下的app.js和app2.js是兩個服務的入口文件。
app2.js是目標服務器,有三個測試頁面
1、http://localhost:20000/json.html post請求測試,對應'/json'接口,可發(fā)送數(shù)據(jù),f12查看請求是否成功
2、http://localhost:20000/upload.html 文件上傳測試,對應接口'/upload'接口,上傳文件,f12查看請求是否成功,同時在服務器upload文件夾下會有文件。
3、http://localhost:20000/get.html get請求測試,對應接口'/get',同樣f12查看
app2為目標服務器,有3個接口。
1、'/upload'接口,測試文件上傳功能,上傳文件將放在uploads文件夾下,上傳的文件,文件名是一個uuid,沒有后綴,添加后綴即可查看文件是完整。測試過,傳1G的文件沒問題,再大的文件沒試過,有需要的可以試下
2、'/json',測試POST請求。
3、'/get',測試GET請求。
app.js為代理服務為器,監(jiān)聽端口為18000,將所有請求轉(zhuǎn)發(fā)至app2,即所有app2的接口靜態(tài)資源,app中訪問時一致的。
測試步驟:
1、可開啟目標服務器,通過三個頁面測試功能。
2、開啟代理服務器,訪問下面三個頁面:
http://localhost:18000/json.html
http://localhost:18000/upload.html
http://localhost:18000/get.html
測試同樣的功能。若和步驟1實現(xiàn)同樣功能,則代理服務功能已經(jīng)實現(xiàn)了。
經(jīng)過測試,代理功能是沒問題的。
如果問題歡迎留言,或發(fā)送郵件至472784995@qq.com。
至于性能,我沒測過,因為我自己這邊的應用場景,訪問量都不大,可以使用。
關(guān)于node和express如何搭建代理服務器就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。