[Django] #32982: Tighten up the check for status codes in HttpResponse

93 views
Skip to first unread message

Django

unread,
Aug 2, 2021, 9:24:55 PM8/2/21
to django-...@googlegroups.com
#32982: Tighten up the check for status codes in HttpResponse
-------------------------------------+-------------------------------------
Reporter: Abhyudai | Owner: nobody
Type: Bug | Status: new
Component: HTTP | Version: dev
handling |
Severity: Normal | Keywords: http, status code
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
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.
{{{#!python
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 [https://docs.python.org/3/library/http.html#http.HTTPStatus
HTTPStatus] class from the `http` module should probably help us get
around the problem.

{{{#!sh
>>> 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

{{{#!python
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

{{{#!python
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()
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/32982>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Aug 3, 2021, 12:39:13 AM8/3/21
to django-...@googlegroups.com
#32982: Tighten up the check for status codes in HttpResponse
-------------------------------------+-------------------------------------
Reporter: Abhyudai | Owner: nobody
Type: | Status: closed
Cleanup/optimization |
Component: HTTP handling | Version: dev
Severity: Normal | Resolution: wontfix

Keywords: http, status code | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* status: new => closed
* type: Bug => Cleanup/optimization
* resolution: => wontfix


Comment:

Thanks for the ticket, however HTTP status codes are extensible (see
[https://datatracker.ietf.org/doc/html/rfc7231#section-6 RFC 7231]):
{{{
HTTP status codes are extensible. HTTP clients are not required to
understand the meaning of all registered status codes, though such
understanding is obviously desirable. However, a client MUST
understand the class of any status code, as indicated by the first
digit, and treat an unrecognized status code as being equivalent to
the x00 status code of that class, with the exception that a
recipient MUST NOT cache a response with an unrecognized status code.

For example, if an unrecognized status code of 471 is received by a
client, the client can assume that there was something wrong with its
request and treat the response as if it had received a 400 (Bad
Request) status code. The response message will usually contain a
representation that explains the status.
}}}
I see no reason for additional validation and complicating users code.

--
Ticket URL: <https://code.djangoproject.com/ticket/32982#comment:1>

Django

unread,
Aug 31, 2021, 5:12:57 AM8/31/21
to django-...@googlegroups.com
#32982: Tighten up the check for status codes in HttpResponse
-------------------------------------+-------------------------------------
Reporter: Abhyudai | Owner: nobody
Type: | Status: closed
Cleanup/optimization |
Component: HTTP handling | Version: dev
Severity: Normal | Resolution: wontfix
Keywords: http, status code | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Adam Johnson):

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 .

--
Ticket URL: <https://code.djangoproject.com/ticket/32982#comment:2>

Reply all
Reply to author
Forward
0 new messages