Running Python Flask on a local IIS (not Azure!) with wfastcgi.py

There are already a lot of resources dealing with how to setup Django with IIS, or configure IIS to support WSGI with various tools such as Helicon Zoo, isapi-wsgi, and FastCGI.

FastCGI looked good among others because I wanted to go with least 3rd party stack and the Microsoft distribute the wfastcgi.py through PTVS. However, there’s a still one problem. I couldn’t find the document explains how to set up a local IIS to work with FastCGI and Flask.

Thanks to PTVS, it’s already well implemented and provided. The PTVS contains the wfastcgi.py, and web.config which set required environments to run. Here’s more detailed step:

1. Install wfastcgi.py. The PTVS official homepage has the link to download wfastcgi.py MSI installer.

http://pytools.codeplex.com/downloads/get/920481

wfastcgi

The wfastcgi MSI installer creates local copies of wfastcgi.py to python installed directory as below:

wfastcgi-installed

2. Install FastCGI to IIS and add wfastcgi.py handler to it. The official PTVS page has the required command to ease the steps here:

http://pytools.codeplex.com/wikipage?title=wfastcgi

start /wait %windir%\System32\\PkgMgr.exe /iu:IIS-CGI

%windir%\system32\inetsrv\appcmd set config /section:system.webServer/fastCGI “/+[fullPath=’c:\Python27\python.exe’, arguments=’C:\Python27\Scripts\wfastcgi.py’]”

The wfastcgi.py MSI installer also seems to add the handlers above automatically if FastCGI is already configured, but it’s not sure. You can now see the FastCGI listed installed Python paths.

fastcgi

3. Now it’s time to edit the web.config for Flask/IIS. If you created the Flask project with PTVS addon, it already contains the required web.config to support deploy to Azure. However, in order to run it on local IIS, it needs a little modification. Let’s see the original web.config first PTVS generated.

<?xml version=”1.0″?>
<!– Generated web.config for Microsoft Azure. Remove this comment to prevent
modifications being overwritten when publishing the project.
–>
<configuration>
<system.diagnostics>
<trace>
<listeners>
<add type=”Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ name=”AzureDiagnostics”>
<filter type=”” />
</add>
</listeners>
</trace>
</system.diagnostics>
<appSettings>
<add key=”WSGI_ALT_VIRTUALENV_HANDLER” value=”FlaskWebProject1.app” />
<add key=”WSGI_ALT_VIRTUALENV_ACTIVATE_THIS” value=”%ROOTDIR%\env\Scripts\activate_this.py” />
<add key=”WSGI_HANDLER” value=”ptvs_virtualenv_proxy.get_virtualenv_handler()” />
<add key=”PYTHONPATH” value=”%ROOTDIR%” />
</appSettings>
<system.web>
<compilation debug=”true” targetFramework=”4.0″ />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests=”true” />
<handlers>
<add name=”Python FastCGI” path=”handler.fcgi” verb=”*” modules=”FastCgiModule” scriptProcessor=”%INTERPRETERPATH%|%WFASTCGIPATH%” resourceType=”Unspecified” requireAccess=”Script” />
</handlers>
<rewrite>
<rules>
<rule name=”Static Files” stopProcessing=”true”>
<match url=”^/static/.*” ignoreCase=”true” />
<action type=”Rewrite” url=”^/FlaskWebProject1/static/.*” appendQueryString=”true” />
</rule>
<rule name=”Configure Python” stopProcessing=”true”>
<match url=”(.*)” ignoreCase=”false” />
<conditions>
</conditions>
<action type=”Rewrite” url=”handler.fcgi/{R:1}” appendQueryString=”true” />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

Few things. First, I removed the <system.diagnostics> section which installs Azure diags listener. Second, the IIS cannot understand the %ROOTDIR% variable so you should convert it all absolute path for that server you about to run.

So it’ll look like this:

<appSettings>
<add key=”WSGI_ALT_VIRTUALENV_HANDLER” value=”FlaskWebProject1.app” />
<add key=”WSGI_ALT_VIRTUALENV_ACTIVATE_THIS” value=”D:\repo\web\FlaskWebProject1\FlaskWebProject1\env\Scripts\activate_this.py” />
<add key=”WSGI_HANDLER” value=”ptvs_virtualenv_proxy.get_virtualenv_handler()” />
<add key=”PYTHONPATH” value=”D:\repo\web\FlaskWebProject1\FlaskWebProject1” />
</appSettings>

The generated web.config has a python handler mapped, but the path also needs to be updated to point the direct wfastcgi.py path as follows:

<handlers>
<add name=”Python FastCGI” path=”handler.fcgi” verb=”*” modules=”FastCgiModule” scriptProcessor=”C:\Python34\python.exe|C:\Python34\Scripts\wfastcgi.py” resourceType=”Unspecified” requireAccess=”Script” />
</handlers>

It’s enough to edit a web.config. However, if you still encounter a strange 500 internal error, please make sure the local IIS has the URL Rewrite 2.0 module installed. In my case, whenever I tried to open the edited web.config from IIS manager, it gives me that “There was an error while performing this operation. … web.config” error so that I couldn’t open a web.config nor edit mapping handlers. Fortunately, I found those answers from SO and solved it by installing URL Rewrite 2.0 through the ‘Web Platform Installer’. Microsoft Download site also provides a standalone exe.

urlrewrite2

http://stackoverflow.com/questions/3701562/iis-7-5-cant-open-handler-mappings

http://stackoverflow.com/questions/22199424/asp-net-iis-web-config-there-was-an-error-while-performing-this-operation

Done. If the IIS successfully loaded web.config, then it’ll show the correctly mapped Python wfastcgi handler at ‘Handler Mappings’ as follows:

handler1 handler2

If you have any questions, please leave a comment. Thanks for reading.