Express server Error 400 is not returning json message - node.js

I am submitting a form and if the form id already exists in the database, I am returning status 400 with a message saying that the form exists.
res.status(400).send({
status: 400,
message: "Form exists"
})
When I read the response sent back from my express server, I am getting Bad request message instead of the custom message object that I am returning. If I replace res.status(400) with res.status(200), I am getting the expected custom message object.
Weird enough, I can get the custom message object when making the server call in development environment. I get Bad Request message from my production server and I don't know why the response is different when the environment is different. I am hosting this server on IIS Manager v10
So my question is should I use status code of 200 instead of 400 in this scenario? Is there a way to return a custom message from status 400? Based on my understanding, I should use 4xx status code if there is a client input errors eg there is already an existing ID or invalid inputs.
Edit: This is my code from my React app.
axiosInstance
.post("/form/some-endpoint", formData)
.then(function () {
navigate(ROUTE_SUCCESS_PAGE);
})
.catch(function (error) {
// eslint-disable-next-line no-console
console.log(error);
alert(error.response !== undefined ? error.response.data.message : error.message);
});
This is the actual screenshot of the response from prod server (I console log it)
But in development environment, I am getting the response that I wanted.
Postman response from Prod server:

<system.webServer>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
Adding the <httpErrors existingResponse="PassThrough" /> to the server's web.config file on IIS Manager resolved my issue. Based on my understanding, bypassing the http error handler and not letting IIS to send its response is the solution that I need.

should I use status code of 200 instead of 400 in this scenario
TLDR: It depends on the usage.
If your intent is to Update a form, like using a PUT request, you should require an id and if that id does not exist, return 404.
If you are looking to Create a new form, like using a POST request, with an id or other meta data and one already exists matching the id or meta data (e.g. groupId), then 400 is fine but it could be better to use 409 stating that there is a conflict with the existing state, that being a preexisting form id or meta data. Though you don't often pass an id to a POST create request.
The full list of codes is a great place to start, but sometimes it helps to see how certain codes are used in production APIs. A good place to look is the GitHub API which shows the possible status codes for each endpoint along with a description. Take the Pulls API for example, just searching for 40 on the page gives you a lot of insight about when certain codes are used.
Comparing these statuses with your example, if you look at the PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge route, they use 409 whenever the state is not matching as they describe...
Conflict if sha was provided and pull request head did not match
This seems similar in nature to the POST request described above.
At the end of the day the crucial part is to get in the correct grouping (i.e 2xx, 4xx, etc.) after that it's more about being consistent across your API than matching the codes to exact best option. Also everyone is different and some may choose different codes for the same use case.
As far as changing the response itself on 400 status, you should be able to achieve this by setting statusMessage directly and then call res.end.
function(req, res) {
res.statusMessage = "Form exists";
res.status(400).end();
}
Also see https://stackoverflow.com/a/36507614/6943587

Related

Why would I want to return a json object with a custom status field and message?

I am learning node and express and I noticed some tutorials like to send a response that looks like this:
{status: “Success”, message: “custom message”, response: {actual response object}}
My question is, what is the point of adding the extra status and message fields? Why not just return the response object by itself?
The simple reason is convenience. It sends a clear message to the client about the status of the request and what message to display based on that status. Its just a good programming practice that helps to structure your code base on how to handle errors from requests in the client side.

Browser not showing Internal Server Error HTML Page with status 500

I've two components in my application. A frontend which is built on Angular and backend built using express. I'm using the Nest.js framework in the backend.
I have an http-exception.filter.ts file which takes care of any thrown exception. So far, I've been handling Internal Server Error in the application this way.
if(exception.getStatus() === 500) {
response
.status(500)
.json({
status: '500',
code: 'INTERNAL_SERVER_ERROR',
message: 'Internal Server Error'
});
}
But, now an HTML page has been designed showing Internal Server Error message. All I need to do to render that page is to hit the URL /ui/internal-server-error. So, I tried to that using the code below.
response
.status(500)
.redirect('/ui/internal-server-error');
The page loads when a case of internal server error occurs, but the problem is I'm not getting 500 status when I'm reading the network logs in the browser. Instead, I'm getting 304 Not modified status.
Could anyone please point me in the right direction? I want to show the error page along with status code 500 and the UI page needs to come from Frontend only as I've no access over it.
When redirect is called, it sets the status, so the 500 is replaced.
From the express docs (relevant as NestJS uses Express by default):
Redirects to the URL derived from the specified path, with specified status, a positive integer that corresponds to an HTTP status code . If not specified, status defaults to “302 “Found”.
res.redirect('/foo/bar')
res.redirect('http://example.com')
res.redirect(301, 'http://example.com')
res.redirect('../login')
Add the desired status as an argument to redirect.

firebase Http function error

I have written a Firebase Http function.
When successful it returns status 200 with some data.
When it errors I want the client (which is using axios.post) to use a standard error handler which means showing the error.message property.
If I send an error code back with data - yes, I can access that data/message etc in error.response.data, but that isn't a pattern I can use for all errors - some errors might occur that don't give a response or data property.
So if I just want to access error.message at the client I need to be able to set that message but at the moment if I use for example:-
res.status(520).send('My custom error message')
I get:
Request failed with status 520
in the error.message, then I have to go to the error.response.data to get the actual message I want to display.
How could I do this so that I just use error.message regardless? I have tried using
res.status(x).send({error:customerror})
also tried
res.statusText = customerror
As you can see on Axios documentation, you have to use the error.response to get info from your custom message. You wouldn't be able to set the value on error.message on Axios.
If you really need to use error.message, you have to make a custom function to change it on cliente.

204 error code then 500 error code responses

So I have an application which needs to send data to the API which is created by our team leader using NodeJS with Express.js.
On my end I have laravel application which using VueJS for the UI. Inside the Vue JS component. I am using axios to request to the API.
axios.post('https://clearkey-api.mybluemix.net/sendcampaign', request)
.then(function(response) {
//console.log(response);
})
However, it returns 204 which means according to this https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.
204 No Content
The server has fulfilled the request but does not need to return an
entity-body, and might want to return updated metainformation. The
response MAY include new or updated metainformation in the form of
entity-headers, which if present SHOULD be associated with the
requested variant.
If the client is a user agent, it SHOULD NOT change its document view
from that which caused the request to be sent. This response is
primarily intended to allow input for actions to take place without
causing a change to the user agent's active document view, although
any new or updated metainformation SHOULD be applied to the document
currently in the user agent's active view.
The 204 response MUST NOT include a message-body, and thus is always
terminated by the first empty line after the header fields.
Then next it returns 500 Internal Server Error. So in my opinion it returns this error because there is no content to be returned from the server?
Can you tell me other possible problems why it return that response?
Check if the "HTTP method" of the 204 is OPTIONS and if the method of the 500 is POST.
If both are like that, then you are seeing first a CORS pre-flight request (the OPTIONS that returns 204) and then the actual request (the POST that returns 500).
The CORS pre-flight request is a special HTTP message your browser sends to the server when the webpage and the backend are hosted at different addresses. For example, if your website is hosted at http://localhost but the backend you are trying to access is hosted at https://clearkey-api.mybluemix.net.
The reason of the 204 just means your backend endpoint is correctly setup to handle requests for /sendcampaign (you can ignore it). The reason of the 500 is because of some exception in the implementation of the function that handles that endpoint.

Difference between response.status() vs. response.sendStatus() in express

What is the difference between response.status() and response.sendStatus() in Express.
I notice that one is used generally for post, get, and other middleware, while the later is used in delete requests. Why is this?
status() sets a HTTP status on the response (as a Javascript object on the server side).
sendStatus() sets the status and sends it to the client.
The usage doesn't depend on the HTTP method of the request. In most cases you would use sendStatus anyway since it's unlikely that the status changes once the request is processed (especially since status code is the first line in a raw HTTP response).
Read more in the docs:
https://expressjs.com/en/4x/api.html#res.sendStatus
res.sendStatus is shorthand for implementing res.send and res.status
the link shared by #freakish explains it all.
res.sendStatus(200); // equivalent to res.status(200).send('OK')
res.sendStatus(403); // equivalent to res.status(403).send('Forbidden')
res.sendStatus(404); // equivalent to res.status(404).send('Not Found')
res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')
As freakish already pointed out, sendStatus sets and sends the status.
This means that if you want to both set a status and send a body you have to use status. For example, you want to set an error status, and send a body with a JSON that explains why the error occured, you first have to set the status (using status), and then send the JSON (using send). If you had already set the status with sendStatus, it is no longer possible to send the JSON, because you already used a form of sent.
sendStatus(code) is a function that duplicates the standard status message corresponding to the provided status code into the body:
app.get('/a', (req, res) => {
res.sendStatus(500)
})
HTTP/1.1 500 Internal Server Error <--- this status message (aka "reason phrase")
<response headers>
Internal Server Error <--- gets duplicated here in body
See here for its implementation. There is no obvious need to do that, because the status message (the text after "500 ") will be there regardless. The above is NOT a normal HTTP idiom. Who knows why it was added into the express response. Moreover, when you send a non-empty body along with a status to a browser, it will render that body rather than a standard stylish page:
res.status(500).send() is sufficient to respond in a standard way:
app.get('/b', (req, res) => {
res.status(500).send()
})
HTTP/1.1 500 Internal Server Error <--- status message
<response headers>
<--- empty body
This is what everyone expects if there is nothing to say beyond status code & message.
no it's not for special routers like delete
The diffrence is res.status() only sets header and when you send response (res.send()) it will send to user
but res.sendStatus() sends the response at the moment without response body

Resources