[英]Proxy with express.js
為了避免同域 AJAX 問題,我希望我的 node.js Web 服務器將來自 URL /api/BLABLA
所有請求/api/BLABLA
到另一台服務器,例如other_domain.com:3000/BLABLA
,並返回給用戶與此遠程服務器相同的內容服務器返回,透明。
所有其他 URL(除了/api/*
)將直接提供,沒有代理。
我如何使用 node.js + express.js 實現這一點? 能舉個簡單的代碼例子嗎?
(web 服務器和遠程3000
服務器都在我的控制之下,都運行 node.js 和 express.js)
到目前為止,我找到了這個https://github.com/http-party/node-http-proxy ,但閱讀那里的文檔並沒有讓我更明智。 我結束了
var proxy = new httpProxy.RoutingProxy();
app.all("/api/*", function(req, res) {
console.log("old request url " + req.url)
req.url = '/' + req.url.split('/').slice(2).join('/'); // remove the '/api' part
console.log("new request url " + req.url)
proxy.proxyRequest(req, res, {
host: "other_domain.com",
port: 3000
});
});
但是沒有任何東西返回到原始 Web 服務器(或最終用戶),所以沒有運氣。
我找到了一個更短且非常簡單的解決方案,它可以無縫工作,並且還可以使用express-http-proxy
進行身份驗證:
const url = require('url');
const proxy = require('express-http-proxy');
// New hostname+path as specified by question:
const apiProxy = proxy('other_domain.com:3000/BLABLA', {
proxyReqPathResolver: req => url.parse(req.baseUrl).path
});
然后簡單地:
app.use('/api/*', apiProxy);
注:如由@MaxPRafferty提到的,使用req.originalUrl
代替baseUrl
保存查詢字符串:
forwardPath: req => url.parse(req.baseUrl).path
更新:正如 Andrew 所提到的(謝謝!),有一個使用相同原理的現成解決方案:
npm i --save http-proxy-middleware
進而:
const proxy = require('http-proxy-middleware')
var apiProxy = proxy('/api', {target: 'http://www.example.org/api'});
app.use(apiProxy)
文檔: Github 上的 http-proxy-middleware
我知道我加入這個聚會遲到了,但我希望這對某人有所幫助。
您想使用http.request
創建對遠程 API 的類似請求並返回其響應。
像這樣的東西:
const http = require('http');
// or use import http from 'http';
/* your app config here */
app.post('/api/BLABLA', (oreq, ores) => {
const options = {
// host to forward to
host: 'www.google.com',
// port to forward to
port: 80,
// path to forward to
path: '/api/BLABLA',
// request method
method: 'POST',
// headers to send
headers: oreq.headers,
};
const creq = http
.request(options, pres => {
// set encoding
pres.setEncoding('utf8');
// set http status code based on proxied response
ores.writeHead(pres.statusCode);
// wait for data
pres.on('data', chunk => {
ores.write(chunk);
});
pres.on('close', () => {
// closed, let's end client request as well
ores.end();
});
pres.on('end', () => {
// finished, let's finish client request as well
ores.end();
});
})
.on('error', e => {
// we got an error
console.log(e.message);
try {
// attempt to set error message and http status
ores.writeHead(500);
ores.write(e.message);
} catch (e) {
// ignore
}
ores.end();
});
creq.end();
});
注意:我還沒有真正嘗試過上面的方法,所以它可能包含解析錯誤,希望這會給你一個關於如何讓它工作的提示。
擴展trigoman的答案(他的全部學分)以使用 POST (也可以使用 PUT 等):
app.use('/api', function(req, res) {
var url = 'YOUR_API_BASE_URL'+ req.url;
var r = null;
if(req.method === 'POST') {
r = request.post({uri: url, json: req.body});
} else {
r = request(url);
}
req.pipe(r).pipe(res);
});
我使用以下設置將/rest
上的所有內容定向到我的后端服務器(端口 8080),並將所有其他請求定向到前端服務器(端口 3001 上的 webpack 服務器)。 它支持所有 HTTP 方法,不會丟失任何請求元信息並支持 websockets(我需要熱重載)
var express = require('express');
var app = express();
var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();
var backend = 'http://localhost:8080',
frontend = 'http://localhost:3001';
app.all("/rest/*", function(req, res) {
apiProxy.web(req, res, {target: backend});
});
app.all("/*", function(req, res) {
apiProxy.web(req, res, {target: frontend});
});
var server = require('http').createServer(app);
server.on('upgrade', function (req, socket, head) {
apiProxy.ws(req, socket, head, {target: frontend});
});
server.listen(3000);
首先安裝 express 和 http-proxy-middleware
npm install express http-proxy-middleware --save
然后在你的 server.js
const express = require('express');
const proxy = require('http-proxy-middleware');
const app = express();
app.use(express.static('client'));
// Add middleware for http proxying
const apiProxy = proxy('/api', { target: 'http://localhost:8080' });
app.use('/api', apiProxy);
// Render your site
const renderIndex = (req, res) => {
res.sendFile(path.resolve(__dirname, 'client/index.html'));
}
app.get('/*', renderIndex);
app.listen(3000, () => {
console.log('Listening on: http://localhost:3000');
});
在這個例子中,我們在端口 3000 上為站點提供服務,但是當請求以 /api 結束時,我們將其重定向到 localhost:8080。
http://localhost:3000/api/login重定向到http://localhost:8080/api/login
好的,這是使用 require('request') npm 模塊和環境變量 * 而不是硬編碼代理的准備復制粘貼答案:
咖啡腳本
app.use (req, res, next) ->
r = false
method = req.method.toLowerCase().replace(/delete/, 'del')
switch method
when 'get', 'post', 'del', 'put'
r = request[method](
uri: process.env.PROXY_URL + req.url
json: req.body)
else
return res.send('invalid method')
req.pipe(r).pipe res
javascript:
app.use(function(req, res, next) {
var method, r;
method = req.method.toLowerCase().replace(/delete/,"del");
switch (method) {
case "get":
case "post":
case "del":
case "put":
r = request[method]({
uri: process.env.PROXY_URL + req.url,
json: req.body
});
break;
default:
return res.send("invalid method");
}
return req.pipe(r).pipe(res);
});
我找到了一個更短的解決方案,它完全符合我的要求https://github.com/http-party/node-http-proxy
安裝http-proxy
npm install http-proxy --save
在你的 server/index/app.js 中像下面一樣使用它
var proxyServer = require('http-route-proxy');
app.use('/api/BLABLA/', proxyServer.connect({
to: 'other_domain.com:3000/BLABLA',
https: true,
route: ['/']
}));
我真的花了幾天時間到處尋找以避免這個問題,嘗試了很多解決方案,但沒有一個有效,只有這個。
希望它也能幫助別人:)
我認為你應該使用cors npm
const app = express();
const cors = require('cors');
var corsOptions = {
origin: 'http://localhost:3000',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.use(cors(corsOptions));
我沒有快遞樣本,但有一個帶有普通http-proxy
包的樣本。 我在博客中使用的代理的精簡版。
簡而言之,所有 nodejs http 代理包都在 http 協議級別工作,而不是 tcp(socket) 級別。 這也適用於 express 和所有 express 中間件。 它們都不能做透明代理,也不能做 NAT,這意味着將傳入流量源 IP 保留在發送到后端 Web 服務器的數據包中。
但是,Web 服務器可以從 http x 轉發的標頭中獲取原始 IP 並將其添加到日志中。
該xfwd: true
在proxyOption
啟用X轉發頭功能http-proxy
。
const url = require('url');
const proxy = require('http-proxy');
proxyConfig = {
httpPort: 8888,
proxyOptions: {
target: {
host: 'example.com',
port: 80
},
xfwd: true // <--- This is what you are looking for.
}
};
function startProxy() {
proxy
.createServer(proxyConfig.proxyOptions)
.listen(proxyConfig.httpPort, '0.0.0.0');
}
startProxy();
X-Forwarded 標頭參考: https : //en.wikipedia.org/wiki/X-Forwarded-For
我的代理的完整版本: https : //github.com/J-Siu/ghost-https-nodejs-proxy
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.