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