content_type application/problem+json

169 views
Skip to first unread message

webm...@johlia.de

unread,
Nov 14, 2017, 10:12:14 AM11/14/17
to pylons-discuss
Hi all,

I have a pyramid application. How can I change the content_type to problem+json (as defined in: https://tools.ietf.org/html/rfc7807#page-9)

My code looks like this:
from pyramid.httpexceptions import HTTPNotFound
def error_handler(self, message):
        response
= HTTPNotFound()
        response
.body = dumps({'message': message})
        response
.content_type = 'application/json'
       
raise response

Changing the content_type to application/problem+json doesn't work.

Regards,
Sascha

Tres Seaver

unread,
Nov 15, 2017, 10:06:55 AM11/15/17
to pylons-...@googlegroups.com
On 11/14/2017 09:25 AM, webm...@johlia.de
wrote:

> I have a pyramid application. How can I change the content_type to
> problem+json (as defined in: https://tools.ietf.org/html/rfc7807#page-9)

Interesting -- thanks for pointing that out! I'd never come across that
RFC before.

> My code looks like this:
> from pyramid.httpexceptions import HTTPNotFound
> def error_handler(self, message):
> response = HTTPNotFound()
> response.body = dumps({'message': message})
> response.content_type = 'application/json'
> raise response
>
> Changing the content_type to application/problem+json doesn't work.

'HTTPExecption.prepare'[1] is overriding that content type based on the
'Accept:' header detection. Making that method aware of possible extension
types seems like a reasonable choice: the fastest way to get that in place
would be a pull request with tests.

In the meanwhile, ISTM that you'll either need to monkey-patch
'HTTPResponse.prepare' or else stop using exception types which derive from
'HTTPException'. E.g.:

from pyramid.response import Response

class ProblemResponse(Response, Exception):
pass

def error_handler(self, message):
raise ProblemResponse(
body=dumps({'message': message},
status='404 Not Found',
content_type = 'application/problem+json',
)


[1]https://github.com/Pylons/pyramid/blob/cc6a6ed60260b0391aa38f372b26311d58edf0d6/pyramid/httpexceptions.py#L248-L316


Tres.
--
===================================================================
Tres Seaver +1 540-429-0999 tse...@palladion.com
Palladion Software "Excellence by Design" http://palladion.com

Bert JW Regeer

unread,
Nov 15, 2017, 1:44:11 PM11/15/17
to pylons-...@googlegroups.com

On Nov 15, 2017, at 08:05, Tres Seaver <tse...@palladion.com> wrote:

On 11/14/2017 09:25 AM, webm...@johlia.de
wrote:

I have a pyramid application. How can I change the content_type to
problem+json (as defined in: https://tools.ietf.org/html/rfc7807#page-9)

Interesting -- thanks for pointing that out!  I'd never come across that
RFC before.

My code looks like this:
from pyramid.httpexceptions import HTTPNotFound
def error_handler(self, message):
       response = HTTPNotFound()
       response.body = dumps({'message': message})
       response.content_type = 'application/json'
       raise response

Changing the content_type to application/problem+json doesn't work.

'HTTPExecption.prepare'[1] is overriding that content type based on the
'Accept:' header detection.  Making that method aware of possible extension
types seems like a reasonable choice:  the fastest way to get that in place
would be a pull request with tests.


This should be checking if the response already has a body, in which case prepare won’t do any work…

Since the response.body is already set, that check should just short-circuit prepare and not do anything.

The issue I think here is that he is “raising” the HTTPNotFound() instead of just returning it. At some point this HTTPNotFound that you’ve created needs to be sent back as a response.

@exception_view_config(HTTPNotFound)
def ret_error(exc, request):
    return exc

For example will return the HTTPNotFound that was raised elsewhere in your code. Body/content_type will stay in tact.

If you don’t register an exception view for HTTPNotFound your raise will get caught by the exception view tween, and it will try to find a view for it, and upon failure it will raise a HTTPNotFound.


In the meanwhile, ISTM that you'll either need to monkey-patch
'HTTPResponse.prepare' or else stop using exception types which derive from
'HTTPException'.  E.g.:

   from pyramid.response import Response

   class ProblemResponse(Response, Exception):
       pass

   def error_handler(self, message):
       raise ProblemResponse(
           body=dumps({'message': message},
           status='404 Not Found',
           content_type = 'application/problem+json',
       )


[1]https://github.com/Pylons/pyramid/blob/cc6a6ed60260b0391aa38f372b26311d58edf0d6/pyramid/httpexceptions.py#L248-L316


Tres.
--
===================================================================
Tres Seaver          +1 540-429-0999          tse...@palladion.com
Palladion Software   "Excellence by Design"    http://palladion.com

--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discus...@googlegroups.com.
To post to this group, send email to pylons-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/ouhl59%242cf%241%40blaine.gmane.org.
For more options, visit https://groups.google.com/d/optout.

Michael Merickel

unread,
Nov 15, 2017, 2:52:33 PM11/15/17
to Pylons
The issue I think here is that he is “raising” the HTTPNotFound() instead of just returning it. At some point this HTTPNotFound that you’ve created needs to be sent back as a response.

Ok first, Pyramid already has a HTTPException handler which will catch and return the exception as a response so this @exception_view_config is not necessary.

Second, everything actually works completely fine and whatever Sascha is doing in his app is breaking things outside of his pasted example. You can see below this example works as intended:

import json
from pyramid.httpexceptions import HTTPNotFound
from pyramid.view import view_config

@view_config(route_name='problem')
def problem_view(request):
    exc = HTTPNotFound()
    exc.text = json.dumps({'message': 'foobar'})
    exc.content_type = 'application/problem+json'
    raise exc

if __name__ == '__main__':
    from pyramid.config import Configurator
    from waitress import serve

    config = Configurator()
    config.add_route('problem', '/problem')
    config.scan(__name__)
    app = config.make_wsgi_app()

    serve(app)

HTTP/1.1 404 Not Found
Content-Length: 21
Content-Type: application/problem+json
Date: Wed, 15 Nov 2017 19:51:20 GMT
Server: waitress

{"message": "foobar"}%

- Michael


To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discuss+unsubscribe@googlegroups.com.
To post to this group, send email to pylons-discuss@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discuss+unsubscribe@googlegroups.com.
To post to this group, send email to pylons-discuss@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/9D026DB3-6B57-4EC3-B09E-8A19FA7E7E10%400x58.com.

webm...@johlia.de

unread,
Nov 16, 2017, 2:27:20 AM11/16/17
to pylons-discuss
Hi Michael,

yes you are right. The code works as expected.
The guys from the quality control tested this code with the firefox, and changing the content_type won't work.(e.g. Chrome can handle that)
I kicked out the Selenium/Firefox tests....

But finally this is a REST-API...so curl and chrome should be enough.

Regards,
Sascha

@All: Thx
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discus...@googlegroups.com.
To post to this group, send email to pylons-...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discus...@googlegroups.com.
To post to this group, send email to pylons-...@googlegroups.com.

Michael Merickel

unread,
Nov 16, 2017, 11:10:03 AM11/16/17
to Pylons
The guys from the quality control tested this code with the firefox, and changing the content_type won't work.(e.g. Chrome can handle that)
I kicked out the Selenium/Firefox tests....

The network inspector in firefox shows it receiving the correct content type. I assume this is just an issue with whatever AJAX library you are using that isn't properly exposing the headers.

To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discuss+unsubscribe@googlegroups.com.
To post to this group, send email to pylons-discuss@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/d755b129-1c4d-4f55-aba4-a08b6bf5d54f%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages