B.Mr.W.
B.Mr.W.

Reputation: 19618

Create Proxy for Python Flask Application

we have an internal application, the backend was written in Java and the front end was written in HTML, Javascript..etc. The app was hosted using nginx server. However, I have another web application was written in Python flask where the boss want to integrate those two tools together.

say for example, the initial project(Java solution) has the domain

inv.datafireball.com 

And the admin showed me that he can change the configuration file of nginx in that way, a route can be mapped/proxy to the second app running on a different server

inv.datafireball.com/competitor -> datafireball.com:5000

However, based on my research, all the paths in the Python application need to be re-coded in a way: /static/js/d3.js need to be changed to /competitor/static/js/d3.js...

We harded coded a few paths it looked very promising, however, our Python application is pretty big and it is really a big mass after to manually change all the path.

Can anyone give me a guidance if there is an easy way to map/proxy a Python flask application to an existing application written in Java with changing the existing Python code?

Upvotes: 2

Views: 2434

Answers (1)

junnytony
junnytony

Reputation: 3515

Here's a solution that requires miminal change to the Flask application and works pretty well:

Here's what it does essentially: We tell Nginx to pass some special headers to our proxy flask application and then we create a wrapper (ReverseProxied) that intercepts each request, extracts the headers set by Nginx and modifies the request processing environment so that it matches the urls we want.

In Nginx, add the following inside the server directive:

location /competitor {
    proxy_pass http://127.0.0.1:5001;
    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 /competitor;
}

In Flask, add the class below to your main application file (wherever you create the main Flask app object)

class ReverseProxied(object):
    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)

Finally, force your app to use the new ReverseProxied middleware

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

You can find the original solution and code snippets here http://flask.pocoo.org/snippets/35/

Upvotes: 2

Related Questions