Flask Snippets

Snippets are unofficial and unmaintained.

This is an archived view of user-submitted snippets. Despite being hosted on the Flask site, they are not official. No Flask maintainer has curated or checked the snippets for security, correctness, or design.

Fixing SCRIPT_NAME/url_scheme when behind reverse proxy

Posted by Peter Hansen on 2010-07-21 @ 20:52 and filed in Deployment

When running behind a reverse proxy, not only is the public URL different, but often you want the application to appear below some path other than /. Sometimes you even use https from the outside, in which case you likely don't use SSL between the proxy server and your Flask app.

In such cases, if you can control the headers in the proxy server (easy with Nginx and many others), this middleware lets you transparently change where the application appears. This works dynamically for each request, so you can simultaneously access from the local machine using http://localhost:port without using the full URL.

class ReverseProxied(object):
    '''Wrap the application in this middleware and configure the 
    front-end server to add these headers, to let you quietly bind 
    this to a URL other than / and to an HTTP scheme that is 
    different than what is used locally.

    In nginx:
    location /myprefix {
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header X-Script-Name /myprefix;

    :param app: the WSGI application
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
        if script_name:
            environ['SCRIPT_NAME'] = script_name
            path_info = environ['PATH_INFO']
            if path_info.startswith(script_name):
                environ['PATH_INFO'] = path_info[len(script_name):]

        scheme = environ.get('HTTP_X_SCHEME', '')
        if scheme:
            environ['wsgi.url_scheme'] = scheme
        return self.app(environ, start_response)

Install in app using:

    app = Flask(__name__)
    app.wsgi_app = ReverseProxied(app.wsgi_app)

That's it! Now your page accessible locally at will also be accessible externally at https://example.com/myprefix/myapp.

Don't forget to /etc/init.d/nginx reload or the equivalent after changing your server configuration.

This snippet by Peter Hansen can be used freely for anything you like. Consider it public domain.