Proxy incorrectly changes 301 redirects to 200 responses when using chunked encoding #115
-
I've identified what I believe is an issue where the proxy changes 301 redirects to 200 responses, but only when the response uses chunked encoding. This is maybe specifically in issue for Django applications, where the default Here's how to reproduce in a Django application. Note you must serve the application with gunicorn or another server that automatically switches to chunked encoding in this circumstance): urls.py: path("redirect_good/", views.redirect_good, name="redirect_good"),
path("redirect_bad/", views.redirect_bad, name="redirect_bad"),
path("redirect_result/", views.redirect_result, name="redirect_result"), view.py def redirect_good(request):
return HttpResponsePermanentRedirect("/redirect_result/")
def redirect_bad(request):
response = HttpResponsePermanentRedirect("/redirect_result/")
response.streaming = True
return response
def redirect_result(request):
return HttpResponse("It worked!") Basically,
Which correctly resolves https://lifeweeks.app/redirect_good/ But the second returns a 200:
Which results in an empty page https://lifeweeks.app/redirect_bad/ |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 4 replies
-
In case any other Django developers run into this, replacing CommonMiddleware with this one solves the broken class NoChunkedRedirectMiddleware(CommonMiddleware):
"""
Forces redirects to not use chunked encoding (which gunicorn does by default)
to workaround this bug: https://github.com/basecamp/kamal-proxy/discussions/115
"""
def process_response(self, request, response):
# Get the response from parent first (this creates redirects if needed)
response = super().process_response(request, response)
# Then fix chunked encoding if it's a redirect, except for test path
if response.status_code == 301:
response.streaming = False
if "Transfer-Encoding" in response:
del response["Transfer-Encoding"]
if not response.content:
response["Content-Length"] = "0"
return response |
Beta Was this translation helpful? Give feedback.
-
@czue thanks for reporting this. I've not been able to reproduce it by adding Could you share a full redirect response from your app that triggers this behavior? That is, not the response from the proxy, but the response your app generates directly. Thanks! |
Beta Was this translation helpful? Give feedback.
-
Thanks for taking a look. These are the same traces for what's running behind kamal-proxy. I don't see any other notable differences, but I'm definitely not an expert in this space. Did you also remove the content-length? Let me know if you need anything else! Failing URL:
Working URL:
|
Beta Was this translation helpful? Give feedback.
-
Arg. So I managed to create the project and reproduce the bug. Then, before sharing with you I thought I should check my kamal / proxy version. Turns out I was on an older one (2.2 / 8.0). After upgrading to the latest (2.5.3/8.4(?)) it's now working. So sorry for wasting your time and thanks for taking a serious look at it! If you ever do need to reproduce anything with Django in the future, maybe this repo will be helpful? https://github.com/czue/django-kamal-demo |
Beta Was this translation helpful? Give feedback.
Arg. So I managed to create the project and reproduce the bug. Then, before sharing with you I thought I should check my kamal / proxy version. Turns out I was on an older one (2.2 / 8.0). After upgrading to the latest (2.5.3/8.4(?)) it's now working.
So sorry for wasting your time and thanks for taking a serious look at it!
If you ever do need to reproduce anything with Django in the future, maybe this repo will be helpful? https://github.com/czue/django-kamal-demo