Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Block requests from *.appspot.com and force custom domain in Google App Engine

How can I prevent a user from accessing my app at example.appspot.com and force them to access it at example.com? I already have example.com working, but I don't want users to be able to access the appspot domain. I'm using python.

like image 849
Joshua Patton Avatar asked Sep 01 '09 21:09

Joshua Patton


2 Answers

You can check if os.environ['HTTP_HOST'].endswith('.appspot.com') -- if so, then you're serving from something.appspot.com and can send a redirect, or otherwise alter your behavior as desired.

You could deploy this check-and-redirect-if-needed (or other behavior alteration of your choice) in any of various ways (decorators, WSGI middleware, inheritance from an intermediate base class of yours that subclasses webapp.RequestHandler [[or whatever other base handler class you're currently using]] and method names different than get and post in your application-level handler classes, and others yet) but I think that the key idea here is that os.environ is set by the app engine framework according to CGI standards and so you can rely on those standards (similarly WSGI builds its own environment based on the values it picks up from os.environ).

like image 145
Alex Martelli Avatar answered Sep 30 '22 10:09

Alex Martelli


The code posted above has two problems - it tries to redirect secure traffic (which isn't supported on custom domains), and also your cron jobs will fail when Google call them on your appspot domain and you serve up a 301.

I posted a slightly modified version to my blog: http://blog.dantup.com/2009/12/redirecting-requests-from-appid-appspot-com-to-a-custom-domain

I've included the code below for convenience.

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

def run_app(url_mapping):
    application = webapp.WSGIApplication(url_mapping, debug=True)
    application = redirect_from_appspot(application)
    run_wsgi_app(application)

def redirect_from_appspot(wsgi_app):
    """Handle redirect to my domain if called from appspot (and not SSL)"""
    from_server = "dantup-blog.appspot.com"
    to_server = "blog.dantup.com"

    def redirect_if_needed(env, start_response):

        # If we're calling on the appspot address, and we're not SSL (SSL only works on appspot)
        if env["HTTP_HOST"].endswith(from_server) and env["HTTPS"] == "off":

            # Parse the URL
            import webob, urlparse
            request = webob.Request(env)
            scheme, netloc, path, query, fragment = urlparse.urlsplit(request.url)
            url = urlparse.urlunsplit([scheme, to_server, path, query, fragment])

            # Exclude /admin calls, since they're used by Cron, TaskQueues and will fail if they return a redirect
            if not path.startswith('/admin'):
                # Send redirect
                start_response("301 Moved Permanently", [("Location", url)])
                return ["301 Moved Peramanently", "Click Here %s" % url]

        # Else, we return normally
        return wsgi_app(env, start_response)

    return redirect_if_needed
like image 28
Danny Tuppeny Avatar answered Sep 30 '22 08:09

Danny Tuppeny