2

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)

enter image description here

enter image description here

But in development environment, I am getting the response that I wanted. enter image description here

enter image description here

Postman response from Prod server: enter image description here

calvert
  • 631
  • 10
  • 33
  • 1
    I think the way you are approaching this is correct. More accurately, I think you could return a 409 (Conflict) instead for this case. But I think we need more details on your issue to help you out. How are you sending your requests / reading your responses? Can you show a screenshot of the "Bad Request" output you see? – Jaxon Crosmas Aug 26 '22 at 21:41
  • as @JaxonCrosmas stated your approach is the right one but in a situation where you want to continue with `response of 2xx`, you can justify it by saying that the data was received and acted on so response `200` is also accepted here but send a message of fail – Ogoh.cyril Aug 26 '22 at 21:49
  • @JaxonCrosmas I have added some information that might be useful for us to debug. – calvert Aug 26 '22 at 21:50
  • 1
    I see you are logging the actual Axios response object to the console (in this case `AxiosError`). The "Bad Request" text in `AxiosError.response.statusText` is not the text returned by your application, it's a description of the `400` status. The data you are looking for is in `AxiosError.response.data`. This field contains the JSON object you returned from your application. – Jaxon Crosmas Aug 26 '22 at 22:06
  • IISNode or HttpPlatformHandler? – Lex Li Aug 26 '22 at 22:33
  • @LexLi IISNode for the express server – calvert Aug 26 '22 at 22:43
  • @JaxonCrosmas The axios error from prod server does not contain the message that I am looking for, if you look closely at the first image: `response: {data: "Bad Request"}` but at the third image: `response:data:{status: 400, message: "RO/Invoice ...}` I tried making the api call from Postman and I am getting "Bad Request" in the response body. I will attach the screenshot. I suspect something is not working on the server side or the IIS Manager. – calvert Aug 26 '22 at 23:04
  • 1
    https://github.com/tjanczuk/iisnode/issues/291 With all keywords plus iisnode, a search engine can easily lead you to. – Lex Li Aug 26 '22 at 23:08
  • @LexLi Thanks, I had a feeling that IIS Manager/Node could be the culprit and you had the same suspicious but I am not experienced enough with IIS. I managed to resolve it by adding `` to my web.config. It seems like I need to bypass the IIS http error handler and that did the trick. This is the solution to my problem. – calvert Aug 26 '22 at 23:18
  • Then you can post and accept your own answer below. – Lex Li Aug 26 '22 at 23:19

2 Answers2

0

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

Nickofthyme
  • 3,032
  • 23
  • 40
0
<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.

calvert
  • 631
  • 10
  • 33