Search code examples
google-app-enginehttp-status-codeswebapp2

App Engine 401/403 Status Codes Not Working on WebApp2


I am trying to raise a 401/403 status for when a user attempts to access something they don't have privileges to. I used the Webapp2 Exceptions example which generates the proper error codes for 404/500 "natural" events. Such as going to http://localhost:8080/nourl generates the proper 404 and messing up code generates a 500. But when I use the method such as below to set the code using self.error(XXX) I see the code in the console but it does not show up in the browser. EG If you leave self.error() empty it generates the proper 500 code. If you use self.error(500) the console outputs:

INFO     2012-05-09 18:25:29,549 dev_appserver.py:2891] "GET / HTTP/1.1" 500 -

But the browser is completely blank. Below is an example app that exhibits this behaviour. Simply change the self.error() line to the desired code and run. The expected result would be that it generates the proper response to the browser based on the code supplied, not just when a "natural" event occurs such as 404.

main.py

import webapp2
import wsgiref.handlers
import logging
from google.appengine.api import users


class HomeHandler(webapp2.RequestHandler):
    def get(self):
        user = users.get_current_user()
        if user:
            self.response.out.write("Hi :1", user.nickname)
        else:
            self.error(401)


app = webapp2.WSGIApplication([
    (r'/', HomeHandler),
], debug=True)


def handle_401(request, response, exception):
    logging.exception(exception)
    response.write("401 Error")
    response.set_status(401)


def handle_403(request, response, exception):
    logging.exception(exception)
    response.write("403 Error")
    response.set_status(403)


def handle_404(request, response, exception):
    logging.exception(exception)
    response.write("404 Error")
    response.set_status(404)


def handle_500(request, response, exception):
    logging.exception(exception)
    response.write("500 Error")
    response.set_status(500)

app.error_handlers[401] = handle_401
app.error_handlers[403] = handle_403
app.error_handlers[404] = handle_404
app.error_handlers[500] = handle_500


#  Run the application
def main():
    app.run()

app.yaml

application: 401test
version: 1
runtime: python27
api_version: 1
threadsafe: yes

libraries:
- name: webapp2
  version: latest

handlers:
- url: /.*
  script: main.app

Solution

  • you are using py27 with threadsafe environment. in app.yaml you set script: main.app so the code after app is defined is not executed.

    didn't test it but this should work:

    # create a bare app 
    bare_app = webapp2.WSGIApplication(debug=True)
    
    #define the error handlers
    def handle_401(request, response, exception):
        logging.exception(exception)
        response.write("401 Error")
        response.set_status(401)
    
    def handle_403(request, response, exception):
        logging.exception(exception)
        response.write("403 Error")
        response.set_status(403)
    
    
    def handle_404(request, response, exception):
        logging.exception(exception)
        response.write("404 Error")
        response.set_status(404)
    
    
    def handle_500(request, response, exception):
        logging.exception(exception)
        response.write("500 Error")
        response.set_status(500)
    
    # add the error handlers
    bare_app.error_handlers[401] = handle_401
    bare_app.error_handlers[403] = handle_403
    bare_app.error_handlers[404] = handle_404
    bare_app.error_handlers[500] = handle_500
    
    
    bare_app.router.add((r'/', HomeHandler))
    
    app = bare_app
    

    edit:
    use self.abort() instead of self.error()
    http://webapp-improved.appspot.com/guide/exceptions.html#abort

    you can see the difference in the source code:
    http://code.google.com/p/webapp-improved/source/browse/webapp2.py#574
    while self.error() sets the status code but clears the response, self.abort() executes the function that takes care of the error handling.