App Engine 401/403 Status Codes Not Working on WebApp2
Question: 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](http://webapp-improved.appspot.com/guide/exceptions.html) 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
    


Answer: ~~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.

