Search code examples
pythongoogle-app-enginehttp-redirectwebapp2

App Engine: How to redirect from outside of a class


So I know you can redirect in GAE from within a class that inherits from webapp2.RequestHanlder using this:

class Foo(webapp2.RequestHandler):
    def get(self):
        self.redirect('https://google.com')

While this works, it would be great to be able to perform a redirect outside of a class.

For example, say you have the following code that is a global function - i.e. it does not exist inside of a class:

def fetch_url(url, method=urlfetch.GET, data=''):
    """Send a HTTP request"""

    result = urlfetch.fetch(url=url, method=method, payload=data,
                            headers={'Access-Control-Allow-Origin': '*'})

    return result.content

If you could redirect from the function, you could check the status code and redirect to an error page. E.g.

if result.status_code != 200:
    urllib2.urlopen('/error_page.html')
    return

Unfortunately, the above code does nothing in GAE and the following warning is generated.

WARNING  2014-05-22 21:58:24,364 urlfetch_stub.py:482] Stripped prohibited headers from URLFetch request: ['Host']

So is there a way to perform a redirect outside of a class?


Solution

  • You can make your own Exception subclass to handle redirects.

    The way I do this is to make my own subclass of webapp2.RequestHandler that overrides the handle_exception method (See the docs)

    class RedirectError(Exception):
        def __init__(self, new_url):
            self.new_url = new_url
    
    class MyWebappFramework(webapp2.RequestHandler):
        def handle_exception(self, exception, debug_mode):
            if isinstance(exception, RedirectError):
                self.redirect(exception.new_url)
            else:
                super(MyWebappFramework, self).handle_exception(exception, debug_mode)
    

    Using this functionality, you can actually make a wide range of custom exceptions to easily manage expectations. For example, you might also make a NotFound exception to set the status code to 404 and render a "Page not found" message.

    To make the redirect occur, raise the RedirectError.

    it's as simple as raise RedirectError("http://www.google.com").