http-proxy-middleware

http-proxy-middleware

用于把請(qǐng)求代理轉(zhuǎn)發(fā)到其他服務(wù)器的中間件。

簡(jiǎn)介

例如:我們當(dāng)前主機(jī)為http://localhost:3000/奉狈,現(xiàn)在我們有一個(gè)需求,如果我們請(qǐng)求/api,我們不希望由3000來處理這個(gè)請(qǐng)求,而希望由另一臺(tái)服務(wù)器來處理這個(gè)請(qǐng)求怎么辦碳柱?

var express = require('express');
var proxy = require('http-proxy-middleware');

var app = express();

app.use('/api', proxy({target: 'http://localhost:3001/', changeOrigin: true}));
app.listen(3000);

現(xiàn)在,我們利用express在3000端口啟動(dòng)了一個(gè)小型的服務(wù)器熬芜,利用了app.use('/api', proxy({target: 'http://localhost:3001/', changeOrigin: true}));這句話莲镣,使發(fā)到3000端口的/api請(qǐng)求轉(zhuǎn)發(fā)到了3001端口。即請(qǐng)求http://localhost:3000/api相當(dāng)于請(qǐng)求http://localhost:3001/api涎拉。

安裝

$ npm install --save-dev http-proxy-middleware

核心概念

proxy中間件配置

proxy([context,] config)
var proxy = require('http-proxy-middleware');

var apiProxy = proxy('/api', {target: 'http://www.example.org'});
//                   \____/   \_____________________________/
//                     |                    |
//                需要轉(zhuǎn)發(fā)的請(qǐng)求           目標(biāo)服務(wù)器

// 'apiProxy' 現(xiàn)在已經(jīng)準(zhǔn)備作為一個(gè)中間件了瑞侮。
  • options.target: target 由協(xié)議和主機(jī)組成
proxy(uri [, config])
// 上例的簡(jiǎn)潔寫法
var apiProxy = proxy('http://www.example.org/api');

舉例

// 引用依賴
var express = require('express');
var proxy = require('http-proxy-middleware');

// proxy 中間件的選擇項(xiàng)
var options = {
        target: 'http://www.example.org', // 目標(biāo)服務(wù)器 host
        changeOrigin: true,               // 默認(rèn)false,是否需要改變?cè)贾鳈C(jī)頭為目標(biāo)URL
        ws: true,                         // 是否代理websockets
        pathRewrite: {
            '^/api/old-path' : '/api/new-path',     // 重寫請(qǐng)求鼓拧,比如我們?cè)丛L問的是api/old-path半火,那么請(qǐng)求會(huì)被解析為/api/new-path
            '^/api/remove/path' : '/path'           // 同上
        },
        router: {
            // 如果請(qǐng)求主機(jī) == 'dev.localhost:3000',
            // 重寫目標(biāo)服務(wù)器 'http://www.example.org' 為 'http://localhost:8000'
            'dev.localhost:3000' : 'http://localhost:8000'
        }
    };

// 創(chuàng)建代理
var exampleProxy = proxy(options);

// 使用代理
var app = express();
    app.use('/api', exampleProxy);
    app.listen(3000);

上下文匹配

假如你不能使用主機(jī)的路徑參數(shù)來創(chuàng)建代理,或者你需要更靈活的方式來創(chuàng)建代理的話季俩,這里提供了選擇性的方式來決定哪些請(qǐng)求會(huì)被轉(zhuǎn)發(fā)慈缔;

 foo://example.com:8042/over/there?name=ferret#nose
 \_/  \______________/\_________/ \_________/ \__/
  |           |            |            |       |
協(xié)議          主機(jī)         路徑          查詢     碎片
  • 路徑匹配
    • proxy({...}):匹配任何路徑,所有請(qǐng)求將被轉(zhuǎn)發(fā)种玛;
    • proxy('/', {...}) :匹配任何路徑藐鹤,所有請(qǐng)求將被轉(zhuǎn)發(fā);
    • proxy('/api', {...}):匹配/api開頭的請(qǐng)求
  • 多重匹配
    • proxy(['/api', '/ajax', '/someotherpath'], {...})
  • 通配符路徑匹配
    細(xì)粒度的匹配可以使用通配符匹配赂韵,Glob 匹配模式由 micromatch創(chuàng)造娱节,訪問 micromatch or glob 查找更多用例。
    • proxy('**', {...}) 匹配任何路徑祭示,所有請(qǐng)求將被轉(zhuǎn)發(fā)肄满;
    • proxy('**/*.html', {...}) 匹配任何以.html結(jié)尾的請(qǐng)求;
    • proxy('/*.html', {...}) 匹配當(dāng)前路徑下以html結(jié)尾的請(qǐng)求质涛;
    • proxy('/api/**/*.html', {...}) 匹配/api下以html為結(jié)尾的請(qǐng)求稠歉;
    • proxy(['/api/**', '/ajax/**'], {...}) 組合
    • proxy(['/api/**', '!**/bad.json'], {...}) 不包括**/bad.json
  • 自定義匹配
    /**
     * @return {Boolean}
     */
    var filter = function (pathname, req) {
        return (pathname.match('^/api') && req.method === 'GET');
    };
    
    var apiProxy = proxy(filter, {target: 'http://www.example.org'})
    

選項(xiàng)

http-proxy-middleware options

  • option.pathRewrite:對(duì)象/函數(shù),重寫目標(biāo)url路徑
// 重寫
pathRewrite: {'^/old/api' : '/new/api'}

// 移除
pathRewrite: {'^/remove/api' : ''}

// 添加
pathRewrite: {'^/' : '/basepath/'}

// 自定義
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
  • option.router:對(duì)象/函數(shù)汇陆,重新指定請(qǐng)求轉(zhuǎn)發(fā)目標(biāo)
// 使用主機(jī)或者路徑進(jìn)行匹配怒炸,返回最先匹配到結(jié)果
// 所以配置的順序很重要
router: {
    'integration.localhost:3000' : 'http://localhost:8001',  // host only
    'staging.localhost:3000'     : 'http://localhost:8002',  // host only
    'localhost:3000/api'         : 'http://localhost:8003',  // host + path
    '/rest'                      : 'http://localhost:8004'   // path only
}

// 自定義
router: function(req) {
    return 'http://localhost:8004';
}

http-proxy 事件

參照:http-proxy events

  • option.onError:
// 監(jiān)聽proxy的onerr事件
proxy.on('error', function (err, req, res) {
  res.writeHead(500, {
    'Content-Type': 'text/plain'
  });

  res.end('Something went wrong. And we are reporting a custom error message.');
});
  • option.onProxyRes:監(jiān)聽proxy的回應(yīng)事件
proxy.on('proxyRes', function (proxyRes, req, res) {
  console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2));
});
  • option.onProxyReq:監(jiān)聽proxy的請(qǐng)求事件
proxy.on('proxyReq', function onProxyReq(proxyReq, req, res) {
    proxyReq.setHeader('x-added', 'foobar');
});
  • option.onProxyReqWs:
function onProxyReqWs(proxyReq, req, socket, options, head) {
    proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
}
  • option.onOpen:監(jiān)聽來自目標(biāo)服務(wù)器的信息
proxy.on('open', function (proxySocket) {
  proxySocket.on('data', hybiParseAndLogMessage);
});
  • option.onClose:展示websocket鏈接分離
proxy.on('close', function (res, socket, head) {
  console.log('Client disconnected');
});

http-proxy-middleware

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市毡代,隨后出現(xiàn)的幾起案子阅羹,更是在濱河造成了極大的恐慌,老刑警劉巖教寂,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捏鱼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡酪耕,警方通過查閱死者的電腦和手機(jī)导梆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來迂烁,“玉大人看尼,你說我怎么就攤上這事』楸唬” “怎么了狡忙?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)址芯。 經(jīng)常有香客問我灾茁,道長(zhǎng),這世上最難降的妖魔是什么谷炸? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任北专,我火速辦了婚禮,結(jié)果婚禮上旬陡,老公的妹妹穿的比我還像新娘拓颓。我一直安慰自己,他們只是感情好描孟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布驶睦。 她就那樣靜靜地躺著砰左,像睡著了一般。 火紅的嫁衣襯著肌膚如雪场航。 梳的紋絲不亂的頭發(fā)上缠导,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音溉痢,去河邊找鬼僻造。 笑死,一個(gè)胖子當(dāng)著我的面吹牛孩饼,可吹牛的內(nèi)容都是我干的髓削。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼镀娶,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼立膛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汽畴,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤旧巾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后忍些,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鲁猩,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年罢坝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了廓握。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘁酿,死狀恐怖隙券,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闹司,我是刑警寧澤娱仔,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站游桩,受9級(jí)特大地震影響牲迫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜借卧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一盹憎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铐刘,春花似錦陪每、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挂签。三九已至,卻和暖如春盼产,著一層夾襖步出監(jiān)牢的瞬間竹握,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國打工辆飘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像卿嘲,于是被迫代替她去往敵國和親炉峰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容