I'm learning Node.js, and for some reason I need to set up a http.request to another ip, and get the response from it and apply to ctx.body of koa. I wrote the code like this:
var refreshData = async (ctx, next) =>{
var option = {
host: 'xxx.xxx.xxx.xxx',
port: 8080,
path: '/reqPath',
method: 'POST',
headers:{'Content-Type': 'application/json'}
};
var postData = "1";
var resData = '';
var req = http.request(option, function(res){
res.setEncoding('utf8');
res.on('data', function (chunk) {
resData = resData + 'Chunk: ' + chunk;
});
res.on('end', function(){
ctx.res.body = resData;
console.log('ResponseData: ' + ctx.res.body); //shows the correct data
});
});
req.on('error', function(e){
console.log('problem with request: ' + e.message);
});
req.write(postData);
req.end();
};
module.exports = {
'GET /refreshDataGet': refreshData,
};
Learning to use controller mapping and it works, and resData is the correct data. But I can only get 'status 0' when doing the 'GET /refreshDataGet' from the webpage. If I don't do the http.request and directly apply a JSON object to ctx.body, I can get the correct status and data on the webpage. Did I miss something? Or there is a better solution to act this?
Thanks!!
Edit: return 404, if manually set to 200 then find nothing in the response body. But the debug print is correct inside
res.on('end', function(){})
The problem here is the following: within your async
function, you are defining a callback function. This will lead to your 404, because the ascny / await pattern requires promises ... So what you basically have to do is to wrap your http.request
into another funttion which returns a promise. So something like:
// not tested !!
function getHttpRequest() {
let option = {
host: 'xxx.xxx.xxx.xxx',
port: 8080,
path: '/reqPath',
method: 'POST',
headers:{'Content-Type': 'application/json'}
};
return new Promise((resolve, reject) => {
let postData = "1";
let resData = '';
let req = http.request(option, function(res){
res.setEncoding('utf8');
res.on('data', function (chunk) {
resData = resData + 'Chunk: ' + chunk;
});
res.on('end', function(){
resolve(resData)
});
});
})
}
Then in your refreshData
async function you are awaiting the resolving promise like:
ctx.body = await getHttpRequest():
Hope that helps ...