Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop request processing in CherryPy and return 200 response from a tool

My Question

I am looking for a way to stop request processing in a Tool without raising an exception. In other words: I want to stop the request befor it gets to the specified controller and return a 2xx status code?

Background

We want our application to support CORS and therefore the preflight request. The idea was to write a tool which hooks before_handler. If an OPTIONS request is made, return the relevant CORS-headers and exit.

The problem is, that I havn't found a way to stop the execution flow. This means that the original URL is processed, as it would be if requested normally. The point is: this could lead to security issues, as the preflight request is always made. This is what I have so far:

class CORSTool(cherrypy.Tool):
    def __init__(self):
        cherrypy.Tool.__init__(self, 'before_handler', self.insert_cors_header, priority=40)
        cherrypy.request.hooks.attach('before_handler', self.insert_cors_header, priority=40)

    def _setup(self):
        cherrypy.Tool._setup(self)

    def insert_cors_header(self):
        """
        Inserts the relevant CORS-Headers:
        - Access-Control-Allow-Origin: <from-config>
        - Access-Control-Allow-Methods: POST, GET, OPTIONS
        - Access-Control-Max-Age: 86400
        """
        if cherrypy.config.get('enable_cors') is True:
            if cherrypy.request.method.upper() == "OPTIONS":
                cherrypy.response.headers['Access-Control-Allow-Origin'] = cherrypy.config.get('cors_domains')
                cherrypy.response.headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
                cherrypy.response.headers['Access-Control-Max-Age'] = '86400'

                # Stop execution
                cherrypy.response.body = None
                cherrypy.response.status = 200
                cherrypy.response.finalize()

                # And NOW stop doing anything else...

Alternatives likely not working

I know that there is a cherrypy-cors plugin, but from the source I can't see how this stops the execution.

I also know that CherryPy has a MethodDispatcher, but that would mean a complete rewrite of our code.

Searching Stackoverflow I found this answer, however I don't want to "kill" the execution, I just want a way to prevent the handler from being called.

like image 810
Chris Avatar asked Aug 21 '15 06:08

Chris


1 Answers

Just have your Tool set request.handler = None. See Request.respond for the code which implements this and the CachingTool for an example:

    request = cherrypy.serving.request
    if _caching.get(**kwargs):
        request.handler = None
like image 73
fumanchu Avatar answered Sep 28 '22 09:09

fumanchu