我正在使用node-http-proxy作为中间件。处理GET
请求时可以。对于具有JSON正文的POST
请求,我无法发送application/json
标题和json编码的正文。
这是我的中间件。我已经按照建议添加了reastream选项,但这似乎无法解决问题:
//restream parsed body before proxying
proxy.on('proxyReq', function (proxyReq, req, res, options) {
if (!req.body || !Object.keys(req.body).length) {
return;
}
var contentType = proxyReq.getHeader('Content-Type');
var bodyData;
if (contentType === 'application/json') {
bodyData = JSON.stringify(req.body);
}
if (contentType === 'application/x-www-form-urlencoded') {
bodyData = queryString.stringify(req.body);
}
if (bodyData) {
console.log("------", bodyData);
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
proxyReq.write(bodyData);
}
});
proxy.on('proxyRes', function (proxyRes, req, res) {
modifyResponse(res, proxyRes, function (response) {
if (!MXMUtil.empty(response) && !MXMUtil.empty(response.message) && !MXMUtil.empty(response.message.body)) { // valid response
if (!MXMUtil.empty(response.message.body.error)) { // error response
var message = self.processor.createErrorMessage(500, '', response.message.body.error);
response = message;
} else { // valid response
var message = self.processor.prepareResponse(req_start, response.message.body);
response = message;
}
}
return response; // return value can be a promise
});
});
proxy.on('error', function (error, req, res) {
var errorMessage = self.processor.createErrorMessage(500, '', error.message);
res.send(errorMessage);
res.end();
});
proxy.web(req, res, {
// url string to be parsed with the url module
target: target_uri,
// true/false, Default: false - changes the origin of the host header to the target URL
changeOrigin: true,
// true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request
ignorePath: true
});
在后端,我收到此错误:
Malformed HTTP message from 172.17.0.1: Malformed HTTP headers: '\r\n0\r\n\r\n'
第二个请求也将失败,并在中间件上出现Can't set headers after they are sent.
错误:
[Tue Sep 25 2018 18:16:29 GMT+0200 (CEST)] trapped error code: message:Can't set headers after they are sent. stack:Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ClientRequest.setHeader (_http_outgoing.js:498:3)
at ProxyServer.<anonymous> (/webservice/lib/api.js:616:34)
at ProxyServer.emit (/webservice/node_modules/eventemitter3/index.js:210:27)
at ClientRequest.<anonymous> (/webservice/node_modules/http-proxy/lib/http-proxy/passes/web-incoming.js:132:27)
at emitOne (events.js:121:20)
at ClientRequest.emit (events.js:211:7)
at tickOnSocket (_http_client.js:652:7)
at onSocketNT (_http_client.js:668:5)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickDomainCallback (internal/process/next_tick.js:218:9):
在中间件初始化之前,我正在使用主体解析器:
// express app
this.app = express();
// development || production
this.app.set('env', env);
// custom logging: only error codes
this.app.use(morgan('combined', {
skip: function (req, res) {
return res.statusCode < 400;
}
}));
// LP: handle Error: request entity too large
this.app.use(bodyParser.json({limit: '50mb'}));
this.app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
this.app.use(cookieParser());
this.app.use(compression()); // gzip compression
注意。 这可能是一个错误,并且我已经打开了一个问题here,但是应该有替代方法。另一个关联的问题是here。
通过curl -d {...}
向tornado
后端提出的请求将正常工作。
[更新]
我已解决Can't set headers after they are sent.
问题,在写入数据后关闭了请求:
proxyReq.write(bodyData);
proxyReq.end();
我已经尝试过将建议bodyParser
放在代理使用之后的建议解决方案,但是我无法在体系结构中执行此操作,这意味着在我的情况下,顺序如下:
httpProxy = require('http-proxy'),
proxy = httpProxy.createProxyServer({});
// custom logging: only error codes
this.app.use(morgan('combined', {
skip: function (req, res) {
return res.statusCode < 400;
}
}));
// LP: handle Error: request entity too large
this.app.use(bodyParser.json({ limit: '50mb' }));
this.app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
this.app.use(cookieParser());
this.app.use(compression()); // gzip compression
//...api routes...
this.app.post(self._options.baseUrl.uri, function (req, res) {
var req_start = new Date().getTime();
var target_uri = self._options.proxy.uri;
//restream parsed body before proxying
proxy.on('proxyReq', function (proxyReq, req, res, options) {
if (!req.body || !Object.keys(req.body).length) {
return;
}
var bodyData = JSON.stringify(req.body);
proxyReq.setHeader('Content-Type', 'application/json');
proxyReq.write(bodyData);
proxyReq.end();
});
proxy.on('proxyRes', function (proxyRes, req, res) {
modifyResponse(res, proxyRes, function (response) {
console.log("--response--->", response)
if (!MXMUtil.empty(response) && !MXMUtil.empty(response.message) && !MXMUtil.empty(response.message.body)) { // valid response
if (!MXMUtil.empty(response.message.body.error)) { // error response
var message = self.processor.createErrorMessage(500, '', response.message.body.error);
response = message;
} else { // valid response
var message = self.processor.prepareResponse(req_start, response.message.body);
response = message;
}
}
return response; // return value can be a promise
});
});
proxy.on('error', function (error, req, res) {
var errorMessage = self.processor.createErrorMessage(500, '', error.message);
res.send(errorMessage);
res.end();
});
proxy.web(req, res, {
// url string to be parsed with the url module
target: target_uri,
// true/false, Default: false - changes the origin of the host header to the target URL
changeOrigin: true,
// true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request
ignorePath: true
});
});
正如下面的评论中所注意到的,与上述代码一样,代理请求被发送了两次,因此我看到两次登录proxyReq
和proxyRes
事件。