Browser doesn't follow 302 redirect for preflighted CORS requests.
See original GitHub issueI’m not sure if this behaviour is triggered by any particular combination or lack of headers being set by django-cors-headers, or if it’s a general limitation or CORS, or an implementation bug in both Firefox and Chrome (and possibly others?)
I have installed django-cors-headers and set CORS_ORIGIN_WHITELIST
to actual host names (so it’s not setting Access-Control-Allow-Origin: *
, it’s using the actual whitelisted origin.
If I submit a “safe” (non-preflighted) POST request to a URL that returns a 302 redirect, the browser will transparently follow that redirect.
If I trigger a preflighted POST request by changing the content type to something like text/css
, or include an additional header like X-Requested-With: XMLHttpRequest
, then the browser will not follow the redirect.
Here’s my sample code. If you just change the domain names, update the CORS_ORIGIN_WHITELIST
setting, and configure the target URL to return a 302 redirect on POST, you should be able to recreate this problem.
test.html:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script type="text/javascript">
$(function() {
$('#preflighted').submit(function(e) {
e.preventDefault();
$.ajax({
contentType: 'text/css',
type: 'POST',
url: 'http://xyz.com:8000/test/',
// headers: {
// 'X-Requested-With': 'XMLHttpRequest'
// },
success: function(data, textStatus, jqXHR) {
console.log('success');
}
})
});
$('#simple').submit(function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: 'http://xyz.com:8000/test/',
success: function(data, textStatus, jqXHR) {
console.log('success');
}
})
});
});
</script>
</head>
<body>
<form id="preflighted" action="http://xyz.com:8000/test/" method="POST">
<input type="submit" value="Submit preflighted CORS request">
</form>
<form id="simple" action="http://xyz.com:8000/test/" method="POST">
<input type="submit" value="Submit simple CORS request">
</form>
</body>
</html>
views.py:
@csrf_exempt
def test(request):
if request.method == 'POST':
return HttpResponseRedirect('/test2/')
return TemplateResponse(request, 'test.html')
Then view your site at localhost:8000
, add that to CORS_ORIGIN_WHITELIST
, and add a hosts entry for xyz.com
to 127.0.0.1
.
Firefox with Firebug does a better job than Chrome at reporting the response headers in both cases.
Simple request (browser DOES follow the redirect):
POST /test/ HTTP/1.1
Host: xyz.com:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101 Firefox/23.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://localhost:8000/test/
Origin: http://localhost:8000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Content-Length: 0
HTTP/1.0 302 FOUND
Date: Tue, 01 Oct 2013 07:38:02 GMT
Server: WSGIServer/0.1 Python/2.7.5
Access-Control-Allow-Origin: http://localhost:8000
Etag: "d41d8cd98f00b204e9800998ecf8427e"
Content-Type: text/html; charset=utf-8
Location: http://xyz.com:8000/test2/
Preflighted request (browser does NOT follow redirect):
OPTIONS /test/ HTTP/1.1
Host: xyz.com:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101 Firefox/23.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Origin: http://localhost:8000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
HTTP/1.0 200 OK
Date: Tue, 01 Oct 2013 07:41:39 GMT
Server: WSGIServer/0.1 Python/2.7.5
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Max-Age: 86400
Etag: "d41d8cd98f00b204e9800998ecf8427e"
Access-Control-Allow-Origin: http://localhost:8000
Access-Control-Allow-Headers: x-requested-with, content-type, accept, origin, authorization, x-csrftoken
Content-Type: text/html; charset=utf-8
POST /test/ HTTP/1.1
Host: xyz.com:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101 Firefox/23.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Content-Type: text/css
Referer: http://localhost:8000/test/
Origin: http://localhost:8000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Content-Length: 0
HTTP/1.0 302 FOUND
Date: Tue, 01 Oct 2013 07:41:39 GMT
Server: WSGIServer/0.1 Python/2.7.5
Access-Control-Allow-Origin: http://localhost:8000
Etag: "d41d8cd98f00b204e9800998ecf8427e"
Content-Type: text/html; charset=utf-8
Location: http://xyz.com:8000/test2/
Issue Analytics
- State:
- Created 10 years ago
- Comments:6 (1 by maintainers)
Top GitHub Comments
Thanks for the link and explanation @jor123
Going to close it based on @musically-ut’s and @jor123’s comment; and from what I see, the middlewear is behaving as intended.