#32982 closed Cleanup/optimization (wontfix)
Tighten up the check for status codes in HttpResponse
Reported by: | Abhyudai | Owned by: | nobody |
---|---|---|---|
Component: | HTTP handling | Version: | dev |
Severity: | Normal | Keywords: | http, status code |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
As of now, all values in between the range 100 and 600 are allowed. https://github.com/django/django/blob/main/django/http/response.py#L123
I'm quoting the relevant section for potential ease of discussion here.
if not 100 <= self.status_code <= 599: raise ValueError('HTTP status code must be an integer from 100 to 599.')
Not all of them are valid, for example 111
is not a valid status code. The list of valid status code can be seen here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
Using the HTTPStatus class from the http
module should probably help us get around the problem.
>>> from http import HTTPStatus as status >>> status(111) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.8/enum.py", line 339, in __call__ return cls.__new__(cls, value) File "/usr/lib/python3.8/enum.py", line 663, in __new__ raise ve_exc ValueError: 111 is not a valid HTTPStatus >>> status(100) <HTTPStatus.CONTINUE: 100>
This will have a downside as to preventing a server that may probably be sending a custom status code in between 100
and 600
, which may raise an error in case this is allowed. For what it is worth, we already disallow values outside this range.
I think we can solve this issue, by introducing a method, something like verfiy_status_code
which does the default verification and may be overridden in case someone wants to.
Default implementation
from http import HTTPStatus as status class HttpResponseBase: def verify_status_code(self): if self.status is None: return try: self.status_code = int(status) except (ValueError, TypeError): raise TypeError('HTTP status code must be an integer.') try: status(self.status) except ValueError as exc: raise
Overriden implementation
from django.http import HttpResponseBase class CustomHttpResponse(HttpResponseBase): my_custom_codes = [111, 121] def verify_status_code(self): if self.status in self.my_custom_codes: return super().verify_status_code()
Change History (2)
comment:1 by , 3 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
Type: | Bug → Cleanup/optimization |
comment:2 by , 3 years ago
A concrete use case: htmx uses the non-standard status code 286 to mean "stop polling", and I use that from within Django: https://github.com/adamchainz/django-htmx#django_htmxhttphttpresponsestoppolling-typehttpresponse .
Thanks for the ticket, however HTTP status codes are extensible (see RFC 7231):
I see no reason for additional validation and complicating users code.