同じドメインAJAXの問題を回避するには、node.js WebサーバーがすべてのリクエストをURL /api/BLABLA
から別のサーバー、たとえばother_domain.com:3000/BLABLA
に転送し、このリモートサーバーが返したものと同じものをユーザーに返します。透過的に。
他のすべてのURL(/api/*
以外)は、プロキシなしで直接提供されます。
Node.js + express.jsでこれを達成するにはどうすればよいですか?簡単なコード例を教えていただけますか?
(Webサーバーとリモート3000
サーバーの両方が私の制御下にあり、どちらもnode.jsとexpress.jsを実行しています)
これまでのところ、私はこれを見つけました https://github.com/nodejitsu/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サーバー(またはエンドユーザー)には何も返されないため、運はありません。
http.request
を使用して、リモートAPIへの同様のリクエストを作成し、そのレスポンスを返します。
このようなもの:
var http = require('http');
/* your app config here */
app.post('/api/BLABLA', function(req, res) {
var 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: req.headers
};
var creq = http.request(options, function(cres) {
// set encoding
cres.setEncoding('utf8');
// wait for data
cres.on('data', function(chunk){
res.write(chunk);
});
cres.on('close', function(){
// closed, let's end client request as well
res.writeHead(cres.statusCode);
res.end();
});
cres.on('end', function(){
// finished, let's finish client request as well
res.writeHead(cres.statusCode);
res.end();
});
}).on('error', function(e) {
// we got an error, return 500 error to client and log error
console.log(e.message);
res.writeHead(500);
res.end();
});
creq.end();
});
注意:上記は実際には試していません。そのため、解析エラーが含まれている可能性があります。
私は似たようなことをしましたが、代わりに request を使用しました:
var request = require('request');
app.get('/', function(req,res) {
//modify the url in any way you want
var newurl = 'http://google.com/';
request(newurl).pipe(res);
});
これが役立つことを願っています。
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', {
forwardPath: req => url.parse(req.baseUrl).path
});
そして単純に:
app.use('/api/*', apiProxy);
注:@MaxPRaffertyで述べたように、baseUrl
の代わりにreq.originalUrl
を使用して、クエリ文字列を保持します。
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
私はこのパーティーに遅刻することは知っていますが、これが誰かの助けになることを願っています。
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メソッドをサポートし、リクエストメタ情報を失わず、websocket(ホットリロードに必要)をサポートします。
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
OK、ハードコードされたプロキシの代わりに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/koppelaar/auth-proxy
私が望むものを正確に実行するより短いソリューションを見つけました https://github.com/nodejitsu/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: ['/']
}));
私は本当にこの問題を回避するためにあらゆる場所を探して何日も費やし、多くの解決策を試みましたが、どれも機能しませんでした。
それが他の誰かにも役立つことを願っています:)
エクスプレスサンプルはありませんが、プレーンhttp-proxy
パッケージが含まれています。ブログに使用したプロキシの非常にストリップダウンされたバージョン。
つまり、すべてのnodejs httpプロキシパッケージは、tcp(socket)レベルではなく、httpプロトコルレベルで動作します。これは、エクスプレスおよびすべてのエクスプレスミドルウェアにも当てはまります。いずれも透過プロキシもNATも実行できません。つまり、バックエンドWebサーバーに送信されるパケットに着信トラフィックの送信元IPを保持します。
ただし、Webサーバーはhttp x-forwardedヘッダーから元のIPを取得してログに追加できます。
proxyOption
のxfwd: true
は、http-proxy
のx-forwardヘッダー機能を有効にします。
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