Why does the OPTIONS request fail when the response to the request for subsequent requests is 204?

I am building an application based on Backbone.js and am facing some strange problem.

At some point, the application requests a collection resource, and inside Chrome (and Safari) I get this error:

XMLHttpRequest cannot load http://api.mydomain.net/v1/foos/00000d/bars/000014/boots Origin http://localhost:3501 is not allowed by Access-Control-Allow-Origin. 

Ok, CORS problem, I thought and blamed my API. Then I requested this same resource through CURL:

 curl -i -H'Accept: application/json' -H'X-Auth-Token: pAWp5hrCmXA83GgFzgHC' -XOPTIONS 'http://api.mydomain.net/v1/foos/00000d/bars/000014/boots' HTTP/1.1 200 OK Status: 200 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Auth-Token Content-Length: 0 

looks good, now get:

 curl -i -H'Accept: application/json' -H'X-Auth-Token: pAWp5hrCmXA83GgFzgHC' -XGET 'http://api.mydomain.net/v1/foos/00000d/bars/000014/boots' HTTP/1.1 204 No Content Status: 204 Cache-Control: no-cache Content-Length: 0 Content-Type: text/plain 

In case I request a boots collection that contains at least one object, everything works fine. The CORS headers on my server respond perfectly to arr as I think. So why do browsers report a cross-source issue?

Is this related to the text/plain content type of my 204 responses?

Preflight request (OPTIONS) in dev tools: OPTIONS

Request interrupted response headers: Get

+4
source share
1 answer

You should also include Access-Control-Allow-Origin in the response headers of the second request. This is not a client-side problem, but an internal one.

This behavior complies with the CORS specification used in the following explanation ( Section 7.1.5, Origin of Request with Pre-Flight Period ):

  • Preprofessional request ( details omitted)
  • "Set the status of the cross origin request before the end of the preflight."
  • "This is an actual request. (...) follow the request rules below when submitting a request."
    • If the response has an HTTP status code of 301, 302, 303, or 307 Not applicable
    • If the end user cancels the request Not applicable
    • If there is a network error Not applicable
    • Otherwise
      Perform a resource check. If it returns with an error, apply the caching and network error steps.

Your request is no longer executed in the first step of checking access to resources :

  • If the response contains zero or more Access-Control-Allow-Origin header values, the return fails and completes this algorithm.

I provide a simple NodeJS example illustrating your problem.
Your current backend behaves as follows:

 require('http').createServer(function(request, response) { if (request.method == 'OPTIONS') { // Handle preflight response.writeHead(200, { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "X-Foo" }); } else { // Handle actual requests response.writeHead(204, { //"Access-Control-Allow-Origin": "*" }); } response.end(); }).listen(12345); 

Now make a request and crash :

 var x = new XMLHttpRequest; x.open('GET', 'http://localhost:12345'); x.setRequestHeader('X-Foo','header to trigger preflight'); x.send(); 

Return to the code I provided and include the Access-Control-Allow-Origin header in the response and retry the test. Your request will be successful.

+7
source

Source: https://habr.com/ru/post/1445199/


All Articles