Convert Response to HTTP, and a JSON error response

Skip to first unread message

Mike Orr

unread,
Jan 10, 2019, 11:57:01 PM1/10/19
to pylons-...@googlegroups.com
Is there a simple way to convert a Response to an HTTP string; i.e.,
with headers and a body like it would send to the client?

I have a JSON backend view that sends an HTTP exception like this:

# HTTP 422, simulating a validation error
jreq = {"email": "m...@example.com", "errors": {"email": "Test error."}}
raise pyramid.httpexceptions.HTTPUnprocessableEntity(json=jreq)

The frontend makes an AJAX call using Backbone Model.save(), and in
the error callback the response is status 422 as it should be, but it
doesn't appear to contain the data. .responseJSON contains the kind of
things that appear on an exception page, and my data object doesn't
appear to be anywhere.

So I wrote a little Python program to see what the exception object
contains, and its '_app_iter' attribute contains the expected JSON.
Then I wanted to see what kind of HTTP document it would produce, and
I realized I don't know how to do that on the console without a WSGI
server.

I looked in the httpexceptions and response docs and didn't see any
related method. I then thought maybe it's just 'str()'. But 'str()'
returns "Unable to process the contained instructions". Curious. I
then looked at the 'wsgiref' docs but didn't see anything useful. Is
there a function or method that does this, or only a WSGI server has
the code?

Second, what is the solution to my underlying problem? I want to echo
back the input items and add an "errors" key containing the errors for
the invalid fields. I read that HTTP 422 Unprocessable Entity is the
correct response to a request that contains syntactically valid JSON
but the data values are invalid.

--
Mike Orr <slugg...@gmail.com>

Michael Merickel

unread,
Jan 11, 2019, 11:32:31 AM1/11/19
to Pylons
Your frontend that's making the ajax call is likely not configuring the accept header appropriately to prefer application/json content.

--
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/CAH9f%3Dup9q%3D5tKHw-pv5Fgx6pXm77R08tROxPd%2BLrfKrtuiBEMA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Arndt Droullier

unread,
Jan 11, 2019, 12:08:14 PM1/11/19
to Pyramid on google groups
Am Fr., 11. Jan. 2019 um 05:57 Uhr schrieb Mike Orr <slugg...@gmail.com>:
Is there a simple way to convert a Response to an HTTP string; i.e.,
with headers and a body like it would send to the client?

I have a JSON backend view that sends an HTTP exception like this:

# HTTP 422, simulating a validation error
jreq = {"email": "m...@example.com", "errors": {"email": "Test error."}}
raise pyramid.httpexceptions.HTTPUnprocessableEntity(json=jreq)

The frontend makes an AJAX call using Backbone Model.save(), and in
the error callback the response is status 422 as it should be, but it
doesn't appear to contain the data. .responseJSON contains the kind of
things that appear on an exception page, and my data object doesn't
appear to be anywhere.

I'm not sure how preconfigured exceptions like HTTPUnprocessableEntity handle data but
if you return a custom HTTP Response with status=422 and json data it works. 

But most JS Frameworks do not automatically parse the orginal json body if the HTTP
status is not OK (200 ... 299). You will have to get the body and parse the json manually in
your frontend code.
Maybe that's the issue here?

Arndt.



Jonathan Vanasco

unread,
Jan 11, 2019, 12:27:59 PM1/11/19
to pylons-discuss
To accomplish something similar, i use a mix of custom exceptions and pyramid's exception handling.

I have a class in my exceptions.py like this...

class ViewExceptionJsonForm(Exception):
    def __init__(self, ... ):
        ... setup with args, which might contain the Form, a Wrapped Exception, etc

In my view I would raise an error...

    @view_config(route="my_view")
    def my_view(self, req):
        ...
        if form.errors:
            raise ViewExceptionJsonForm(form=form)

And then I map it to a custom exception handler, which does everything for me...

@view_config(context=ViewExceptionJsonForm, renderer='json')
def exception_view__JsonForm(exc, request):
    request.response.status_code = xyz
    rval = new_rval()
    rval = {...}
    # populate rval based on `exc`
    return rval


Whenever I have an issue processing an API form, I raise this exception... and then the pyramid internals handle everything else. It's pretty great!

But as Michael noted, you probably have an issue with the frontend not having an appropriate accept header (or the request is being made for a non-json route/context if you're supporting stuff like that).
Reply all
Reply to author
Forward
0 new messages