20

How do I configure the app.yaml file to redirect all URLs to another URL? For example I want http://test.appspot.com/hello or http://test.appspot.com/hello28928723 to redirect to http://domain.com.

I am only serving static files at the moment. Here is my app.yaml file:

application: testapp
version: 1
runtime: python
api_version: 1

handlers:
- url: (.*)/
  static_files: static\1/index.html
  upload: static/index.html

- url: /
  static_dir: static
lucrussell
  • 4,754
  • 2
  • 30
  • 38
mistero
  • 4,639
  • 8
  • 25
  • 27

7 Answers7

40

Webapp2 has a built-in redirect handler

No need to roll your own handler; webapp2 already comes with one.

application = webapp2.WSGIApplication([
    webapp2.Route('/hello', webapp2.RedirectHandler, defaults={'_uri':'http://domain.com'}),
    webapp2.Route('/hello28928723', webapp2.RedirectHandler, defaults={'_uri':'http://domain.com'}),
], debug=False)

The _uri argument is what the RedirectHandler class uses to define the destination. It took a lot of Google Fu to find the documentation on this but it works flawlessly in my app.

Update:

I assumed you're aware of this but you need to change your catch-all route from:

- url: /
  static_dir: static

To (python27 version):

- url: /.*
  script: main.application

Or: (pre python27 version)

- url: /.*
  script: main.py

main.py is the file containing the request handler + routes.

Note: There is no static-only way to handle redirects on GAE because of the nature of static files. Basically, there's no way to do a redirect in app.yaml alone.

Evan Plaice
  • 13,310
  • 4
  • 70
  • 94
  • 2
    This handles get/post/etc... It's basically the 'proper' way to do a 301 (permanent) redirect in GAE. – Evan Plaice May 04 '12 at 17:34
  • It's important to note that apparently App Engine doesn't support redirecting to static files/directories. I couldn't get the redirect to work. I kept getting these errors in my logs: "File referenced by handler not found: main.app". Finally, I found this, which confirmed that static files are not accessible to handlers: http://stackoverflow.com/questions/8734040/google-app-engine-static-pages-python-2-5-directories-etc. – Stephen Kaiser Nov 27 '13 at 19:20
  • @StephenKaiser Technically, it's not a redirect but you could define a new route in app.yaml that points from the old URI to the new one. Due to the architecture and the way static files are handled there's no way to define an actual 301/302 redirect on static files. – Evan Plaice Feb 04 '14 at 18:34
  • I think hello28928723 was just an example, he wanted to redirect all requests. – Jonny Apr 15 '14 at 01:55
  • @Jonny There's a significant difference between how static and non-static files are handled on GAE. You could add a non-static handle in the list above the static handler specifically to catch just redirects. Either way, it's important to understand how and why static files are handled different in GAE. App.yaml is basically an instruction set for a reverse proxy where all static files are actually stored on a static file cache separately from the non-static files. 302/301 redirects aren't possible until you hit the a http server (ie not the static cache). – Evan Plaice Dec 15 '14 at 05:53
  • I tried your first example `RedirectHandler` and got `File "/usr/local/lib/python2.7/dist-packages/webapp2_extras/routes.py", line 157, in __init__ setattr(route, self._attr, prefix + getattr(route, self._attr)) TypeError: cannot concatenate 'str' and 'type' objects` – Christian Feb 16 '16 at 12:00
9

All you need (replace app-id, http://example.com):

  • app.yaml:

    application: app-id
    version: 1
    runtime: python27
    api_version: 1
    threadsafe: false
    
    handlers:
    - url: /.*
      script: main.py
    
  • main.py:

    from google.appengine.ext import webapp
    from google.appengine.ext.webapp.util import run_wsgi_app
    
    class AllHandler(webapp.RequestHandler):
        def get(self):
            self.redirect("http://example.com", True)
    
    application = webapp.WSGIApplication([('/.*', AllHandler)])
    
    def main():
        run_wsgi_app(application)
    
    if __name__ == "__main__":
        main()
    
feklee
  • 7,203
  • 9
  • 48
  • 67
  • suggest adding "secure: optional" to the app.yaml handler so that https works also. – Jay Lee Nov 21 '14 at 14:49
  • "secure: optional" is the default when not provided (https://cloud.google.com/appengine/docs/python/config/appconfig#Python_app_yaml_Secure_URLs) – qix Sep 03 '15 at 09:11
5

you can redirect all requests easily with a python handler. Something like

class FormHandler(webapp.RequestHandler):
  def post(self):
    if processFormData(self.request):
      self.redirect("http://domain.com")
diega
  • 603
  • 3
  • 9
  • 9
    This answer is incomplete - that code snippet is insufficient on its own to redirect reqeusts. Also, what about get requests? – Brian Leathem May 01 '12 at 22:50
  • 1
    @BrianLeathem Just posted a [complete example](http://stackoverflow.com/a/18297787/282729). – feklee Aug 18 '13 at 09:50
4

Here is a python script that will do the redirect:

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class MainPage(webapp.RequestHandler):
  def get(self, path):
    self.redirect("http://example.com", permanent=True)
  def head(self, path):
    self.redirect("http://example.com", permanent=True)

application = webapp.WSGIApplication(
            [
                (r'^(.*)', MainPage)
            ])

def main():
   run_wsgi_app(application)

if __name__ == "__main__":
    main()
Brian Leathem
  • 4,525
  • 1
  • 22
  • 44
3

If you want a static-files-only way to do "redirects" then do this:

In the app.yaml, put this as the catch-all, at the end of the file:

-   url: /.*
    static_files: root/redirect.html
    upload: root/redirect.html

Then in the root/redirect.html file, put this:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="refresh" content="0;URL=/" />
        <script>
            location.replace("/");
        </script>
    </head>
    <body></body>
</html>

This example will redirect all unknown URLs to the root (i.e., / ). If you want another URL, just substitute http://mydomain.com in the appropriate places.

Ron
  • 3,009
  • 1
  • 16
  • 21
0

Riffing off Evan's answer, to redirect all requests you could use regexes to do something like:

import webapp2
from webapp2_extras.routes import RedirectRoute

app = webapp2.WSGIApplication([
     RedirectRoute('/<:.*>', redirect_to='/')
    ], debug=False)

For official docs check out:

https://webapp-improved.appspot.com/api/webapp2_extras/routes.html

https://webapp-improved.appspot.com/api/webapp2.html#webapp2.Route.init

qix
  • 6,008
  • 1
  • 44
  • 58
0

The redirect handler for webapp2 (webapp2.RedirectHandler) mentioned in a previous answer will not work for post requests, as it does not contain a post method (see https://github.com/GoogleCloudPlatform/webapp2/blob/master/webapp2.py), so you will need to roll your own python handler if concerned with posts. Something like the following:

import webapp2

class MainPage(webapp2.RequestHandler):


    def post(self):
        self.redirect('http://example.com')


application = webapp2.WSGIApplication([
('/.*', MainPage)
], debug=False)
Conor Muldoon
  • 114
  • 1
  • 3