Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extensible HTTP Errors #1455

Closed
jvanasco opened this issue Nov 12, 2014 · 3 comments
Closed

Extensible HTTP Errors #1455

jvanasco opened this issue Nov 12, 2014 · 3 comments

Comments

@jvanasco
Copy link
Contributor

This idea goes in line with the following merged Pull Request #1372

A shortcoming of Pyramid's implementation of HTTP Status Codes is that it only supports a subset of official extensions. There are a handful of "unofficial" status codes that are widely used.

Referencing the Wikipedia entry: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes here are some popular examples:

• "420 Enhance Your Calm" Twitter uses this instead of a 429
• "420 Method Failure" Some versions of Spring use this.
• 440-499 - various framework specific
• 520-524 - specific to CloudFlare
• 598-599 - specific to Microsoft

While a developer shouldn't issue these special status codes themselves, they might have very good reasons to mimic existing services and their status codes (ie, for offline unit and integration tests that process foreign APIs). The current approach also means that Pyramid needs to constantly keep up with evolving standards to make the HTTP Exceptions available.

So I'd like to suggest a possible solution -- offering a factory method to create classes if not defined.

Here's a rough idea that would allow an undefined 420 exception to be raised as:

exception_response(420, title='Enhance Your Calm')

def HttpExceptionFactory(name, BaseClass):
    def __init__(self, **kwargs):
        assert 'code' in kwargs
        assert 'title' in kwargs
        for key, value in kwargs.items():
            if key in ('code', 'title'):
                setattr(self, key, value)
                del kwargs[key]
        BaseClass.__init__(self, **kwargs)
    newclass = type(name, (BaseClass,),{"__init__": __init__})
    return newclass    

def exception_response(status_code, **kw):
    """Creates an HTTP exception based on a status code. Example::
        raise exception_response(404) # raises an HTTPNotFound exception.
        The values passed as ``kw`` are provided to the exception's constructor.
    """
    if status_code in status_map:
        exc = status_map[status_code](**kw)
    else:
        _title = "HTTP Error"
        if 'title' in kw:
            _title = kw['title']
        baseClass = HTTPException
        if status_code >= 400 and status_code <= 499:
            baseClass = HTTPClientError
        elif status_code >= 500 and status_code <= 599:
            baseClass = HTTPServerError
        excClass = HttpExceptionFactory('CustomClass', baseClass)
        kw['code'] = status_code
        kw['title'] = _title
        exc = excClass(**kw)
    return exc
@mmerickel
Copy link
Member

Since this isn't mutating any module state or creating any global classes then I don't really have a problem with it. I'd add support for the 1xx and 2xx base classes as well just to say you did. Also I doubt that factory works on python 3 as-is.

@mmerickel
Copy link
Member

It looks like there's no interest in working on this over the last 2 years. Feel free to submit a PR and we can reopen this issue.

@digitalresistor
Copy link
Member

As a side note, HTTP2 does away with custom status texts... The only thing that is sent to the client is the status code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants