What is the reason for an OPTIONS request not succeeding when the response to the subsequent request is a 204 status code?

While developing a Backbone.js based application, I encountered an unusual issue.

When the app requests a collection resource at a specific point, I receive an error in Chrome and Safari that reads:

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.

Initially, I assumed it was a CORS problem and blamed my API. However, when I tried to request the same resource using 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

Seems fine so far, but when I tried the GET request:

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

It only works if the boots collection contains at least one object. The CORS headers from my server seem correct. So why do the browsers still flag it as a cross-origin resource problem?

Could it be because of the content type text/plain in my 204 responses?

Preflight (OPTIONS) request in dev tools: https://i.sstatic.net/Viifh.png

Request headers of aborted response: https://i.sstatic.net/XdOgs.png

Answer №1

Make sure to include the Access-Control-Allow-Origin in the response headers of the second request as well. This issue is not on the client-side but rather on the backend.

This behavior aligns with the specifications outlined in the CORS specification, particularly detailed in the explanation found in section 7.1.5 "Cross-Origin Request with Preflight":

  1. An initial preflight request occurs (details omitted)
  2. The cross-origin request status is set to preflight complete.
  3. This marks the actual request. While making this request, specific rules need to be observed.
    • If the response has an HTTP status code of 301, 302, 303, or 307 Not relevant
    • If the end user cancels the request Not relevant
    • If there is a network error Not relevant
    • Otherwise,
      Perform a resource sharing check. If it fails, follow through with cache and network error steps.

Your request is currently failing at the first step of the resource sharing check:

  1. If the response contains no or more than one Access-Control-Allow-Origin header values, mark it as a failure and stop the algorithm.

To assist you better understand the issue, here's a simple NodeJS example that showcases your problem.
Your current backend logic looks like:

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

Observe the request and notice the failure experienced:

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

If you revisit the provided code and enable the Access-Control-Allow-Origin header in the response, and test again - your request will now succeed.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Sending information to a node using XMLHttpRequest

I'm currently attempting to send data to a form using XMLHttpRequest with the code below: function submitForm(event) { event.preventDefault(); var data = new FormData(form); var request = new XMLHttpRequest(); request.onreadystatechange = fun ...

Invoke a fresh constructor within a $get method in Angular's provider

I'm encountering an issue where I am attempting to utilize a function as a constructor inside the `.provider`, but I'm unable to instantiate a new constructor when it's within the `$get`. Here is my provider setup - this.$get = $get; ...

Having difficulty displaying GLTF object using three.js

I am attempting to display a GLTF object provided by the guidance from three.js (https://github.com/mrdoob/three.js/blob/master/examples/models/gltf/DamagedHelmet) In order to achieve this, I have used the loader mentioned in their documentation () Follo ...

What steps can be taken to verify that the submitted data is a legitimate numerical pair?

When I receive a string, it should be in the following format: number,number For example: 34.798,52.123 I need to verify that the number is indeed in this format before assigning it to variables and performing calculations. There is also a concern that ...

Prevent additional functions from running when clicking in Angular 5

I have implemented an Angular material table where each row expands when clicked. In the last cell of the table, I load a component dynamically using ComponentFactory. This loaded component is a dropdown menu. The problem arises when the dropdown menu is ...

Is it impossible to show more than 4 days of the week using Javascript?

My goal is to display a schedule showing the remaining days of the week, but I'm encountering an issue when using getDay() more than 4 times in the function. This is necessary for obtaining the days. To illustrate my point, I have included a sample co ...

Utilizing Three.js to create a vertex shader that dynamically adjusts pixel coloring according to its position on the screen

In my project using Three.js, I have created a vertex shader that assigns colors to each point in a plane based on the quadrant of the screen where a pixel is rendered. // customized vertex shader uniform float width; uniform float height; varying float x ...

Adjust the JQuery UI Slider value in real-time as you slide the slider

I am currently using a jQuery slider. When I slide the slider, I test for a specific scenario in the slide function. If the scenario is not met, the slider should revert back to its original position. For instance: Let's say the current slider value ...

Using Express.js to Serve Static Content on a Dynamic Route

I am working with the app.js code below; app.use(express.static(__dirname + "/public")); app.use("/example", express.static(__dirname + "/public")); app.engine("html", require("ejs").renderFile); app.get("/", (req, res) => res.render("index.ejs")); a ...

Is it possible for an AJAX call to fail, despite receiving a valid 200OK response?

There are times when the server responses return a 200OK status, but the content of the response is not what was anticipated. Is it possible to invoke the jquery ajax error callback even with a successful response, depending on certain criteria within the ...

Unable to get the Express.js Router functioning correctly on my server, even in a basic scenario

I am encountering an issue with using express.Router(). It was not functioning correctly in my application for serving JSON from MongoDB, so I attempted to simplify the scenario. However, I am receiving a 404 Not Found error in the request. What steps shou ...

Execute AJAX function following the completion of table loading from PHP in Ajax

I'm currently working on a shopping cart feature that involves calculating certain figures based on table values. The process involves loading the table using AJAX and PHP, which is functioning properly. However, I'm facing an issue where I nee ...

Unusual layout in Next.js editor (VS Code)

My chosen formatter is prettier, but I'm encountering an issue with the way it handles simple JSX functions. Initially, my code looks like this: function HomePage() { return; <div> <h1>Hello Next.js</h1> <p> Welcome ...

Is it possible to recreate the initial JavaScript source file using a minified version alongside its associated source-map file?

Currently, I am tackling a project that involves statically analyzing JavaScript code. The challenge lies in the fact that for certain libraries, I am limited to only having a minified version of the file along with its corresponding source-map. Are ther ...

Issue with JQuery Promise: fail() being invoked before promise resolution

In my TypeScript code, I encountered a peculiar issue with a jQuery promise. The fail() function is being executed immediately, logging an error message to the console, despite the promise resolving successfully afterwards. Here is the code snippet: ...

hide the container while keeping the content visible

Currently, I am working on a map with zoom in and zoom out functionalities. My main concern is how to make the red section invisible while keeping the buttons visible. This will ensure that when users search for locations on the map, their view will not be ...

The link that has been clicked on should remain in an active state

Is there a way to make the link that is clicked on active? I have attempted various scripts but have had no luck in getting the desired effect. Can anyone identify what might be causing the issue? $("a").click(function () { if ($(this).hasClass("acti ...

Error encountered with jQuery UI datepicker beforeShowDay function

After installing jquery-ui's datepicker, I encountered an issue while attempting to implement an event calendar. The datepicker was working fine until I tried to register the beforeShowDay handler using the following code: $('#datePicker'). ...

A Comprehensive Guide to Transmitting Variable Value Image Files using Ajax and PHP

I am currently exploring the integration of PHP and AJAX to facilitate image uploads into a designated folder, along with passing values from textboxes and textarea elements. <!DOCTYPE html> <body> <span id="msg" style="co ...

Utilize Material UI's TouchRipple Component to enhance the interactivity of custom elements and components

Within my material-ui application, I have a curated list featuring columns and icon buttons. Upon selecting an item from the list, I desire to incorporate the ripple effect characteristic of Material Design. Although Material UI provides lists with built ...