Skip to content

Instantly share code, notes, and snippets.

@shibukawa
Last active October 11, 2022 22:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shibukawa/52502ceb5462b6bf6ea6c5704be6659b to your computer and use it in GitHub Desktop.
Save shibukawa/52502ceb5462b6bf6ea6c5704be6659b to your computer and use it in GitHub Desktop.
diff --git a/http/response.py b/http/response.py
index f7d248e..dbd1c34 100644
--- a/http/response.py
+++ b/http/response.py
@@ -16,7 +16,7 @@ from django.core.serializers.json import DjangoJSONEncoder
from django.http.cookie import SimpleCookie
from django.utils import timezone
from django.utils.encoding import iri_to_uri
-from django.utils.http import http_date
+from django.utils.http import http_date, is_new_redirect_supported
_charset_from_content_type_re = re.compile(r';\s*charset=(?P<charset>[^\s;]+)', re.I)
@@ -470,11 +470,15 @@ class HttpResponseRedirectBase(HttpResponse):
class HttpResponseRedirect(HttpResponseRedirectBase):
- status_code = 302
+ def __init__(self, *args, request=None, **kwargs):
+ self.status_code = 307 if is_new_redirect_supported(request) else 301
+ super().__init__(*args, **kwargs)
class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
- status_code = 301
+ def __init__(self, *args, request=None, **kwargs):
+ self.status_code = 308 if is_new_redirect_supported(request) else 302
+ super().__init__(*args, **kwargs)
class HttpResponseNotModified(HttpResponse):
diff --git a/middleware/common.py b/middleware/common.py
index a18fbe7..a339899 100644
--- a/middleware/common.py
+++ b/middleware/common.py
@@ -57,7 +57,7 @@ class CommonMiddleware(MiddlewareMixin):
# Return a redirect if necessary
if redirect_url or path != request.get_full_path():
redirect_url += path
- return self.response_redirect_class(redirect_url)
+ return self.response_redirect_class(redirect_url, request=request)
def should_redirect_with_slash(self, request):
"""
@@ -104,7 +104,7 @@ class CommonMiddleware(MiddlewareMixin):
# a path with a slash appended.
if response.status_code == 404:
if self.should_redirect_with_slash(request):
- return self.response_redirect_class(self.get_full_path_with_slash(request))
+ return self.response_redirect_class(self.get_full_path_with_slash(request), request=request)
# Add the Content-Length header to non-streaming responses if not
# already set.
diff --git a/utils/http.py b/utils/http.py
index de1ea71..7414956 100644
--- a/utils/http.py
+++ b/utils/http.py
@@ -43,6 +43,9 @@ RFC3986_SUBDELIMS = "!$&'()*+,;="
FIELDS_MATCH = re.compile('[&;]')
+# IE11 on Win 7/8/8.1 doesn't support 307/308 redirect
+OLD_IE_MATCH = re.compile(r'Windows NT 6\.\d;.+Trident')
+
@keep_lazy_text
def urlquote(url, safe='/'):
@@ -456,3 +459,11 @@ def escape_leading_slashes(url):
if url.startswith('//'):
url = '/%2F{}'.format(url[2:])
return url
+
+def is_new_redirect_supported(request):
+ """
+ Return user agent support new redirect status code (307/308).
+ """
+ if not request:
+ return False
+ return not OLD_IE_MATCH.search(request.META['HTTP_USER_AGENT'])
\ No newline at end of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment