Fetching from the same origin results in a null comparison issue due to HTTP CORS restrictions

Encountering an issue where a simple same-origin fetch("fetch.xml") call fails, resulting in a console error message

Access to fetch at 'http://127.0.0.1:8000/fetch.xml' from origin 'null' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'http://127.0.0.1:8000' that is not equal to the supplied origin. To resolve this, the server should send the header with a valid value. Alternatively, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

The network headers associated are as follows

General
Request URL: http://127.0.0.1:8000/fetch.xml
Referrer Policy: origin

Response Headers
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Origin: http://127.0.0.1:8000
Access-Control-Max-Age: 86400
Content-Security-Policy: sandbox allow-scripts
Content-Type: text/xml
Date: Sun, 16 Aug 2020 06:20:43 GMT
Referrer-Policy: origin
Server: SimpleHTTP/0.6 Python/3.8.5

Request Headers
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: no-cache
Connection: keep-alive
DNT: 1
Host: 127.0.0.1:8000
Origin: null
Pragma: no-cache
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36

Despite being the same origin, the browser incorrectly identifies the origin as null when executing the fetch statement. This behavior persists even when using a real domain instead of just the IP address.

If the fetch statement is modified to

fetch("fetch.xml", { mode: "same-origin" })
, the browser still labels the origin as null but changes the error message to

Fetch API cannot load . Request mode is "same-origin" but the URL's origin does not match the request origin, null.

Seeking guidance on how to ensure the browser correctly identifies the origin instead of defaulting to null for the fetch statement. Refrain from utilizing Access-Control-Allow-Origin values of null or *, as it could potentially disable CORS due to being too open.

Note: Access to files is done through a real web server, not via file:// URLs! Even with a genuine domain setup, the origin remains tagged as null by the browser.



Reproduction Example

A simple server setup encompassing everything needed for quick testing (execute it with python3):

#!/usr/bin/env python3

from http.server import HTTPServer, HTTPStatus, SimpleHTTPRequestHandler, test
import sys
from urllib.parse import urlparse
import os

class TestRequestHandler (SimpleHTTPRequestHandler):
    def do_GET(self):
        """Serve a GET request."""
        url = urlparse(self.path)
        if url.path == '/' or url.path == '/index.html': # index.html
            f = self.send_head('text/html')
            self.wfile.write('''<!DOCTYPE html>
                            <html>
                            <head>
                                <title>Test</title>
                                <script type="text/javascript" src="control.js"></script>
                            </head>
                            <body>
                            </body>
                            </html>'''.encode('utf-8'))
        elif url.path == '/control.js': # control.js will try to fetch the fetch.xml
            f = self.send_head('application/javascript')
            self.wfile.write('''function init() {
                    fetch("fetch.xml", { mode: "same-origin" }).then(r => r.text()).then(t => console.log(t));
                }
                window.addEventListener("load", init);'''.encode('utf-8'))
        elif url.path == '/fetch.xml': # fetch.xml
            f = self.send_head('text/xml')
            self.wfile.write('''<?xml version="1.0" encoding="UTF-8"?>
                            <root>
                                <test>Hi</test>
                            </root>'''.encode('utf-8'))


    def send_head(self, ctype):
        self.send_response(HTTPStatus.OK)
        self.send_header('Content-Type', ctype)
        self.send_header('Access-Control-Allow-Origin', 'http://127.0.0.1:8000')
        self.send_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
        self.send_header('Access-Control-Max-Age', 86400)
        self.send_header('Referrer-Policy', 'origin')
        self.send_header('Content-Security-Policy', 'sandbox allow-scripts')
        SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
    test(TestRequestHandler, HTTPServer, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000)

To test using different files on your own server:

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
    <script type="text/javascript" src="control.js"></script>
</head>
<body>
</body>
</html>

control.js

function init() {
    fetch("fetch.xml", { mode: "same-origin" }).then(r => r.text()).then(t => console.log(t));
}
window.addEventListener("load", init);

fetch.xml

<?xml version="1.0" encoding="UTF-8"?>
<root><test>Hello</test></root>

Ensure the server is configured to send the following headers (adjust the IP/domain accordingly):

Access-Control-Allow-Origin: http://127.0.0.1:8000
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Max-Age: 86400
Referrer-Policy: origin
Content-Security-Policy: sandbox allow-scripts

Answer №1

Your issue lies here:

Content-Security-Policy: sandbox allow-scripts

Please refer to the official documentation.

The problem is that you forgot to activate this setting:

allow-same-origin

This allows the content to be recognized as coming from its original source. If this option is not enabled, the embedded content will be treated as originating from a distinct source.

This means that http://localhost:8000/ and http://localhost:8000/fetch.xml are considered as separate and unique origins.

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

Centralizing images in a Facebook gallery/lightbox during the loading process

Is the image width and height stored in Facebook's gallery database? In typical JavaScript usage, the image width and height cannot be determined until the image is fully loaded. However, on Facebook, images are pre-loaded before being displayed, ens ...

Using Fabric.js to manage image controls situated beneath another overlay image

I'm currently working on a canvas user interface using jquery and the fabric.js library. I managed to add an overlay png image with transparency by implementing the code below: var bgImgSrc = bgImg.attr('src'); canvas.setOverlayImage(bgImgS ...

Enhancing the session helper in Silex with additional values

Hey there, I'm currently working on a basic shopping cart using an MVC framework called Silex. However, I've run into a JavaScript/AJAX issue that I could use some help with. My problem arises when trying to add a product to the basket. The issue ...

Modifying the src attribute of an object tag on click: A step-by

So I have an embedded video that I want to dynamically change when clicked on. However, my attempt at doing this using JavaScript doesn't seem to be working. <object id ="video" data="immagini/trailer.png" onclick="trailer()"></object> H ...

Problem with animated scrolling in Jquery

Currently, I am working on a function that aims to smoothly scroll the web to a specific div each time a user scrolls "into" a container div. You can get a better idea of what I mean by looking at my JSFiddle. Everything works perfectly when the user scro ...

What is the best way to display the JSON data?

<!DOCTYPE HTML> <html> <head> <title></title> <link href="/bundles/hoaxpartner/css/style.css" type="text/css" rel="stylesheet" /> </head> <body> <div id="header">Backbone</div> &l ...

JavaScript function to double the odd numbers

I'm attempting to extract the odd numbers from the given array and then double them using the reduce method, but I keep getting an undefined error. Can someone please offer some guidance? const multiplyOddByTwo = (arr) => { return arr.reduce(( ...

Unable to iterate through nested arrays in Contentful mapping

I am facing an issue while trying to map further into the array after successfully retrieving data from Contentful. The error message field.fields.map is not a function keeps popping up and I can't figure out what I'm doing wrong. export defau ...

Is it possible to include multiple API routes within a single file in NextJS's Pages directory?

Currently learning NextJS and delving into the API. Within the api folder, there is a default hello.js file containing an export default function that outputs a JSON response. If I decide to include another route, do I need to create a new file for it or ...

Is there a way to simulate a minified module for testing purposes?

For my project, I developed a component intended to function as a module. The implementation involves the utilization of third-party code provided in the form of a config file (initOpinionLab.js) and a .min.js file (opinionlab.min.js). As part of the devel ...

Create a dynamic effect by adding space between two texts on the page

const Button = () => { const options = ['test1', 'test2', 'test3']; return ( <div style={{ position: 'absolute', left: '8px', width: 'auto', flexDirection: 'row' ...

What could be the reason for this JSON being considered "invalid"?

Despite passing validation on jsonlint, both Firefox and Chrome are rejecting this JSON: { "messages": [ { "subject": "One" }, { "subject": "Two" }, { "subject": "Three" ...

Tips for incorporating flow and TypeScript typings into an NPM module

Are there any resources available for adding both flow and typescript typings to an NPM module at the same time? I've been struggling to find a comprehensive guide on this topic, and it seems to be a common issue faced by open source library maintain ...

How can I replay an HTML audio element?

I created an HTML5 page with an audio element for playing music in mp3 format. However, when the music plays to the end, it stops and I'm using JavaScript to control the audio element. Even so, I can't seem to replay it, only stop it. Is there a ...

Is it possible to conceal and completely empty the TextBox once the checkbox is deselected?

When the checkbox is checked, the textbox is displayed; otherwise, it remains hidden. However, the value is not being cleared. Can someone please help me with this issue? Thank you in advance. HTML <div class="munna"> <in ...

Discovering the Nearest Textfield Value Upon Checkbox Selection Using JQuery

How can I retrieve the value of the nearest Textfield after selecting a checkbox? This HTML snippet serves as a simple example. In my actual project, I have dynamically generated lists with multiple checkboxes. I require a way to associate each checkbox wi ...

Launching JQuery modal upon button click

I'm encountering an issue with jQuery Mobile. Here is the JSFiddle link: http://jsfiddle.net/Gc7mR/3/ Initially, I have a Panel containing multiple buttons. The crucial button has an id of 'define'. <div data-role=header data-position= ...

AngularJS: Advanced Routing for Dynamic Web Applications

Hello, I am currently exploring the possibility of implementing something similar to this code snippet using AngularJS: $routeProvider .when('/root/:controllerName/blah/:blahId/blah/:blah', { templateUrl: '/tmpl/:controllerName ...

I am working on a NodeJs code that utilizes (Array)Buffers and native readUInt16BE. However, since I am working within a browser context, I plan to opt for DataView.getUint16 instead

While working on adapting a JPEG parsing function in Node.js for use in a browser environment, I discovered that the original code can be found here. The challenge lies in using Node.js' Buffer class. To make it compatible with a browser environment, ...

Having trouble with Jquery Ajax call in IE8?

I have a dynamic data loading from the database, with each row containing links that perform various actions. Most of them work perfectly fine, but I've noticed an issue with the last one I added – it doesn't seem to be functioning properly on ...