可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to set up proxy for some XYZ server whose i am not the admin.
Then i want to do some analysis over the request and response headers then also over request and response bodies.
So i am using http-proxy https://github.com/nodejitsu/node-http-proxy
this is what i am doing :
var proxy = httpProxy.createProxyServer();
connect.createServer(
connect.bodyParser(),
require('connect-restreamer')(),
function (req, res) {
proxy.web(req, res, { target : 'XYZserver' });
}
).listen(config.listenPort);
Upto GET request everything is fine but whenever a request with some body like POST, PATCH, PUT etc request are made i get the error :
Error: socket hang up
at createHangUpError (http.js:1472:15)
at Socket.socketCloseListener (http.js:1522:23)
at Socket.EventEmitter.emit (events.js:95:17)
at TCP.close (net.js:466:12)
I google a lot but found no clue whats wrong going on.
I enable socket proxy with 'ws:true' option of 'proxy.web' but still the same error.
回答1:
I had a similar issue and resolved it by moving my proxy code above other node middleware.
e.g. This:
var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();
app.use("/someroute", function(req, res) {
apiProxy.web(req, res, { target: 'http://someurl.com'})
});
app.use(someMiddleware);
not this:
app.use(someMiddleware);
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer();
app.use("/someroute", function(req, res) {
proxy.web(req, res, { target: 'http://someurl.com'})
});
My specific issue was having BodyParser middleware above the proxy. I haven't done much digging but it must have modified the request in some way that broke the proxy library when the request finally came to it.
回答2:
Just for sake of completeness, there is really an integration problem between modules body-parser
and http-proxy
, as stated in this thread.
If you can't change the order of the middleware; You can restream the parsed body before proxying the request.
// restream parsed body before proxying
proxy.on('proxyReq', function(proxyReq, req, res, options) {
if (req.body) {
let bodyData = JSON.stringify(req.body);
// incase if content-type is application/x-www-form-urlencoded -> we need to change to application/json
proxyReq.setHeader('Content-Type','application/json');
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
// stream the content
proxyReq.write(bodyData);
}
}
I've lost 2 days on this f***** problem. Hope it helps!
回答3:
Need catching proxy's errors:
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({ target: argv.proxy_url })
proxy.on('error', function(err, req, res) {
res.end();
})
回答4:
It seems that http-proxy
is not compatible with body-parser
middleware.
You may want to move the http-proxy
middleware before body-parser
or stop using body-parser
.
See also:
Socket hangup while posting request to Node-http-proxy Node.js
回答5:
After wasting more than a day and following some posts in nodejitsu/node-http-proxy issues I was able to make it working thanks to riccardo.cardin.
I've decided to post full example to save you time.
The below example uses server express, body-parser (req.body middleware) and ofcourse http-proxy to proxy and forward request to 3rd party server.
const webapitargetUrl = 'https://posttestserver.com/post.php';
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json()); // support json encoded bodies
var https = require('https');
var stamproxy = httpProxy.createProxyServer({
target: 'https://localhost:8888',
changeOrigin: true,
agent : https.globalAgent,
toProxy : true,
secure: false,
headers: {
'Content-Type': 'application/json'
}
});
stamproxy.on('proxyReq', function(proxyReq, req, res, options) {
console.log("proxying for",req.url);
if (req.body) {
console.log("prxyReq req.body: ",req.body);
// modify the request. Here i just by removed ip field from the request you can alter body as you want
delete req.body.ip;
let bodyData = JSON.stringify(req.body);
// in case if content-type is application/x-www-form-urlencoded -> we need to change to application/json
proxyReq.setHeader('Content-Type','application/json');
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
// stream the content
console.log("prxyReq bodyData: ",bodyData);
proxyReq.write(bodyData);
}
console.log('proxy request forwarded succesfully');
});
stamproxy.on('proxyRes', function(proxyRes, req, res){
proxyRes.on('data' , function(dataBuffer){
var data = dataBuffer.toString('utf8');
console.log("This is the data from target server : "+ data);
});
});
app.use(compression());
app.use(favicon(path.join(__dirname, '..', 'static', 'favicon.ico')));
app.use(Express.static(path.join(__dirname, '..', 'static')));
var sessions = require("client-sessions");
app.use(sessions({
secret: 'blargadeeblargblarg',
cookieName: 'mysession'
}));
app.use('/server/setserverip', (req, res) => {
console.log('------------ Server.js /server/setserverip ---------------------------------');
req.mysession.serverip += 1;
console.log('session data:');
console.log(req.mysession.serverip)
console.log('req.body:');
console.log(req.body);
// Proxy forwarding
stamproxy.web(req, res, {target: webapitargetUrl});
console.log('After calling proxy serverip');
});