28

I've been struggling recently with a super-weird problem only happening in Chrome: as my API (NodeJS) is on a different subdomain, I need to use CORS to reach it from my front-end (EmberJS).

It's working pretty well but I'm very frequently (95% of the time) having very very slow OPTIONS queries, delaying any API calls by about 3 seconds.

2 requests, OPTIONS takes 3 seconds

Most of this time is spent downloading an empty content:

Downloading an empty content takes 3 seconds

It gets even weirder when I'm trying this on another website we made using a similar architecture, experiencing the exact same problem.

A few other things I tried:

  • I've been trying this with Firefox and Safari, and didn't get any delay.
  • I've been trying this locally or in production, experimenting the same delay.
  • I've been trying this with incognito mode (no extensions), and I have the exact same problem.

We're using on the back-end NodeJS with the CORS package.

Now, I have no idea if the problem is on either Chrome 60, NodeJS, the CORS package or EmberJS + jQuery.

Anyone experienced this too?

Benjamin Netter
  • 1,501
  • 3
  • 18
  • 34
  • 1
    Maybe you could do manual `OPTIONS` requests with `curl` or some REST-tester like restlet? Also do you mean you get no `OPTIONS` requests on Firefox, or that the `OPTIONS` request is fast? – Lux Sep 15 '17 at 02:53
  • @Lux I tried with Postman to replay a OPTIONS request and didn't experience the latency. Firefox does the OPTIONS request but it's not slow. – Benjamin Netter Sep 15 '17 at 08:13
  • 1
    I know may sound a bit weird but is this going via a http proxy i mean the ember code when calls the api is it going via a http proxy? – vaibhav Oct 04 '17 at 09:32
  • 1
    Do chrome and firefox send exactly the same headers via `options` request? Can you dump their headers? – ykaragol Oct 04 '17 at 10:05
  • 1
    Maybe you can try to analyze the request with a sniffer like wireshark? – Lux Oct 04 '17 at 20:02
  • 1
    @Benjamin Netter Can you please add the request and response headers for OPTIONS call. – Kalana Demel Oct 08 '17 at 02:37
  • change cors to this middleware function preflight(req, res, next) { res.setHeader( "Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS") if ("OPTIONS" === req.method) res.send(200) else next() } and lets see what happen – Tiago Fabre Oct 10 '17 at 17:17
  • I'm having the same issue. Ajax requests from localhost page to .local LAN address cause OPTIONS to hang for ~2 seconds. GET/POST requests to the same endpoint are <50ms. Chrome is slow-walking preflight. – Jeff McMahan Oct 10 '17 at 18:37
  • 1
    Can you please share the CORS package configuration? Did you change the optionsSuccessStatus variable? My guess is that this issue is related to the OPTIONS response code (204 or other). see here - https://www.npmjs.com/package/cors#configuration-options – Ido.Co Oct 10 '17 at 19:21
  • 1
    We couldn't find an open Chrome issue for this, so my colleague has opened one: https://bugs.chromium.org/p/chromium/issues/detail?id=803580 – NullColaShip Jan 21 '18 at 21:13
  • You can fix it for your own browser in Chrome settings: Go to Settings / Advanced / Privacy and turn off "Use a prediction service to load pages more quickly". It's the prediction requests that lock up your single-threaded server. – Blaise May 16 '19 at 14:31

4 Answers4

8

Just as a note: It seems a chrome bug

I reproduced the issue using a server with two DNS names using a service in a unique domain

https://domain1.com  --> https://domain1.com (No CORS, no delay)
https://domain2.com  --> https://domain1.com (CORS, delay)

chrome cors

It is exactly the same service responding to two names, so I am testing exactly the same request, client and server code (DNS names are interchangeable)

Tested with

  • Chrome 61.0.3163.100 (Windows) -->DELAY
  • Chrome 62.0.3202.84 (Android) -->DELAY
  • Chrome 62.0.3202.84 (iOS-Ipad) -->OK!!!
  • Firefox-->OK
  • Edge --> OK

Workaround (in my case). Create a proxy in my host to respond to the same origin DNS and avoid CORS

pedrofb
  • 37,271
  • 5
  • 94
  • 142
4

I've been seeking to debug this and it appears to be a chrome bug as we were experiencing the same issue.

For reference, I've filed a bug report to chromium here: CORS pre-flight and subsequent requests are very slow only on Chrome

I'm adding this here to help stop any more developers spending half a day investigating it ;) Will update as we here more from Chromium.

Overview of bug report follows:

UserAgent:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36

Steps to reproduce the problem:

  1. Have app.domain.com
  2. List item
  3. Have api.domain.com
  4. Enable CORS on API to enable access
  5. Check responses in DevTools, see OPTIONS and GET requests are taking up to 300ms+

What is the expected behavior?

Response timings should be accurate.

What went wrong?

We are using Go microservices and noticed a big disparity in the time taken between browsers - chrome being the slowest up to a magnitude of 100x.

when we have checked the timings from the backend, responses take at most 10ms, with most being sub 1ms. When checking the timing under devtools the same responses were coming in at ~100ms~1s.

Did this work before?

N/A

Chrome version: 63.0.3239.132 Channel: stable OS Version: 10.0 Flash Version:

In Firefox (and any other browser), the exact same requests return in ~1-20ms as expected.

In trying to diagnose further, we used Telerik's Fiddler to check the actual network response times and confirmed that they were being sent and received by Chrome within our expected timings. The only conclusion we could come to is that something internal to Chrome is slowing the processing of these requests down.

We tried all permutations of chrome://flags#out-of-blink-cors and chrome://flags#enable-site-per-process, which are the two options which we spotted which seem vaguely relevant. Nothing seemed to help.

We have also found many Stack Overflow articles about a similar issues that make mention of it being a Chrome bug, but I haven't been able to find it reported here:

We've just tested Chrome on MacOS and it doesn't appear to be an issue - so may be limited to Windows.

Chrome: optionsChrome getChrome

Edge: optionsEdge getEdge

Firefox: optionsFirefox getFirefox

0

I found the solution for my case and I will share it here.

I am on Windows, using Chrome version 70, runing a AngularJS front-end with a nodeJS backend with restify on the same server. I am using fiddler to monitor the requests, and OPTIONS request can take 1 second some times, while some times just < 5 ms. Stop using Filler bring that maximum time down to 300 ms, but still considered long. And this delay happens in Chrome, but not in Firefox. I did not test other browsers.

My case might be different from the question, as I looked the Chrome network timeline, when Fiddler is present, there is a 1s waiting(TTFB) delay. And when Fiddler is not on, there is a 300 ms gap between DNA lookup and initial connection.

I finally found this AJAX query weird delay between DNS lookup and initial connection on Chrome but not FF, what is it?

Just change back-end connection URL from localhost to 127.0.0.1 and It solved my problem perfectly.

Haijin
  • 2,561
  • 2
  • 17
  • 30
0

Old article, but this is a much deeper problem than most of these answers imply and can affect anyone. This article https://www.wpeform.io/blog/handle-cors-preflight-php-wordpress/ greatly helped my understand and mitigation of the problem.

The OPTIONS request is needed as part of the web spec per URL. This makes cache smashing requests very easy to happen, simply by changing a URL. In addition it is important to ensure your requests detect OPTIONS requests and don't do too much processing (e.g. loading lots of stuff from databases etc).

Alexp
  • 520
  • 1
  • 4
  • 15