http-proxy-middleware 服務代理

該文章以收錄 《webpack、npm探索之路》

本文爲 http-proxy-middleware 官網譯文 html

單線程node.js代理中間件,用於鏈接,快速和瀏覽器同步node

Node.js代理簡單。 輕鬆配置代理中間件鏈接,快速,瀏覽器同步等。webpack

由流行的Nodejitsu http代理提供。git

TL;DR

代理/api請求到http://www.example.orggithub

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

var app = express();

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

可使用全部http-proxy選項,以及一些額外的http-proxy-middleware選項。web

提示:將基於名稱的虛擬託管網站的選項changeOrigin設置爲true。ajax

安裝

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

核心概念

proxy([context,] config)express

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

var apiProxy = proxy('/api', {target: 'http://www.example.org'});
//                   \____/   \_____________________________/ 
//                     |                    | 
//                   context             options 

// 'apiProxy' is now ready to be used as middleware in a server.
  • context:肯定應將哪些請求代理到目標主機。 (更多關於上下文匹配)
  • options.target:目標主機到代理。 (協議+主機)

(http-proxy-middleware配置選項的完整列表)npm

proxy(uri [, config])json

// shorthand syntax for the example above: 
var apiProxy = proxy('http://www.example.org/api');

更多關於速記配置。

舉個栗子

使用express服務器的示例。

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

// proxy middleware options 
var options = {
        target: 'http://www.example.org', // target host 
        changeOrigin: true,               // needed for virtual hosted sites 
        ws: true,                         // proxy websockets 
        pathRewrite: {
            '^/api/old-path' : '/api/new-path',     // rewrite path 
            '^/api/remove/path' : '/path'           // remove base path 
        },
        router: {
            // when request.headers.host == 'dev.localhost:3000', 
            // override target 'http://www.example.org' to 'http://localhost:8000' 
            'dev.localhost:3000' : 'http://localhost:8000'
        }
    };

// create the proxy (without context) 
var exampleProxy = proxy(options);

// mount `exampleProxy` in web server 
var app = express();
    app.use('/api', exampleProxy);
    app.listen(3000);

匹配代理規則

提供一種替代方式來決定哪些請求應該被代理;若是您沒法使用服務器的路徑參數來裝載代理,或者須要更多的靈活性。

RFC 3986路徑用於上下文匹配。

foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment
  • 路徑匹配
  1. proxy({...}) - 匹配任意路徑,全部的請求都會被代理。
  2. proxy('/', {...})-匹配任意路徑,全部的請求都會被代理。
  3. proxy('/api', {...})-匹配全部以/api開始的路徑。
  • 多重路徑匹配
  1. proxy(['/api', '/ajax', '/someotherpath'], {...})
  • 通配符路徑匹配
    對於細粒度控制,您可使用通配符匹配。經過micromatch進行全局模式匹配。訪問micromatch或glob更多globbing示例。
  1. proxy('**', {...}) 匹配任意路徑,全部的請求都會被代理。
  2. proxy('**/*.html', {...}) 匹配全部以.html結尾的任意路徑。
  3. proxy('/*.html', {...}) 直接匹配絕對路徑下的路徑。
  4. proxy('/api/**/*.html', {...})匹配在/api路徑下以.html結尾的請求。
  5. proxy(['/api/**', '/ajax/**'], {...})組合多重路由模式。
  6. proxy(['/api/**', '!**/bad.json'], {...})排除匹配。
  • 自定義匹配
    爲了徹底控制,您能夠提供一個自定義函數來肯定哪些請求應該被代理。
var filter = function (pathname, req) {
    return (pathname.match('^/api') && req.method === 'GET');
};

var apiProxy = proxy(filter, {target: 'http://www.example.org'})

選項

http-proxy-middleware選項

  • option.pathRewrite:Object/Function,重寫目標的url路徑。對象鍵將被用做RegExp來匹配路徑。
// rewrite path 
pathRewrite: {'^/old/api' : '/new/api'}

// remove path 
pathRewrite: {'^/remove/api' : ''}

// add base path 
pathRewrite: {'^/' : '/basepath/'}

// custom rewriting 
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
  • option.router:Object/Function,從新定位特定請求的option.target
// Use `host` and/or `path` to match requests. First match will be used. 
// The order of the configuration matters. 
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 
}

// Custom router function 
router: function(req) {
    return 'http://localhost:8004';
}
  • option.logLevel:String, [‘debug’, ‘info’, ‘warn’, ‘error’, ‘silent’]. 默認:info
  • option.logProvider:Function,修改或者替換日誌服務。默認:console
// simple replace 
function logProvider(provider) {
    // replace the default console log provider. 
    return require('winston');
}

// verbose replacement 
function logProvider(provider) {
    var logger = new (require('winston').Logger)();

    var myCustomProvider = {
        log: logger.log,
        debug: logger.debug,
        info: logger.info,
        warn: logger.warn,
        error: logger.error
    }
    return myCustomProvider;
}

-(已棄用)option.proxyHost:用option.changeOrigin = true代替。
-(已棄用)option.proxyTable:用option.router代替。

http-proxy 事件

  • option.onError:Function,訂閱http-proxyerror事件以進行自定義錯誤處理。
function onError(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:Function,訂閱http-proxyproxyRes事件。
function onProxyRes(proxyRes, req, res) {
    proxyRes.headers['x-added'] = 'foobar';     // add new header to response 
    delete proxyRes.headers['x-removed'];       // remove header from response 
}
  • option.onProxyReq:Function,訂閱http-proxyproxyReq事件。
function onProxyReq(proxyReq, req, res) {
    // add custom header to request 
    proxyReq.setHeader('x-added', 'foobar');
    // or log the req 
}
  • option.onProxyReqWs:Function,訂閱http-proxyproxyReqWs事件。
function onProxyReqWs(proxyReq, req, socket, options, head) {
    // add custom header 
    proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
}
  • option.onOpen:Function,訂閱http-proxyopen事件。
function onOpen(proxySocket) {
    // listen for messages coming FROM the target here 
    proxySocket.on('data', hybiParseAndLogMessage);
}
  • option.onClose:Function,訂閱http-proxyclose事件。
function onClose(res, socket, head) {
    // view disconnected websocket connections 
    console.log('Client disconnected');
}

http-proxy選項

底層http-proxy庫提供如下選項。

option.target:url 字符串將與url模塊解析
option.forward:url字符串將與url模塊解析
option.target:傳遞給http(s)請求的對象(參閱Node https代理和http代理對象)
option.ssl:傳遞給https.createServer()的對象
option.ws:true / false,若是你想要代理websockets
option.xfwd:true / false,添加x-forward請求頭
option.secure:true / false,若是你想要驗證SSL證書
option.toProxy:true / false,將絕對URL做爲path(對代理使用代理時頗有用)
option.prependPath:true / false,默認:true-指定是否要將目標的路徑預置到代理路徑
option.ignorePath:true / false,默認:false-指定是否要忽略傳入請求的代理路徑(注意:若是須要,您將必須附加/手動)。
option.localAddress:用於傳出鏈接的本地接口字符串
option.changeOrigin:true / false,默認值:false - 將主機頭的源更改成目標URL
option.auth:基本認證,即「用戶:密碼」來計算受權頭。
option.hostRewrite:重寫(301/302/307/308)重定向的位置主機名。
option.autoRewrite:根據請求的主機/端口重寫(301/302/307/308)重定向的位置主機/端口。默認值:false。
option.protocolRewrite:重寫位置協議(301/302/307/308)重定向到’http’或’https’。默認值:null。
option.cookieDomainRewrite:重寫set-cookie標頭的域。可能的值:

  • false(默認):禁止重寫cookie
  • 字符串:新域名,好比說cookieDomainRewrite:"new.domain"。使用cookieDomainRewrite:""刪除域名。
  • 對象:域名到新域名的映射,用」*」匹配全部域名。
    舉個栗子:保持一個域名不變,重寫一個域名而且刪除其餘的:
cookieDomainRewrite: { 
"unchanged.domain": "unchanged.domain", 
"old.domain": "new.domain", 
"*": "" 
}

option.headers:對象,添加請求頭。(好比:{host:'www.example.org'})
option.proxyTimeout:超時時間(毫秒)當代理接收不到目標服務器的返回

速記

當不須要詳細配置時,請使用簡寫語法。當使用速記時,上下文和option.target將被自動配置。若是須要,仍然可使用選項。

proxy('http://www.example.org:8000/api');
// proxy('/api', {target: 'http://www.example.org:8000'}); 


proxy('http://www.example.org:8000/api/books/*/**.json');
// proxy('/api/books/*/**.json', {target: 'http://www.example.org:8000'}); 


proxy('http://www.example.org:8000/api', {changeOrigin:true});
// proxy('/api', {target: 'http://www.example.org:8000', changeOrigin: true});

app.use(path, proxy)

若是要使用服務器的app.usepath參數匹配請求;建立並裝載不帶http-proxy-middleware`上下文參數的代理:

app.use('/api', proxy({target:'http://www.example.org', changeOrigin:true}));

app.use文檔

express: http://expressjs.com/en/4x/api.html#app.use
connect:https://github.com/senchalabs/connect#mount-middleware

Websocket

// verbose api 
proxy('/', {target:'http://echo.websocket.org', ws:true});

// shorthand 
proxy('http://echo.websocket.org', {ws:true});

// shorter shorthand 
proxy('ws://echo.websocket.org');

外部WebSocket升級

在之前的WebSocket示例中,http代理中間件依賴於初始http請求以便偵聽http升級事件。若是須要在沒有初始http請求的狀況下代理WebSockets,則能夠手動預訂服務器的http升級事件。

var wsProxy = proxy('ws://echo.websocket.org', {changeOrigin:true});

var app = express();
    app.use(wsProxy);

var server = app.listen(3000);
    server.on('upgrade', wsProxy.upgrade);  // <-- subscribe to http 'upgrade'
相關文章
相關標籤/搜索