Table of contents
1.
Introduction 
2.
Error Handling 
2.1.
Anticipated Errors
2.1.1.
Example 1
2.1.2.
Example 2
2.2.
Unanticipated Errors
2.2.1.
Example 3
3.
Streaming the Response Body
3.1.
Normal CherryPy Response Process
3.2.
How Streaming Output Works with CherryPy 
3.2.1.
Example 4
3.3.
Response Time
4.
Frequently Asked Questions
4.1.
What is CherryPy?
4.2.
What are unanticipated errors?
4.3.
What is the default behavior in case an unanticipated error occurs?
4.4.
What is the response time in CherryPy?
4.5.
Why is streaming output difficult?
5.
Conclusion
Last Updated: Mar 27, 2024
Hard

Error Handling and Response Body in CherryPy

Author Teesha Goyal
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction 

CherryPy is a Python-based, object-oriented web application framework developed in 2002. CherryPy helps in speeding up the process of web application development by wrapping the HTTP protocols. 

This article will discuss the way to handle errors in CherryPy. We will also discuss the concept of streaming the response body and obtaining the response time in CherryPy. 

CherryPy

Check out this article to learn Why CherryPy is a good web application framework. 

Error Handling 

There are anticipated and unanticipated errors in CherrryPy. If a particular type of error occurs, it comes under anticipated, and CherryPy has a method to deal with such Errors. CherryPy also provides a mechanism to deal with unanticipated errors. Let us see how it does so. 

Error Handling

Anticipated Errors

CherryPy makes a web application seem like a rich python application. This means that, like any other Python application, you can raise a Python error or exception from your page handler. Depending on the type of error, CherryPy will catch it and convert it into HTTP messages.

It does so by using the HTTPError class. The HTTPError class has some responses immediately made when an error is raised. 

Example 1

class Root:
    @cherrypy.expose
    def demo(self, path):
        if not authorized():
            raise cherrypy.HTTPError(401, 'Unauthorized')
        try:
            file = open(path)
        except FileNotFoundError:
            raise cherrypy.HTTPError(404)
You can also try this code with Online Python Compiler
Run Code

 

HTTPError.handle is a context manager that allows exceptions raised in the app to be translated into an appropriate HTTP response.

Example 2

class Root:
    @cherrypy.expose
    def thing(self, path):
        with cherrypy.HTTPError.handle(FileNotFoundError, 404):
            file = open(path)

Unanticipated Errors

It should be noted that if an exception is thrown that is not caught by any other part of the application, then CherryPy will return the HTTP 500 error code by default by using “request.error_response”. This type of error is called an unanticipated error. 

You can also change the error behavior by replacing the “request.error_response” with your own code .

Example 3

from cherrypy import _cperror

def handle_error():
    cherrypy.response.status = 500
    cherrypy.response.body = [
        "<html><body>Hey! It seems like an Error Occurred! You are requested to refresh the tab </body></html>"
    ]

@cherrypy.config(**{'request.error_response': handle_error})
class Root:
    pass

 

You can see how easily you have created your function handle_error and defined it as an HTML file. This file is then linked to your request.error_response, which is displayed when any unanticipated error occurs. 

Streaming the Response Body

CherryPy manages HTTP requests, packing and unpacking the low-level details before passing control to your application's page handler, which generates the response body. It provides us the mechanism to return and yield the body content. 

CherryPy supports various return types, including string, list of strings, and file. Also, to stream the response body output, you have to use the yield method. By default, yield is set to off as it is not safe and easy to stream the output content. 

First, we will discuss how the “normal” CherryPy response process works, and after that, we will discuss how “streaming output” works with CherryPy.

Normal CherryPy Response Process

CherryPy acts as a middleman between the HTTP server and your application. The conversation between the page handler and the HTTP server is managed by CherryPy, as shown in the following image:

Normal CherryPy response process

As you can see, all the requests made by the client first reach CherryPy, and then to the application. A response is generated by the application and sent back to CherryPy, which thereby sends the response to the HTTP server. The HTTP server waits for the entire output to reach it, accumulates the output, and then sends it back to the client all at once. The output contains the status, headers, and the response body. This mechanism works well for static or simple pages.

Now we will discuss how streaming output works in CherryPy

How Streaming Output Works with CherryPy 

The streaming of the output is set to false by default. So, to stream the response body, you must first set the “response.stream” to True. Once this is done, the internal working changes and looks something like this:

Streaming Output

The main difference is that the HTTP server does not wait for the entire output to reach it before sending it back to the client. It first gets the status and headers, which it sends back to the client before the output is yielded. It is necessary for CherryPy to set the status and headers before producing any output. 

After the status and headers are set, the generator comes into the picture. The generator yields the output individually and produces the response body in pieces. It uses the next method to move ahead and continue to yield the output. A piece of output is yielded and sent to the HTTP server by the application code. 

The HTTP server writes the output to the client and requests for the generator.next() and the next piece is yielded by the application and sent to the HTTP server. This process continues until all the pieces of the output are not yielded and written to the client.

CherryPy steps out of the picture once the status and headers are set, and the output is started to be written down to the client. So, if any error occurs during this time, it is not observed by CherryPy. It directly reached the HTTP server. 

Now HTTP server does not know how to deal with errors. This is when errors like NotFound, InternalRedirect, HTTPError, and HTTPRedirect occur. You must return a generator that is separate from your page handler if you want to use a streaming generator while modifying headers.

Example 4

class Root:
    @cherrypy.expose
    def demo(self):
        cherrypy.response.headers['Content-Type'] = 'text/plain'
        if not authorized():
            raise cherrypy.NotFound()
        def content():
            yield "Hello, "
            yield "Ninja"
        return content()
    demo._cp_config = {'response.stream': True}
You can also try this code with Online Python Compiler
Run Code

Since streaming output is difficult, it must be used only when necessary. CherryPy allows the use of streaming output in situations like:

  • Your application takes a lot of time to gather the output before writing it to the client.
  • When you want something to be displayed fast on a web page, then some other details. 

 

It is advised to use buffer content in place of stream content. 

Response Time

To record the time at which the response began, a response in CherryPy includes an attribute response.time. 

Response Time

response.time = a time.time(), which marks the time at which the response has begun. 

Frequently Asked Questions

What is CherryPy?

CherryPy is a python-based, object-oriented web application framework developed in 2002. CherryPy helps in speeding up the process of web application development by wrapping the HTTP protocols. 

What are unanticipated errors?

If your application throws an exception that is not caught by any other part of the application, then CherryPy will return the HTTP 500 error code by default by using “request.error_response”. This type of error is called an unanticipated error. 

What is the default behavior in case an unanticipated error occurs?

When an unanticipated error occurs in CherryPy, it is treated as Error 500. It is similar to what is meant by “request.error_response”. We can also change the behavior by defining our functions and replacing “request.error_response” with them. 

What is the response time in CherryPy?

Response time is an attribute in CherryPy that records the time at which the response began. It gives a time.time() marking the starting time of the response.

Why is streaming output difficult?

When we are streaming the output, the response is not gathered together and written to the client at once. During the yielding time, if any error occurs it cannot be detected by CherryPy, but goes straight to the HTTP server, which is difficult and unsafe. 

Conclusion

This article discussed the way for handling errors in CherryPy. We also discussed the concept of streaming the response body and obtaining the response time in CherryPy. 

I hope you would have gained a better understanding of these topics now!

Are you planning to ace the interviews of reputed product-based companies like AmazonGoogleMicrosoft, and more? 

Attempt our Online Mock Test Series on Coding Ninjas Studio now!

Happy Coding!

Live masterclass