Reputation: 3580
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 -
Upvotes: 40
Views: 34093
Reputation: 15159
I have reviewed all the above given answers and used the following at the end as the most universal 404 solution:
Add this link at the end of app.yaml
- url: /(.*)
script: 404.app
and create 404.py
with the following content
import webapp2
from google.appengine.ext.webapp import template
class NotFound(webapp2.RequestHandler):
def get(self):
self.error(404)
self.response.out.write(template.render('404.html', {}))
app = webapp2.WSGIApplication([
('/.*', NotFound)
], debug=True)
This will display contents of 404.html
file with 404 error code.
The advantage of this solution is simplicity, correctness of bahaviour and flexibility, as it allows to use a static 404.html
file as error page content.
I also want to warn against some of the solutions suggested above.
Custom Error Responses
don not work with 404 errorUpvotes: 2
Reputation: 1128
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
Upvotes: 27
Reputation: 3758
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
Upvotes: 3
Reputation: 3931
My approach is to handle both 404 and permanent redirects in a catch all handler that I put as the last one. This is usefull when I redesign and app and rename/substitute urls:
app = webapp2.WSGIApplication([
...
...
('/.*', ErrorsHandler)
], debug=True)
class ErrorsHandler(webapp2.RequestHandler):
def get(self):
p = self.request.path_qs
if p in ['/index.html', 'resources-that-I-removed']:
return self.redirect('/and-substituted-with-this', permanent=True)
else:
self.error(404)
template = jinja_environment.get_template('404.html')
context = {
'page_title': '404',
}
self.response.out.write(template.render(context))
Upvotes: 0
Reputation: 1510
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.
Upvotes: 4
Reputation: 993
I can't comment on jonmiddleton's answer, but the custom error responses is for App engine specific errors by the look of it. I don't see a way to specify a custom 404 page.
Django let's you specify one though.
Upvotes: 0
Reputation: 101149
The dev_appserver is already returning 404 responses for anything that doesn't match the mapping, or does match the mapping but doesn't exist. The 404 response itself has no body, but it's still a 404:
$ wget -O - http://127.0.0.1:8080/foo
--2010-10-28 10:54:51-- http://127.0.0.1:8080/foo
Connecting to 127.0.0.1:8080... connected.
HTTP request sent, awaiting response... 404
2010-10-28 10:54:51 ERROR 404: (no description).
$ wget -O - http://127.0.0.1:8080/foo/
--2010-10-28 10:54:54-- http://127.0.0.1:8080/foo/
Connecting to 127.0.0.1:8080... connected.
HTTP request sent, awaiting response... 404
2010-10-28 10:54:54 ERROR 404: (no description).
If you want to return a more user-friendly error page, follow jonmiddleton's advice and specify a custom 404 page.
Upvotes: 2
Reputation: 3538
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.
Upvotes: 4
Reputation: 17742
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.
Upvotes: 37