Rob
Rob

Reputation: 311

CherryPy HTTPError custom response handling (*NOT* HTML)

I'm having an issue providing custom response handling for cherrypy.HTTPError. The only content that I want displayed in the body of the response is a JSON-encoded dict (this is REST API). The source code seems to indicate that HTTPError.set_response() can be used to modify the cherrypy.response object ... to quote the comment in this method:

Modify cherrypy.response status, headers, and body to represent self. CherryPy uses this internally, but you can also use it to create an HTTPError object and set its output without *raising* the exception.

I have sub-classed HTTPError to provide my own body for the response. I call the base class methods to ensure that any necessary housekeeping takes place.

class APIError(cherrypy.HTTPError):
    def __init__(self, err_resp):
        super().__init__(status=err_resp['error_code'])
        self._api_err_resp = err_resp

    def set_response(self):
        super().set_response()
        response = cherrypy.serving.response
        response.body = json.dumps(self._api_err_resp).encode()

I can now call APIError without a problem, but the issue I have is that the CherryPy web server takes approx 10-15sec to respond to my client once my custom error is raised (I experience no delay if I use HTTPError). I've traced the source code, but can't find the cause of the delay.

Any help would be appreciated.

Rob

Upvotes: 5

Views: 1421

Answers (2)

Blindfreddy
Blindfreddy

Reputation: 712

I got it to work with this approach, which takes esp. into account jmpcm's comment on setting the content length:

class APIError(cherrypy.HTTPError):
    def __init__(self, status=500, message=None):
        super().__init__(status=status, message=message)
        self._json_error = json.dumps({'error': message}).encode('utf-8')
    def set_response(self):
        super().set_response()
        response = cherrypy.serving.response
        response.body = self._json_error
        response.headers["Content-Length"] = len(self._json_error)
        response.headers['Content-Type'] = 'application/json'

``

Upvotes: 0

576i
576i

Reputation: 8382

Using cherrypy 16.0.2 on Python 3.7.2, 64bit, windows7 subclassing HTTPError does not cause unusual waiting times. Maybe you should try with a current version of cherrypy.

This is the code I used to test it:

import cherrypy as cp 

class APIError(cp.HTTPError):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._json_error = kwargs

    def set_response(self):
        super().set_response()
        response = cp.serving.response
        response.body = json.dumps({'error': self._json_error}).encode('utf-8')

This example requires you to call APIError with the proper keywords status and message. For production use, I wrote a larger class where I pass status, json data and other data for logging and then call the super().__init__ with only the status code.

Upvotes: 1

Related Questions