探究http-proxy-middleware源碼

1、http-proxy-middleware 與 node-http-proxy

  • 配置http-proxy-middleware能夠很容易地在connect, express, browser-sync實現http代理node

  • http-proxy-middleware 是基於node-http-proxy實現的中間件git

2、http-proxy-middleware簡單用法

- /api 請求代理到http://www.example.org的例子
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);

3、使用node-http-proxy進行http代理的代碼對比

var express = require('express')
var httpProxy = require('http-proxy')


var options = {target: "http://jsonplaceholder.typicode.com/users",changeOrigin: true};
var httpProxyServer = httpProxy.createProxyServer(options);
function jsonHttpProxy(req, res) {
    httpProxyServer.web(req, res);
}
var app = express()
app.use('/users', jsonHttpProxy)
app.listen(3002)
  • 由上述代碼能夠看出,當要訪問/users時,須要target中對應代理網站中也設置對應的/users路徑github

  • 而在http-proxy-middleware中有一個req.url的設置,能夠根據當前訪問路徑自動映射代理網站相應路徑web

  • httpProxyServer.web()表示代理http或者https常規的代理鏈接,而想要代理websocket的鏈接則須要使用httpProxyServer.ws()方法ajax

4、探究http-proxy-middleware源碼處理過程

4.1. http-proxy-middleware源碼目錄

clipboard.png logger.js和errors.js分別用於輸出日誌和錯誤信息這裏不做分析express

4.2 http-proxy-middleware代理普通請求(http和https)

  • 在indexjs中能看到主入口文件,下面這段省略的源碼能充分反映普通請求代理中http-proxy-middleware和node-http-proxy的關係json

var httpProxy = require('http-proxy')

function HttpProxyMiddleware (context, opts) {
    ……
    return middleware
    
     var proxy = httpProxy.createProxyServer({})
     
     function middleware (req, res, next) {
      ……
      var activeProxyOptions = prepareProxyRequest(req)
      proxy.web(req, res, activeProxyOptions)
      ……
    
      }
}
  • 與三中的代碼比較最主要的區別是對options作了處理,也就是activeProxyOptions = prepareProxyRequest(req),下面分析prepareProxyRequest函數作的處理api

  • 以訪問options = {target: "http://jsonplaceholder.typicode.com",changeOrigin: true}爲例,訪問http://localhost:3000/userswebsocket

function prepareProxyRequest (req) {
    //這一步的處理很是關鍵,能夠將請求路徑對應上代理的路徑
    //若是不設置這一步,那麼代理的路徑就是對應了target不會變化
    req.url = (req.originalUrl || req.url)

    // proxyOptions就是原始的options
    var originalPath = req.url
    var newProxyOptions = _.assign({}, proxyOptions)

    //這裏是處理更多變得路徑代理狀況,下面詳細介紹
    __applyRouter(req, newProxyOptions)
    __applyPathRewrite(req, pathRewriter)

    ……省略logger部分代碼

    return newProxyOptions
  }
  • 從http-proxy-middleware文檔中能夠看到關於router和pathRewriter的舉例用法,處理過程就是對應上面的__applyRouter和__applyRewriter方法app

  • __applyRouter的處理在router.js中,主要處理過程是遍歷options.router,而後和請求的host或者host+path比對是否相符,而後將相對應的值賦予target;若是router是函數則傳入req值,執行函數獲得返回值

  • __applyRewriter的處理在path-rewriter.js中,主要處理過程是遍歷options.pathRewrite,用正則包裝key,對應value,返回一個檢測並改變req.url的函數,以此對應相應的代理網站的路徑

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'
    }

  • config-factory.js用於處理傳入的context和options參數

  • 例如:處理proxy(['/api', '/ajax', '/someotherpath'], {...})的context


  • context-matcher.js用於檢測當proxy中傳入了context參數時與請求路徑的比對

  • 例如: proxy('/api', {...}) - 只能代理請求以/api開頭的請求

4.3 http-proxy-middleware代理websocket請求

  • ws代理的核心處理代碼

// 這裏的debounced起到了節流函數的做用,防止短期內屢次調用處理函數
    var wsUpgradeDebounced = _.debounce(handleUpgrade)
     if (proxyOptions.ws === true) {
      catchUpgradeRequest(req.connection.server)
    }
    
    //監聽upgrade
    function catchUpgradeRequest (server) {
        if (!wsInitialized) {
          server.on('upgrade', wsUpgradeDebounced)
          wsInitialized = true
        }
      }
    
    //真正調用node-http-proxy的ws方法的處理函數
    function handleUpgrade (req, socket, head) {
        wsInitialized = true
    
        if (shouldProxy(config.context, req)) {
          var activeProxyOptions = prepareProxyRequest(req)
          proxy.ws(req, socket, head, activeProxyOptions)
        }
  }

5、總結與思考

  • 研究http-proxy-middleware源碼的初衷是想要知道node是如何作到代理請求的,進行到必定步驟才發現http-proxy-middleware並無作任何這方面的處理,只是封裝了代理的步驟,讓參數更靈活,因此下一步仍是要探究node-http-proxy是如何對請求作處理的

  • 可是經過研究http-proxy-middleware不只對用法更加熟悉,還大概瞭解瞭如何作一個express插件

  • 最後 http-proxy-middleware源碼 https://github.com/chimurai/h...

相關文章
相關標籤/搜索