Opened 14 years ago

Closed 11 years ago

#12747 closed New feature (fixed)

Custom HTTP status reason phrases are not supported

Reported by: Gustavo Narea Owned by: gisle
Component: HTTP handling Version: dev
Severity: Normal Keywords: http status, http status reason, http status reason phrase
Cc: akvadrako Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

At present, Django hard-codes the HTTP status reason phrases based on an integer that represents the HTTP status code, forcing the recommended phrases by the HTTP specification.

Note they are just the recommended/default phrases and developers should be allowed to override these phrases. For example, I may want to return the following and Django should allow me to do so:

403 Get out

Or,

200 Everything is fine

See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1

In order to support this, Django could have the following code in django.http:HttpResponse.__init__:

        if isinstance(status, basestring):
            # The status is given as a real HTTP status header, so we should
            # tell the code and the reason apart for Django:
            (status_code, status_reason) = status.split(" ", 1)
            status_code = int(status_code)
            self.status_reason = status_reason or None
        else:
            # The status has been given the old way supported by Django, simply
            # the status code as an integer:
            status_code = status
            self.status_reason = None

And the following on django.core.handlers.wsgi:WSGIHandler.__call__():

        if response.status_reason:
            status_text = "%s %s" % (response.status_code, response.status_reason)
        else:
            try:
                status_text = STATUS_CODE_TEXT[response.status_code]
            except KeyError:
                status_text = 'UNKNOWN STATUS CODE'

If any Django user wants to use this functionality before it gets implemented, they may use twod.wsgi: http://bitbucket.org/2degrees/twod.wsgi/

Attachments (3)

0001-Ticket-12747-Set-custom-status_text-message.patch (4.7 KB ) - added by gisle 14 years ago.
0002-Test-that-the-custom-response-shows-up-on-the-WSGI-l.patch (3.0 KB ) - added by gisle 14 years ago.
Test that the custom response shows up on the WSGI level as well
12747-3.diff (4.9 KB ) - added by Claude Paroz 11 years ago.
Updated patch, tuple instead of string

Download all attachments as: .zip

Change History (23)

comment:1 by Alex Gaynor, 14 years ago

Triage Stage: UnreviewedAccepted

comment:2 by gisle, 14 years ago

Owner: changed from nobody to gisle

comment:3 by gisle, 14 years ago

Needs tests: set

by gisle, 14 years ago

Test that the custom response shows up on the WSGI level as well

comment:4 by gisle, 14 years ago

Needs tests: unset

comment:5 by James Bennett, 14 years ago

milestone: 1.2

1.2 is feature-frozen, moving this feature request off the milestone.

in reply to:  5 comment:6 by Gustavo Narea, 14 years ago

Replying to ubernostrum:

1.2 is feature-frozen, moving this feature request off the milestone.

This can hardly be a feature. It's a fix for partially broken HTTP support.

comment:7 by Russell Keith-Magee, 14 years ago

@Gustavo:

Is there any condition under which the existing implementation will raise an error or cause data loss in the absence of a custom status message?

Is there any standard that is violated by not allowing a custom status message?

The answer to both of these questions is No. Therefore, this isn't a bug fix. It's a feature request.

It may be an extremely useful new feature, but that doesn't change the fact that it is still a feature, and Django 1.2 is feature frozen.

comment:8 by akvadrako, 13 years ago

Cc: akvadrako added

comment:9 by Matt McClanahan, 13 years ago

Severity: Normal
Type: New feature

comment:10 by patchhammer, 13 years ago

Easy pickings: unset
Patch needs improvement: set

0002-Test-that-the-custom-response-shows-up-on-the-WSGI-l.patch fails to apply cleanly on to trunk

comment:11 by Aymeric Augustin, 12 years ago

UI/UX: unset

Change UI/UX from NULL to False.

by Claude Paroz, 11 years ago

Attachment: 12747-3.diff added

Updated patch, tuple instead of string

comment:12 by Claude Paroz, 11 years ago

Patch needs improvement: unset
Version: 1.1master

Just attached an updated patch. I choose to pass a tuple as the status argument, instead of a string that has to be parsed, which is always fragile.

comment:13 by Aymeric Augustin, 11 years ago

I couldn't care less about this feature request, but the approach shown in the patch looks all right.

I don't have an opinion on using a string or a tuple or a new keyword argument to pass the status text.

The patch is out of date; otherwise, in the interest of crossing one ticket off the list, this is RFC.

comment:14 by Aymeric Augustin, 11 years ago

Actually, since this isn't a particularly useful feature, and I don't expect anyone to ever need it, it'd be nice if it didn't have any overhead.

in reply to:  14 comment:15 by Gustavo Narea, 11 years ago

Hi, aaugustin.

Replying to aaugustin:

Actually, since this isn't a particularly useful feature, and I don't expect anyone to ever need it, it'd be nice if it didn't have any overhead.

What do you mean by "overhead"? I think a new keyword argument would be cleaner, but I'm happy to update update the patch in either direction. Which is the approach you prefer?

Thanks.

comment:16 by Paul McNett <p@…>, 11 years ago

This is hackish, quickly written, and tested for only 10 minutes or so but I implemented custom status codes by monkeypatching the django.core.handlers.wsgi.STATUS_CODE_TEXT dict like:

import django.core.handlers.wsgi as wsgi

class NextDict(dict):
    def __init__(self, *args, **kwargs):
        self._nextdict = {}
        super(NextDict, self).__init__(*args, **kwargs)

    def set_next(self, key, value):
        """
        The next time this key is queried, return the passed value.
        After that, use the default.
        """
        self._nextdict[key] = value

    def __getitem__(self, key):
        if key in self._nextdict:
            v = self._nextdict[key]
            del(self._nextdict[key])
            return v
        return super(NextDict, self).__getitem__(key)

wsgi.STATUS_CODE_TEXT = NextDict(wsgi.STATUS_CODE_TEXT)

And then when I want my response to have a custom message for it's status code:

    class MyView(request):
        wsgi.STATUS_CODE_TEXT.set_next(200, "hello")
        return HttpResponse("hello again")

I googled for similar ideas and didn't find anyone doing this, so I thought it may give someone some ideas to develop this into a plugin or something. It wouldn't add overhead to the default (and reasonable) implementation, but would help some of us satisfy our requirements easily and without adding too much extra overhead...

comment:17 by Aymeric Augustin, 11 years ago

#20328 is a duplicate.

comment:18 by Anler Hp, 11 years ago

For the API of my company we use this feature in a lot of places.
One of the use cases is:
We have a courses resource, if the teacher tries to DELETE a course with enrolled users, we return a 400 Cannot delete course with students response.

comment:19 by Aymeric Augustin, 11 years ago

I'd like to stop seeing pull requests about this.

If you want to do it, this is how: https://github.com/django/django/pull/1154

comment:20 by Aymeric Augustin <aymeric.augustin@…>, 11 years ago

Resolution: fixed
Status: newclosed

In cb86f707a04e5635817d5f37a1443f9bf7d6af21:

Fixed #12747 -- Made reason phrases customizable.

Note: See TracTickets for help on using tickets.
Back to Top