IIS as a reverse proxy for python flask application

flask_iis

Skill - IIS as a reverse proxy for python flask application

Table of Contents

Skills Required

Please make sure to have all the skills mentioned above to understand and execute the code mentioned below. Go through the above skills if necessary for reference or revision


  • In this post we will learn how to run a flask server behind IIS acting as a reverse proxy for the flask application

What is IIS

  • Internet Information Services (IIS) is a general purpose web server in windows for hosting web applications
  • It is a production ready web server with good security, stability and many configuration options

Why use IIS as reverse proxy

  • Hosting a python flask server directly to the clients / internet is not generally practiced
  • Flask server should be generally hosted behind a robust reverse proxy server like Nginx or IIS (Internet Information Services)
  • SSL certificate management will be very easy with IIS and need not be handled in the flask application
  • Since IIS is the go-to hosting solution for windows server, this approach is a more useful and a practical implementation of flask server hosting in windows
  • Moreover IIS has a very handy and powerful user interface to control the hosting of web applications

Enabling IIS in windows

  • In windows search for “Turn Windows features On or Off”
  • Under the “Internet Information Services” section, make sure that “IIS Management Console” and default options under “World Wide Web Services” are enabled

Architecture

  • The data flow to the flask application can be as shown below
  • The flask application can be a windows background service or a normal process running in command prompt.
    flask_IIS_reverse_proxy_arch.png

Example Flask server

  • Let us create a simple flask server for this example
  • Create a server.py file that acts as a flask server
# server.py  
from flask import Flask
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from werkzeug.exceptions import NotFound

# create a server instance
app = Flask(__name__)

@app.route('/')
def index():
    return "Hello World!!!"

@app.route('/help')
def helpPage():
    return "This is the Help Page"

hostedApp = Flask(__name__)
hostedApp.wsgi_app = DispatcherMiddleware(NotFound(), {
    "/myApp": app
})

# run the server
hostedApp.run(host="0.0.0.0", port=50100, debug=True)
  • Notice that the flask application is sub-mounted under the URL prefix ‘/myapp’ . Visit this blog post to understand more on how to sub-mount a flask application under a URL-prefix
  • Also consider using waitress for running the application in production. Visit this blog post to understand how to use waitress as WSGI for a flask application

Running the flask server

  • You can run the flask server in command line using the command python server.py
  • You can also use nssm to run the flask server as a windows background service. Read this blog post for more information on this

Setting up IIS as reverse proxy

Step 1 - Installing the url-rewrite and ARR modules in IIS

Step 2 - Enable Proxy in ARR module

  • Open IIS Manager and click on the server
  • In the admin console for the server, double click on the Application Request Routing option:
  • Click the Server Proxy Settings action on the right-hand pane
  • Select the Enable proxy checkbox so that it is enabled
  • Click Apply and proceed with the URL Rewriting configuration

Step 3 - URL rewriting

This url-rewrite rule forwards the request from IIS to the flask application hosted at localhost:50100 if the request URL starts with ‘/myapp’

  • Double click URL rewrite icon in Default Website
  • Click Add Rule(s) link in the right pane
  • Select Blank rule under Inbound rules
  • Create a rule as shown in the image below

flask_iis_url_rewrite.png

  • Server variables section in the above settings should not be set if Step 4 is not done

Step 4 (Optional) - Add HTTP_X_ORIGINAL_HOST server variable

Using a reverse proxy will modify the request headers originating from the end-user’s browser. Hence the HTTP header host will not be known to the flask application. So using the below steps we can send a new HTTP header named HTTP_X_ORIGINAL_HOST to send original host header to flask application from the end user

  • Double click URL rewrite icon in Default Website
  • Click on View Server Variables in the right-hand pane
  • Add HTTP_X_ORIGINAL_HOST to the allowed server variables

Conclusion

  • By following the above steps, IIS can be used as a reverse proxy for the flask application

Video

The video for this post can be seen here

References

Comments