Google App Engine and 404 error
I've setup a static website on GAE using hints found elsewhere, but can't figure out how to return a 404 error. My app.yaml file looks like
- url: (.*)/
static_files: static\1/index.html
upload: static/index.html
- url: /
static_dir: static
with all the static html/jpg files stored under the static directory. The above works for files that exist, but returns a null length file if they don't. The answer is probably to write a python script to return a 404 error, but how do you set things up to serve the static files that exist but run the script for files that don't?
Here is the log from fetching a non-existent file (nosuch.html) on the development application server:
ERROR 2008-11-25 20:08:34,084 dev_appserver.py] Error encountered reading file "/usr/home/ctuffli/www/tufflinet/static/nosuch.html":
[Errno 2] No such file or directory: '/usr/home/ctuffli/www/tufflinet/static/nosuch.html'
INFO 2008-11-25 20:08:34,088 dev_appserver.py] "GET /nosuch.html HTTP/1.1" 404 -
Solution 1:
You need to register a catch-all script handler. Append this at the end of your app.yaml:
- url: /.*
script: main.py
In main.py you will need to put this code:
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class NotFoundPageHandler(webapp.RequestHandler):
def get(self):
self.error(404)
self.response.out.write('<Your 404 error html page>')
application = webapp.WSGIApplication([('/.*', NotFoundPageHandler)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
Replace <Your 404 error html page>
with something meaningful. Or better use a template, you can read how to do that here.
Please let me know if you have problems setting this up.
Solution 2:
google app engine now has Custom Error Responses
so you can now add an error_handlers section to your app.yaml, as in this example:
error_handlers:
- file: default_error.html
- error_code: over_quota
file: over_quota.html
Solution 3:
A significantly simpler way to do this without requiring any CPU cycles is to place this handler at the bottom of your app.yaml
- url: /.*
static_files: views/404.html
upload: views/404.html
This then allows you to place a static 404.html file in your views directory. No need for a python handler. Anything that isn't handled in your app.yaml already will hit that.
Solution 4:
You can create a function to handle your errors for any of the status codes. You're case being 404, define a function like this:
def Handle404(request, response, exception):
response.out.write("Your error message")
response.set_status(404)`
You can pass anything - HTML / plain-text / templates in the response.out.write
function. Now, add the following declaration after your app
declaration.
app.error_handlers[404] = Handle404
This worked for me.
Solution 5:
webapp2
provides the error_handlers
dictionary that you can use to serve custom error pages.
Example below:
def handle_404(request, response, exception):
logging.warn(str(exception))
response.set_status(404)
h = YourAppBaseHandler(request, response)
h.render_template('notfound')
def handle_500(request, response, exception):
logging.error(str(exception))
response.set_status(500)
h = YourAppBaseHandler(request, response)
h.render_template('servererror')
app = webapp2.WSGIApplication([
webapp2.Route('/', MainHandler, name='home')
], debug=True)
app.error_handlers[404] = handle_404
app.error_handlers[500] = handle_500
More details are available on webapp2
's documentation pages: http://webapp-improved.appspot.com/guide/app.html#error-handlers