Search code examples
pythongoogle-app-engineyamlwebapp2

Catch static 'file not found' errors


I have a 'catch-all' regex for an error handler like this:

(r'/.*', errors.Error)

which is listed after all others, in order to match "everything else".

This works as intended to fail gracefully when a page does not exist.

However, I also have a static file directory, uploaded like this:

handlers:
- url: /files
  static_dir: files

Thus, if I attempt to load a URL in /files/ that does not correspond to an existing file in that directory, I get an:

Error: Not Found

The requested URL was not found on this server.

Without having to list each file to upload separately, how can I catch this error; ideally with the same handler errors.Error above?


Solution

  • There's no good way to do this, unfortunately. The feature request is here: https://code.google.com/p/googleappengine/issues/detail?id=8380&q=type%3DFeature%20error%20404&colspec=ID%20Type%20Component%20Status%20Stars%20Summary%20Language%20Priority%20Owner%20Log

    There is no way to configure either a custom handler or a static error page for 404's due to files not being present in a static_dir. The same is true for static_files if the URL matches anything under the subpath, which is equivalent to static_dir:

    handlers:
    - url: /files/(.*)
      static_files: files/\1
      upload: files/.*
    

    The URL path matches the special static handler's URL pattern. Then the static handler realizes that the requested file doesn't exist. Control does not return to the routing logic, nor is there an opportunity to customize the static handler's response. The static handler only returns a generic 404.

    If the URL pattern for static_files matches exactly the filenames that exist, then URL paths that don't match will fall through to subsequent handlers, including possibly a catch-all at the bottom. But that's effectively listing all of the static files in the config file individually:

    handlers:
    - url: /files/(foo.png|bar.js|baz.css)
      static_files: files/\1
      upload: files/.*
    - url: .*
      script: errorhandler.app
    
    # Or for a static error page:
    - url: .*
      static_files: error.html
      upload: error.html
    

    Also unfortunately, error_handlers: does not help, because it does not yet support customizing 404's. Notably, the 404 returned by App Engine if none of the handlers: match the URL is also generic and can't yet be customized either.

    The only way to meet this requirement completely without listing the static filenames in a handler's URL pattern is to not use static files, but instead use an app handler to serve the static data out of application files (and serve the custom 404 message if not found).

    handlers:
    - url: .*
      script: filehandler.app