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

Filter out the selection choice that begins with 'aa' in the drop-down menu

Here is a select field with various options: <select id="sel"> <option value="1">aadkdo</option> <option value="2">sdsdf</option> <option value="3">aasdfsddkdo</option> <option value="4"> ...

How to Remove Carousel Arrows in Bootstrap 5

Any suggestions on how to remove the previous and next arrows in a Bootstrap carousel, particularly on the first and last slide? I'm struggling to find a solution for Bootstrap 5 as most solutions available are for older versions. Your help would be g ...

When you click on Highcharts, a bigger graph will be displayed

I am working on a feature that allows users to zoom in on small charts on my website. This involves revealing an overlay div and displaying a larger chart with the same data as the clicked chart inside it. function DrawSmallChart() { chart_data = [1, 2, 3 ...

Using JavaScript to transform radio buttons into checkboxes

I have a grouping of radio buttons and a checkbox displayed on the page as shown below <html> <head> <title>Languages</title> <script type="text/javascript"> </script> </head> <body> <spa ...

Is it possible for the number returned by setTimeout() in JavaScript to be negative?

Is it possible for a number returned by the setTimeout() function in JavaScript to be negative? Currently, I've observed that the timeoutIds generated are sequentially numbered in Chrome as 1,2,3,4,5,6... While in Firefox, they start from number 4 an ...

When combining stores, what sets Mobx.inject apart from Mobx.observer?

As I start integrating my store with mobx, a question arises in my mind. What sets apart the usage of observer(['store'],...) from inject('store')(observer(...))? Upon closer examination, it seems that inject is not reactive. So, what ...

Tips for monitoring password and password confirmation fields in DevTools when using AngularJS forms

Within the ng-model, I have identified two variables: vm.user.password and vm.confirmpassword. The input fields are equipped with attributes such as id, name, and class. I am interested in monitoring both the password and confirmpassword values within Dev ...

Transforming a canvas into a div element

Hey there, I'm looking to swap out one canvas for another but I'm not sure how it will look on the browser. Any help would be greatly appreciated. <div id="juego"> <canvas width="203" height="256" id="1" class="bloque"></canvas& ...

Choose an XPath formula that will target every single element, text node, and comment node in the original sequence

How can we write an XPath expression that selects all elements, text nodes, and comment nodes in the order they appear in the document? The code below selects all elements but not text nodes and comment nodes: let result = document.evaluate('//*&apo ...

Utilizing the js-yaml library to parse a YAML document

Currently, I'm utilizing js-yaml to analyze and extract the data from a yaml file in node js. The yaml file consists of key-value pairs, with some keys having values formatted like this: key : {{ val1 }} {{ val2 }} However, the parsing process enco ...

An individual in a chat App's UserList experiencing issues with incorrect CSS values. Utilizing Jquery and socketio to troubleshoot the problem

Currently, I am testing a new feature in a chat application that includes displaying a user list for those who have joined the chat. The challenge is to change the color of a specific user's name on the list when they get disconnected or leave the cha ...

Is it possible to iterate through div elements using .each while incorporating .append within an AJAX call?

After sending AJAX requests and receiving HTML with multiple div elements (.card), I am using .append to add new .card elements after each request, creating an infinite scroll effect. However, I am facing issues when trying to use .each to iterate over all ...

A status code of 200 indicates a successful login, which then leads to a 401 status code upon making a

Just recently, I successfully deployed a rails backend and a vue frontend to Heroku. Everything was working fine until today when I encountered a problem while trying to log in to the web app. Immediately after logging in, I started receiving 401 responses ...

`Why won't the checkbox uncheck when the dropdown is changed in jQuery?`

I have a roster of users, each with a unique checkbox for selection. When I adjust the dropdown menu, a new group of users is chosen and marked as selected. However, I am struggling to uncheck the previously selected checkboxes based on the last dropdown c ...

What could be the reason for the initial response appearing blank?

How can I retrieve all the comments of a post using expressjs with mongodb? I am facing an issue where the first response is always empty. Below is the code snippet: const Post = require("../models/posts"), Comment= require("../model ...

Trouble with React Material Select Options Failing to Populate

After iterating and producing MenuItems, I am able to see the items when I console.log, but in the UI, the dropdown appears empty. I'm puzzled as to why the Select's are not being populated. Any thoughts on this issue? Below is the supplied code ...

What is the best way to activate a component within Angular 2 that triggers the display of another component through method invocation?

I have created a popup component that can be shown and hidden by calling specific methods that manipulate the back and front variables associated with the class. hide() { this.back = this.back.replace(/[ ]?shown/, ""); this.front = this.front.replace( ...

What is the best way to retrieve the value of the first name using Protractor?

Is there a way to store the value of the first name using a protractor script? The first name is set when the user logs in and corresponds to the name of the logged-in user. I am wondering if this can be done utilizing by.addLocator(). Here is the tag tha ...

Displaying content on a webpage using PHP, AJAX, and HTML

Looking to update my current form setup. I have a basic Form below: <form action="" method="POST"> <input type="button" value="Generate Numbers" onclick="on_callPhp1()"/> </form> Accompanied by this javascript code: <script type="te ...

The terminal does not recognize the nodemon command

My goal is to automate server reloads using nodemon. I have successfully installed it locally and set the start command as nodemon app.js with this code: "scripts": { "start": "nodemon app.js" } Initially, everything was running smoothly. However, ...