OPTIONS Requests, CORS, and Node.js

OPTIONS requests are 'preflight' requests sent by the client to a server, using cross origin access control headers to bypass your browser's same-origin policy.

That may seem like a mouthful, but by the end of this article you should have a better understanding of OPTIONS requests, Cross origin resource sharing (CORS), and how to respond in node.js.

Let's start with the same-origin policy. The policy only allows scripts to be run from the same origin (URI scheme, hostname, & port number), and was adopted by web browsers as a security mechanism. It was made to combat malicious code from one domain accessing private data from another.

The problem is, sharing resources between origins can be a powerful tool in today's world wide web, especially as network speeds have dramatically decreased loading times.

Here's were cross-origin resource sharing (CORS) comes in. It was created as a technique to bypass the same-origin policy in VoiceXML browsers, and was quickly adopted as a recommended standard of the W3C. So how does CORS work?

CORS specifies that web browsers should send an HTTP request before every action that can modify data (post, put, delete) on the target server. This additional request is called the OPTIONS request, and it contains an HTTP header with the originating domain name. When the server receives the request, it will then reply with an Access-Control-Allow-Origin header that indicates which domains are allowed access, and what actions may be taken by those domains.

If you're a web developer, you've probably encountered OPTIONS requests while testing a web application that made cross origin server calls. Recently I worked on a project with a server built on vanilla node.js, let's go over how to handle those OPTIONS requests.

First you'll need to definte your headers, in this example I'm allowing all origins access as well as the use of all CRUD operations:

var responseHeaders = {  
    "access-control-allow-origin": "*",
    "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS",
    "access-control-allow-headers": "content-type, accept",
    "access-control-max-age": 10,
    "Content-Type": "application/json"
};

Next, the server needs to add the header to the appropriate response, and send that back to the browser. You can do this with the writeHead helper function:

// Inside a request handler method
if (request.method === "OPTIONS") {  
    // Add headers to response and send
    response.writeHead(statusCode, responseHeaders);
    response.end();
}