Handle an OPTIONS request with CORS in Node JS
Have you ever had an API Node JS application running locally on your machine and everything is working fine until someone else tries to make a HTTP request from other machine or domain and poof, no mater what you try, every petition will result into a OPTIONS request? Recently, I had this scenario in the backend of an API application using MongoDB and Mongoose. I initially thought it was a bad request from the frontend side which is using React JS, why? Because I was using Postman to make some POST and GET request and everything was working fine, the server was receiving the right request and the database was creating a new object successfully . Even experienced people were pointing out that the problem was in the frontend side because if Postman can make requests, why the frontend side doesn’t? After approximately 2 hours, I determined that the problem was in the backend side of the application because it was nothing wrong with the frontend, we tried with libraries like Axios and built-in React functions like .fetch to make request using almost every optional argument in the function and all kind of variations in the frontend and nothing worked . So I asked for help again. A colleague told me that he had that kind of problem and was a server-side error and after After approximately 3.5 hours of research I found out the solution and in fact, it was a backend problem. This little explanation may save you a lot of time. The follow implementation is not mine, I was close to implement the solution but ‘Macho Alvarez’ did the job.
Well, all this happens because when you are using a cross origin request (CORS), the browser or application will send an OPTIONS petition frist to make sure you have the privileges to excecute a petition like POST, GET, PUT, etc. Apperantly, Postman will send the request you asked for only. In the other hand, browsers will send OPTIONS request first and then, the actual request. That explains why Postman was working fine and the frontend doesn’t.

In the image above it says that if you have a request in the same domain(blue image) it will not be controlled by CORS, so you have all the requirements to make any HTTP request and your petition will not contain the OPTIONS request. On the other hand, the red image is hosted in another domain, so, the application will send an OPTIONS request before the real petition GET. This is to make sure you are allowed to make HTTP request to that domain so, those petitions will be handle by CORS and if you don’t have your server configured to handle an OPTIONS request, your “real” petition (GET, POST, etc) will not be process by the API, because it will respond to the OPTIONS petition and “forget” about the actual request.

How can we fix it?
In my example application I’m using Express for HTTP requests and npm for installing Node packages.
The easiest way to fix it is to install a package called cors with
npm install cors
After that, require the cors package in your HTTP request as follows:
Let’s say you have an application who has clients, your file where you manage your routes would look something like this:

Take a look at to the code above. We require the cors package and then we use it to create an router to “options” http request. Now, our application knows what to do when it receives an OPTIONS request and CORS will handle this request. The same happends in our POST method. We put the cors() method as a parameter to handle a request from other domain. You have to insert the cors() method in every router method you know will receive an external domain request. There are other options you can apply to CORS to allow some conections with credentials only whit Access-Control-Allow-Credentials: true | false, specific request types with Access-Control-Allow-Methods: <method>[, <method>]* and data type wi and headers fields whit Access-Control-Allow-Headers: <field-name>[, <field-name>]*, specific domains with the Access-Control-Allow-Origin: "domain.example" these preferences must be set at the server start up whit app.use(parameter).
And now, our application is able to handle an OPTIONS request and will work like a charm!
