Reputation: 13071
I have a simple index.html
file. This html is loading from localhost:3000
<body>
<h1>Some app</h1>
<script src="http://localhost:3005/script.js"></script>
</body>
The script.js
is set to load from another origin: localhost:3005
.
From my understanding, The browser should intercept the request and add the origin header to it - and make a preflight request to localhost:3005
server to check if localhost:3000
is allowed.
But i'm getting no origin
. The browser doesn't seem to add the origin header.
This is the server responsible for serving the script.js
file (localhost:3005
). I'm using the cors module.
const app = express()
const whitelist = ["http://localhost:3001"]
const corsOptions = {
origin: function(origin, callback) {
console.log("origin is: ", origin); //undefined -- why is undefined??
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
}
else {
callback(new Error('Not allowed by CORS'))
}
}
}
app.use(cors(corsOptions), express.static(__dirname))
app.listen(3005, () => {
console.log("server listening on port 3005")
})
My actual goal is to white-list only localhost:3000
for asking for my script.js
And i put localhost:3001
just to test if i'm actually getting a cors error - as it should be.
But i'm not even getting the origin - what is causing this? I'm getting the same behavior in both Firefox and Chrome. Did i misunderstood this hole process? Thanks :)
EDIT: Maybe seeing the request helps
Upvotes: 11
Views: 13204
Reputation: 124
For others who may come across this question, here is a practical demonstration of Kevin Christopher Henry's accepted answer above.
This first code snippet below requests a script (a .js file with an src URL) from the domain www.w3schools.com (and automatically executes it too upon the success of request, but that's not important here). Two things to note here:
$.ajax({
url: 'https://www.w3schools.com/lib/w3codecolor.js',
dataType: "script",
success: function(data, status) {
console.log('Result:', status)
},
error: function(err, status) {
console.log('Error:', error);
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This second code snippet below requests a URL (https://www.w3schools.com/bootstrap) to a specific route/page from the domain www.w3schools.com using XHR . This is what you would use when making requests to API endpoints. This is what CORS has jurisdiction over. Two things to note here:
$.ajax({
url: 'https://www.w3schools.com/bootstrap',
success: function(data, status) {
console.log('Result:', status)
},
error: function(err, status) {
console.log('Error:', err);
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
The error here is ambiguous. To see the actual CORS error, open Web Developers Console and you should see something like
"Access to XMLHttpRequest at 'https://www.w3schools.com/bootstrap' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
Now the reason why the error says "from origin 'null'" is because these code snippets are probably being run from sandboxed environments where it's not even setting the request header Origin
to "https://stackoverflow.com".
However, the result would be the same if the Origin
was actually set to "https://stackoverflow.com". Feel free to copy paste the above scripts into Web Developer Console and try it out.
Upvotes: 0
Reputation: 48932
I think you might be misunderstanding the purpose of CORS. It gives servers the ability to opt-in to certain kinds of requests that would otherwise be disallowed under the browser's Same Origin Policy. It doesn't provide a mechanism to disallow requests that were previously allowed.
Executing scripts from foreign origins in the src
of a <script>
tag has always been allowed under the Same Origin Policy, and so CORS simply doesn't apply. That's why there's no header on the request.
My actual goal is to white-list only
localhost:3000
for asking for myscript.js
.
You can't use CORS for that. In fact, you probably can't do that at all. I would take a step back and ask why you want to do that. If you're trying to secure private data then some sort of authentication mechanism (tokens, cookies, whatever) is probably necessary.
Upvotes: 2