NodeJS http-proxy error response.end() not working - node.js

Here's the code:
proxy.web(
req,
res,
{ changeOrigin: false, target: 'http://' + gotDomain.ip + ':' + gotDomain.port },
function (error, req, res) => {
console.log('Error')
res.end('Error')
}
)
If I stop the target server, the console log fires.
The response res.end('Error') does not work.
The request just hangs on the client side. I can run any code I want in the error callback and I can see the res variable is an http response object. I've tried adding:
res.writeHead(500, {
'Content-Type': 'text/plain'
});
I've tried using the proxy.on('error'... setup and the results are exactly the same:
The callback runs
The res variable is a valid http response object
Whatever I put in res.end() doesn't get sent to the client
The client hangs forever waiting for a response.
I've checked this answer:
Node.js http-proxy: Error response not sent to client
I'm not sure how that solution could work because my proxy response doesn't have status() or send() methods. I get TypeError: res.status is not a function if I try those.
With http-proxy, I use end() whenever I'm returning a response.

Related

Problem with redirect using 'fetch' from frontend page

I am using the following JS in a webpage to send information to a Node.js server upon 'clicking' on an image in the webpage, I am having trouble with the 'redirect' once the 'fetch' is executed:
fetch('/members/pages/callup', {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({name: splits[1], presence: available, str: 'Some string: &=&'})
})
.then(function(res) {res.json()})
.then(function(res) {
if(res.response) {
redirect: window.location.replace("/members/pages/" + splits[1]);
} else {
alert("Error in the response");
}
})
.catch(function(err) {
alert("Error in the fetch call..." + err);
})
The fetch seems to properly send the 'body' data to the server. However I am getting the following error: "Error in the fetch call...TypeError: Cannot read property 'response' of undefined"...
The server performs a database call using the information sent by the frontend, and I thought all I needed to do was to send a "200 (OK)" response back...here is the server code:
app.post('/member/pages/callup', jsonParser, function (req, res) {
console.log("I RECEIVED FROM CLIENT THE FOLLOWING:");
console.log(req.body); //works fine, prints output from frontend 'fetch' to console...
db.lookupMember(req.body.name)
.then(function(foundUser) {
console.log('Async success!', foundUser); //works fine, prints database info to console...
if (typeof foundUser != "undefined") {
res.sendStatus(200); //trying this to 'reply' back to 'fetch' in frontend...is this not correct?
} //'foundUser' is NOT'undefined'...
})
.catch(function(error) {
console.log('UNABLE TO RETRIEVE MEMBER INFORMATION FROM THE DATABASE...' + error);
res.redirect('/'); //route to splash page...
});
})
Any suggestions appreciated, this has gone from a minor irritant to a major problem. I thank you in advance.
There are few issues in the code. If fixed, code should work fine.
You forgot to return res.json() from the function at one place. Make it return res.json() and it will work fine (Inside fetch, 1st then). Due to not returning, res is undefined which is giving the error
You are trying to use res.response but res is not send as a proper json from node server. This will fail at res.json(). You should be doing something like res.send({response: true})
After the if loop in server there is syntax error. It needs to be redirect = instead of redirect:. Also redirect is not declared anywhere which. (Note: you might not need redirect variable here, simply window.lo... should also work)
Note: Have updated the original answer after having the discussion with OP

HTTP request issue Internal Server error

I am having issues with an HTTP response giving me a status code: 502, and error message: Internal Server Error. My setup is an AWS Lambda written in NodeJS making an HTTPS POST request to an AWS API Gateway integrated with another Lambda, as its backend.
The strange part is the Lambda acting as the backend of the API receives all the POST requests just fine and is able to execute its functions perfectly, but its callback responds to the other Lambda with an error.
Below is the callback on the lambda on the API Gateway side
const done = (err, res) => callback(err, {
statusCode: err ? JSON.stringify(err.code) : '200',
body: err ? JSON.stringify(err.message) : JSON.stringify(res),
headers: {
'Content-Type': 'application/json',
}
});
And here is the code from the other lambda making an https POST request
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
res.on('end', function () {
console.log(JSON.stringify(body));
});
});
req.on('error', (e) => {
console.error(e);
console.log("request error");
});
req.write(JSON.stringify(payload));
console.log("req.end");
req.end();
I feel the problem is in these blocks of code because if I change the callback of the Lambda integrated API Gateway to hardcode the response to a 200 status code, then everything works fine.
Problem I see with your code is, if err.code is empty or invalid value, then you will get 502 on API Gateway. You need to fix the code so that it sends back a valid http response with a valid status code.
If your status code is invalid or empty then it will throw a 502 to the caller since the http response from lambda is invalid.
Hope it helps.
Problem is fixed now. No code changes were necessary but the problem was that the Lambda's Node.Js source files on the API Gateway side needed to be zipped with the necessary dependencies or node_modules as explained here http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html
I was facing a similar problem of getting Internal server error while calling external API from lambda function.
Earlier time out for lambda function was 6sec and I increased to some 25sec. After that everything works fine.
Nodejs is asynchronous before getting API response next lines were executing irrespective of using async await.

node/ loopback logging all response body

in server.js file i have added the below code from ref. it gives me req.body as expected. but is it possible to log the response.body as well? how.
i tried to print the res.body it gives me long object of response but not actual response body.
app.middleware('initial', function logResponse(req, res, next) {
// install a listener for when the response is finished
res.on('finish', function() {
// the request was handled, print the log entry
console.log(res.body, req.originalUrl, res.statusCode);
});
// resume the routing pipeline,
// let other middleware to actually handle the request
next();
});
A bit late: Although Loopback uses express this is a loopback specific question, so not a duplicate. You need to access the current context not the response obj, the context will have the response obj. A workaround is logging using a hook "afterRemote(**..." or enable enableHttpContext for middleware in config.json
"remoting": {
"context": {
"enableHttpContext": true
}

Redirect to external URL

I am using AngularJs with NodeJs.
I have a scenario when upon a successful HTTP POST request, I need to redirect the user.
In the client through AngularJS, I make a HTTP POST request to a route:
$http.post('/aPath', data)
.success(function (result) {
//Handle success
})
.error(function (err) {
//Handle error
});
This route is handled within NodeJs that then does the actual POST. Upon success, within the route handler, I redirect:
function handlePostRequest (req, res) {
//Route handler
//HTTP POST Request
//Following code called when POST request is successful
if (result) {
//Successful post
res.redirect("http://www.google.com");
}
}
However, the browser does not navigate to google. Instead, in the error handler of the POST request within the AngularJS client, the control is reached.
I checked the server and find that the POST request is returned as status code 302 and thus is picked by the error handler for the POST request in the client.
I cannot figure out why, when the server successfully executes the redirect code, the control still reaches the client and that too the error handler. How do I redirect successfully?
Is it a HTTP POST in angular or an XHR? If it's an XHR you can't redirect the client from serverside, you'd need to send back an error which you then handle in your clientside script such as:
$http({
method: 'POST',
url: 'yoururl',
}).success(function(data, status, headers, config) {
// success stuff
}).error(function(data, status, headers, config) {
if (status == 302) {
window.location = headers('Location');
}
})
Successful XHRs come back with a status of 200. Your server handing back a 302 is technically correct, but it isn't what $http in Angular is expecting. If your server can hand you a 200, you can then do your redirect in the .success function of the $http request.

jquery ajax success event handler not getting called

Node.js (express) web server
Request handler in web server
app.get('/documents/ajax/:id.:format?', function(req, res) {
console.log ('Request Received');
var body = 'hello world';
res.writeHead(200, {
'Content-Length': body.length,
'Content-Type': 'text/plain'
});
})
ajax request from client side javascript
$.ajax({
url : "/documents/ajax/" + item,
success : function(msg) {
alert ("success" + msg);
},
error : function(request, status, error) {
alert("Error, returned: " + request);
alert("Error, returned: " + status);
alert("Error, returned: " + error);
}
});
I am able to receive the request on server side and I send 4 requests
But my success event is not getting called in client side JS. Also, when I stop my web server, then I see my error handlers get called.
Please help.
The main issue is that you are not ending the response so the server never actually sends anything to the client. The server should respond with something like a file, a redirect, some text, etc. You need to finish the callback with a res.end, res.send, res.sendfile, res.redirect, res.render... See the docs.
Furthermore, with express you want to use res.set to set the http headers:
app.get('/documents/ajax/:id.:format?', function(req, res) {
console.log ('Request Received');
var body = 'hello world';
res.set({'Content-Type': 'text/plain'});
res.send(body);
});
200 is the default response code, so you don't need to specify that and the length will be computed for you. These things are often easier to debug from the command line via curl:
curl http://localhost:3000/documents/ajax/1
and
curl -I http://localhost:3000/documents/ajax/1
I had to res.end in server request handler. After that I was able to generate success event in client side JS

Resources