Node 除了能實現 HTTP Server 外,只要加上 Http-proxy middleware,也能輕易實現 Proxy Server。
Version
Node 12.4
Express 4.17.1
http-proxy-middleware 0.19.1
Add Package
$ yarn add express body-parser http-proxy-middleware
express
:web frameworkbody-parser
:讀取 HTTP POST bodyhttp-proxy-middleware
:負責 proxy
Proxy Server
let express = require ('express');
let bodyParser = require ('body-parser');
let proxy = require ('http-proxy-middleware');
let webServer = express ()
let apiServer = express ()
apiServer.use (bodyParser.urlencoded ({ extended: true }))
apiServer.post ('/users', (req, res) => {
let id = req.body.id
let name = req.body.name
let msg = `${id}: ${name}`
res.send(msg);
})
webServer.use (
'/api',
proxy ({
target: 'http://localhost:3000/',
changeOrigin: true,
pathRewrite: {
'^/api/': '/'
}
})
)
webServer.listen(80, _ => console.log('Web server listening on port 80'))
apiServer.listen(3000, _ => console.log('API server listening on port 3000'))
實務上會使用 proxy,最常見是因為 client 直接打不同 domain 的 API server 導致 CORS。
若 API 我們自己可以掌控,固然可直接改 code 開放 CORS;或者先打到自己的 Web server,再透過 proxy 到 API server 躲過 CORS。
第 5 行
let webServer = express ()
let apiServer = express ()
webServer.listen (80, _ => console.log('Web server listening on port 80'))
apiServer.listen (3000, _ => console.log('API server listening on port 3000'))
分別使用 express
建立兩個 HTTP server:
webServer
:port 為80
。apiServer
:port 為3000
。
Web server 與 API server 雖然同屬相同 host name 與 IP,但因為 port 不同,browser 已經視為 CORS。
第 8 行
apiServer.use (bodyParser.urlencoded ({ extended: true }))
API server 使用 bodyParser
middleware。
第 10 行
apiServer.post ('/users', (req, res) => {
let id = req.body.id
let name = req.body.name
let msg = `${id}: ${name}`
res.send(msg)
})
API server 接受 /users
的 POST request,其 body 為 id
與 name
。
18 行
webServer.use (
'/api',
proxy ({
target: 'http://localhost:3000/',
changeOrigin: true,
pathRewrite: {
'^/api/': '/'
}
})
)
實務上常將原本外部 API 的 URL 改打自己 Web server 的 /api
。
如原本為 http://localhost:3000/users
POST:
改成 http://localhost:80/api/users
POST。
webServer.use('/api', proxy(...));
use
的第一個 argument 為 context matching,只要符合 matching,就會繼續 proxy。
注意並不是如 Vue CLI 3 為 mapping,將稍後設定
proxy({
target: 'http://localhost:3000/',
changeOrigin: true,
pathRewrite: {
'^/api/': '/'
}
})
設定 proxy option:
target
:為 API serverchangeOrigin
:設定true
將 host header 的 origin 改成 target URLpathRewrite
:任何api
開頭的 request 將變成/
Conclusion
- 實務上可將 Vue 包在同一個 Node + Express + Http-proxy 的 Docker image 內,如此不需要 Nginx 也能有 proxy