Running Flask Web Apps on IIS with HttpPlatformHandler

July 10, 2022

HttpPlatformHandler can help IIS host Java/Python/Node.js/Go applications, so in this post we wil see how to configure a Python/Flask web app on IIS and troubleshoot the common issue.

It becomes very important for Python developers to learn HttpPlatformHandler, because Microsoft no longer recommends FastCGI,

“We recommend using HttpPlatform to configure your apps, as the WFastCGI project is no longer maintained.”

Basic Flask Setup

No doubt we will start from a sample application as below,

from flask import Flask

def create_app():
    app = Flask(__name__)

    @app.route("/")
    def hello_world():
        return "<p>Hello, World!</p>"

    return app

If we save it as C:\flask-test\app.py, then on a Windows machine with Python and Flask installed, a simple command flask run in the directory of C:\flask-test\ can launch the application at port 5000,

PS C:\flask-test> ~\AppData\Local\Programs\Python\Python310\python.exe -m flask run
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)

If Python and Flask are not yet installed, you can search for guides.

HttpPlatformHandler Setup

Now let’s download and install HttpPlatformHandler on IIS, and add a web.config in C:\flask-test,

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" requireAccess="Script" />
        </handlers>
        <httpPlatform stdoutLogEnabled="true" stdoutLogFile=".\python.log" startupTimeLimit="20" processPath="C:\Users\<user name>\AppData\Local\Programs\Python\Python310\python.exe" arguments="-m flask run --port %HTTP_PLATFORM_PORT%">
        </httpPlatform>
    </system.webServer>
</configuration>

With all settings in place, I can go back to IIS Manager and create a site (I chose *:8086 as site binding) to point to C:\flask-test. By opening a web browser and navigate to http://localhost:8086/, I should now see “Hello, World!”. Ah, what happened?

Troubleshooting

0x8007005

Yeah I am not able to see “Hello, World!” but a Bad Gateway error page with the Error Code of 0x80070005,

Figure 1: Bad Gateway error page of 0x80070005
> .\Err.exe 80070005
# No results found for hex 0x4c5c575 / decimal 80070005
# for hex 0x80070005 / decimal -2147024891
  COR_E_UNAUTHORIZEDACCESS                                       corerror.h
# Access is denied.
  DIERR_OTHERAPPHASPRIO                                          dinput.h
  DIERR_READONLY                                                 dinput.h
  DIERR_HANDLEEXISTS                                             dinput.h
  DSERR_ACCESSDENIED                                             dsound.h
  STIERR_READONLY                                                stierr.h
  STIERR_NOTINITIALIZED                                          stierr.h
  E_ACCESSDENIED                                                 winerror.h
# General access denied error
# as an HRESULT: Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x5
# for hex 0x5 / decimal 5
  ERROR_ACCESS_DENIED                                            winerror.h
# Access is denied.
# 9 matches found for "80070005"

This isn’t hard to understand, because anything under C:\Users\<user name>\ is protected and accessible only by that user account by default, not IIS_IUSRS.

The Infinite Loading

Once I grant IIS_IUSRS read access to C:\Users\<user name>\AppData\Local\Programs\Python\Python310\python.exe, the browser seems to work as it is trying to load the web page. However, I notice that now this page takes for ever to load and the python.exe process keeps crashing.

No doubt Process Monitor is the best tool to use right now and by using a filter of process name python.exe I can see lots of access denied errors on different files in C:\Users\<user name>\AppData\Local\Programs\Python\Python310\.

So I go back and grant IIS_IUSRS read access on the whole directory, not just python.exe.

Switch to Production Application Server

At this moment, a refresh in the web browser leads me to the expected “Hello, World!” message. Now I know that Python/Flask is working.

To move further, I might want to remove the warning of “This is a development server. Do not use it in a production deployment”. For that I have to switch to another Python application server, such as waitress.

Use pip install waitress to install it.

To allow waitress to identify the web app entry, add a file called wsgi.py in the directory,

from app import create_app

application = create_app()

and then the command line waitress-serve can be used to launch the server,

PS C:\flask-test> ~\AppData\Local\Programs\Python\Python310\python.exe -m waitress --port 9000 wsgi:application
INFO:waitress:Serving on http://0.0.0.0:9000

With all the help from waitress, I can modify web.config as below as final version,

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" requireAccess="Script" />
        </handlers>
        <httpPlatform stdoutLogEnabled="true" stdoutLogFile=".\python.log" startupTimeLimit="20" processPath="C:\Users\lextudio\AppData\Local\Programs\Python\Python310\python.exe" arguments="-m waitress --port %HTTP_PLATFORM_PORT% wsgi:application">
        </httpPlatform>
    </system.webServer>
</configuration>

All rights reserved. © Lex Li, 2005-2022

Advertisement