Express代理中間件問題與解決方案

前後端分離應用的架構

在前後端分離架構中,爲了避免跨域以及暴露內部服務地址。一般來說,我會在Express這層中加入一個反向代理。

所有向後端服務訪問的請求,都通過代理轉發到內部的各個服務。

這個反向代理服務器,做起來很簡單。用http-proxy-middleware這個模塊,幾行代碼就可以搞定。

// app.js
Object.keys(proxyTable).forEach(function (context) {
  app.use(proxyMiddleware(context, proxyTable[context]))
})

http-proxy-middleware實際上是對於node-http-proxy的更加簡便的封裝。node-http-proxy是http-proxy-middleware的底層包,如果node-http-proxy有問題,那麼這個問題就會影響到http-proxy-middleware這個包。

最近的bug

http-proxy-middleware最近有個問題,請求體在被代理轉發前,如果請求體被解析了。那麼後端服務將會收不到請求結束的消息,從瀏覽器的網絡面板可以看出,一個請求一直在pending狀態。

Cannot proxy after parsing body #299, 實際上這個問題在node-http-proxy也被提出過,而且處於open狀態。POST fails/hangs examples to restream also not working #1279

目前這個bug還是處於open狀態,但是還是有解決方案的。就是將請求體解析的中間件掛載在代理之後

下面的代碼,express.json()會對json格式的請求體進行解析。方案1在代理前就進行body解析,所有格式是json的請求體都會被解析。

但是有些走代理的請求,如果我們並不關心請求體的內容是什麼,實際上我們可以不解析那些走代理的請求。所以,可以先掛載代理中間件,然後掛載請求體解析中間件,最後掛載內部的一些接口服務。

// 方案1 bad
app.use(express.json())
Object.keys(proxyTable).forEach(function (context) {
  app.use(proxyMiddleware(context, proxyTable[context]))
})
app.use('/api', (req, res, next)=> {

})

// 方案2 good
Object.keys(proxyTable).forEach(function (context) {
  app.use(proxyMiddleware(context, proxyTable[context]))
})
app.use(express.json())
app.use('/api', (req, res, next)=> {

})

總結

經過這個問題,我對Express中間件的掛載順序有了更加深刻的認識。

同時,在使用第三方包的過程中,如果該包bug,那麼也需要自行找出合適的解決方案。而這個能力,往往就是高手與新手的區別。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章