cors

How to apply CORS preflight cache to an entire domain


I am building a REST application that makes use of CORS. Every REST call is different and I am finding that there is significant overhead in getting the preflight OPTIONS call. Is there a way to cache and apply a preflight OPTIONS result so that any subsequent calls to the same domain use the cached response?


Solution

  • Preflight can only be applied to the request, not to the entire domain. I brought the same question up on the mailing list, and there were security concerns. Here's the entire thread: http://lists.w3.org/Archives/Public/public-webapps/2012AprJun/0228.html

    There are a few things to consider if you'd like to limit the number of preflight requests. First note that WebKit-based browsers set a max preflight cache lifetime of 10 minutes:

    https://github.com/WebKit/webkit/blob/master/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp and Blink-based browsers limit the cache to two hours: https://source.chromium.org/chromium/chromium/src/+/main:services/network/cors/preflight_result.cc;l=40;drc=098756533733ea50b2dcb1c40d9a9e18d49febbe

    (I'm not sure if this is true for other browsers). So while you should always set the Access-Control-Max-Age header.

    Next note that it is impossible to avoid a preflight on PUT/DELETE requests. So updates/deletes to your API will require at least one preflight every 10 minutes.

    On GET/POST, avoid custom headers if at all possible, since these still trigger preflights. If your request has JSON body, note that a Content-Type of 'application/json' (in the request, not response) also triggers a preflight.

    If you are willing to bend just how "RESTful" your API is, there are a few more things you can try. One is to use a Content-Type that doesn't need a preflight, like 'text/plain'. Custom headers always trigger preflights, so if you have any custom headers, you could move them into query parameters. At the extreme end, you could use a protocol like JSON-RPC, where all requests are made to a single endpoint.

    In all honesty, because of the browser's preflight cache limit of 10/120 minutes, and REST's resource urls, the preflight cache is of limited value. There's very little you can do to limit preflights over the course of a long running app. I'm hopeful the authors of the CORS spec will try to address this in the future.