Open tamilvjm opened 7 years ago
It's not responding while forwarding put request
The problem seems like a stream "issue". Are you using something before sending the proxy request?
For example:
http.createServer((req, res) => {
anyBody(req, res, { limit: process.env.MAX_BODY_SIZE || '2mb' }, (err, body) => {
req.body = body;
proxy.web(req, res, { secure: false, proxyTimeout: process.env.TIMEOUT || 8000, xfwd: true, toProxy: true, changeOrigin: true});
});
}).listen(1234);
That works like a charm for NON BODY requests, like GET, HEAD or DELETE. But POST, for example, has lost its data stream before sending to proxy.web. The upstream server will get the data, but no response will be received.
worked after:
proxy.on('proxyReq', (proxyReq, req) => {
if (req.body) {
const 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);
}
});
when I use proxyReq.write(bodyData), it call like this: throw new Error('Can\'t set headers after they are sent.'); How can I fix it?
I hit the same bug. @zanaca solution seems to work ;)
I have hit the same bug. However, I had to modify @zanaca's solution to get it to work in all the situations that I was encountering:
proxy.on('proxyReq', (proxyReq, req) => {
if (req.body && req.complete) {
const bodyData = JSON.stringify(req.body);
proxyReq.setHeader('Content-Type', 'application/json');
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
proxyReq.write(bodyData);
}
});
Just a head's up if you hit this problem.
My target server is Tomcat Server for Java. The page post the JSON data through ajax and I use request.getParameter("data") to get my posted data in Java. And then I try @zanaca ‘s method, but it doesn't work. On Java Server, I tried to output the request inputstream for this post action without http-proxy. I saw the correct output was
data=%7B%22%E8%B4%A7%E5%B8%81%E5%9E%8B%22%3A%7B%22wealth%22%3A10000%2C%22url
And I tried to output the request inputstream for this post action with @zanaca ‘s method. I saw the wrong output was
{"data":"{\"璐у竵鍨媆":{\"wealth\":10000,\"url\":\"r
I can't modify my Java code, so if I want to use the request.getParameter("data") to get the data in Java, I must joint the String for inputstream to match Java's need. So I rewrote the method. Maybe someone need this code for Java back-end server:
proxy.on('proxyReq', function (proxyReq, req, res, options) {
if (req.body) {
// var bodyData = encodeURIComponent(JSON.stringify(req.body))
var postStr = "";
for(var key in req.body){
postStr = postStr + encodeURIComponent(key) + "=" + encodeURIComponent(req.body[key]) + "&";
}
postStr = postStr.substr(0, postStr.length - 1);
for(var key in req.headers){
proxyReq.setHeader(key, req.headers[key])
}
// 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(postStr))
// stream the content
proxyReq.write(postStr)
}
})
Because there are non-English language in my post data, So I should use encodeURIComponent() to encode the data.
It seems that I hit the same bug. I used to http-proxy to build a mock server. and I want to conditional proxy the request based on the req body. It works for the GET method, but it just hangs for the PUT method. My code looks like the following:
let server = http.createServer(function(req, res){
let body = [];
req.on('error', (err) => {
console.error(err);
}).on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
body = queryString.parse(body);
if(bodyMeetRequirement(body)){
console.log('return MockData');
returnMockData(mockData, res);
}else{
proxy.on('error', function (err, req, res){
console.log('Both Remote Server and MockData are not available');
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Both Remote Server and MockData are not available');
});
}
proxy.web(req, res, {target: server_url});
});
}).listen(server_port);
Can somebody help me, I have been struggling in the problem for like 3 days and could not figure out why.
The problem seems like a stream "issue". Are you using something before sending the proxy request?
For example:
http.createServer((req, res) => { anyBody(req, res, { limit: process.env.MAX_BODY_SIZE || '2mb' }, (err, body) => { req.body = body; proxy.web(req, res, { secure: false, proxyTimeout: process.env.TIMEOUT || 8000, xfwd: true, toProxy: true, changeOrigin: true}); }); }).listen(1234);
That works like a charm for NON BODY requests, like GET, HEAD or DELETE. But POST, for example, has lost its data stream before sending to proxy.web. The upstream server will get the data, but no response will be received.
UPDATE
worked after:
proxy.on('proxyReq', (proxyReq, req) => { if (req.body) { const 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); } });
Thanks @zanaca ! This solution worked for me.
Cannot forward Post and PUT request using proxy.web method. can you help me how to fix this issue