hckr.fyi // thoughts

Environment Variables and Web.Config Settings for Python and Flask IIS

by Michael Szul on

Traditionally, deploying non-Microsoft languages and frameworks to Windows and IIS can be troublesome to say the least. Most of the time, it's extremely frustrating. Although Microsoft has continued to embrace the open source community, much of their work has focused on cross-platform deployments, which means that for C# and ASP.NET, focusing on Core. Core can be deployed anywhere through the Kestrel server, but the focus, again, is on cross-platform. ASP.NET Core ships with a bridge from Kestrel to IIS to ease the transition burden, but it often feels like IIS has been left in the dust when it comes to compatibility.

This is readily apparent with popular platforms like Node.JS, or frameworks like Python's Flask. You can deploy these to Windows servers, and serve them under IIS, but you're going to be hunting down documentation.

I plan on covering the steps needed to deploy Flask to IIS in a future post, but for this post, I wanted to focus on obtaining environment variables. This is not necessarily environment/OS-specific, but the setup that I was experimenting with was Windows and IIS.

For standard environment variables, you can access these through the os module:

import os
    
    env_vars = os.environ
    

You can also get these items individually:

import os
    
    vdir = os.getenv('BASE_FOLDER', default='/analytics')
    

In the above code, we're using getenv() to get the BASE_FOLDER environment variable, and if it doesn't exist, we're setting it to the default of /analytics.

Now, this is for environment variables, which is different than what would normally be considered server variables in ASP.NET on Windows. To get to those, you would want to use Flask's built-in request object:

s_vars = request.environ
    

You can get individual variables with something like:

if request.environ['HTTP_ORIGIN'] is not None:
        print request.environ['HTTP_ORIGIN']
    

Finally, since we're talking about deploying Python and Flask on Windows under IIS, what about web.config application settings? We actually already showed you this above with:

vdir = os.getenv('BASE_FOLDER', default='/analytics')
    

The BASE_FOLDER string is actually an application key in the web.config:

<configuration>
      <system.webServer>
        <handlers>
            <remove name="Python27_via_FastCGI" />
            <remove name="Python34_via_FastCGI" />
            <add name="Python FastCGI"
                path="*"
                verb="*"
                modules="FastCgiModule"
                scriptProcessor="C:\python37\python.exe|C:\python37\lib\site-packages\wfastcgi.py"
                resourceType="Unspecified"
                requireAccess="Script" />
        </handlers>
      </system.webServer>
      <appSettings>
        <add key="WSGI_HANDLER" value="analytics.app" />
        <add key="PYTHONPATH" value="D:\WebDev\Analytics" />
        <add key="WSGI_RESTART_FILE_REGEX" value=".*((\.py)|(\.config))$" />
        <add key="SCRIPT_NAME" value="/analytics" />
        <add key="BASE_FOLDER" value="" />
      </appSettings>
    </configuration>
    

What this tells us is that wfastcgi--the utility for running Fast CGI applications for Python under IIS--is injecting the application settings into the environment variables for the OS.

Don't worry too much about the rest of the web.config. We'll cover that when we write the aforementioned deployment post.