Microsoft 製の IIS モジュールで、IIS の背後で、IIS 以外のプロセスを起動・管理し、リクエストを受け渡しするモジュールです。
IIS は本来 ASP.NET / .NET を動かすためのものですが、Python・Java・Node.js など IIS が直接実行できない言語のアプリを IIS 配下で動かすために、このモジュールが用意されています。
リクエストが来ると、HttpPlatformHandler は web.config に書かれた processPath と argumentsを使って子プロセスを自分で起動します。
そして IIS が割り当てた内部ポート(%HTTPPLATFORM_PORT%)番号を環境変数でアプリに渡し、すべてのリクエストをそのポートへ転送します。
| 役割 | 内容 |
|---|---|
| プロセスの起動 | 初回アクセス時(または AlwaysRunning 設定時はサイト起動時)に python.exe を自動起動します。 |
| プロセスの監視・再起動 | アプリがクラッシュしたら自動で起動し直します。 |
| ライフサイクル連動 | IIS のアプリプール停止・リサイクルに合わせてプロセスも停止します。 |
| ポート管理 | 空きポートを動的に割り当て、アプリに通知(ポート衝突を自分で気にしなくてよい) |
| 環境変数・ログ | web.config で環境変数を渡し、標準出力をファイルに記録します。 |
HttpPlatformHandler のページ (https://www.iis.net/downloads/microsoft/httpplatformhandler) にアクセスします。
ページ内の[x64 installer]のリンクをクリックします。
リンクをクリックするとインストーラーがダウンロードできます。
インストーラーを実行します。下図のダイアログが表示されます。
[I accept the terms in the license agreement]のチェックボックスをクリックします。チェック 後、[Install]ボタンをクリックします。
インストールが始まります。
インストールが完了すると、下図の画面が表示されます。[Finish] ボタンをクリックしてインストーラーを終了します。
HttpPlatformHandler を利用した。web.configの書式は次のようになります。以下はPythonの例です。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
</handlers>
<httpPlatform processPath="(python.exe または venv環境のpython.exeの実行パス)"
arguments="(実行するスクリプトファイル名)"
startupTimeLimit="120"
stdoutLogEnabled="true"
stdoutLogFile="(ログファイルの保存パス)">
<environmentVariables>
<environmentVariable name="UVICORN_PORT" value="%HTTPPLATFORM_PORT%" />
<environmentVariable name="PYTHONPATH" value="(実行するアプリケーションの絶対パス)" />
<environmentVariable name="ROOT_PATH" value="(実行するアプリケーションの相対URL)" />
<environmentVariable name="PYTHONUNBUFFERED" value="1" />
</environmentVariables>
</httpPlatform>
</system.webServer>
</configuration>
このアプリケーションに来る全リクエスト(path="*"、全HTTPメソッド verb="*")を、httpPlatformHandlerモジュールに渡すという宣言です。
resourceType="Unspecified" は、物理ファイルやディレクトリの存在チェックをせず、URLが何であってもハンドラーに回すという意味で、
リバースプロキシ用途では必須の指定です。これがないと静的ファイル風のURLがIISの静的ファイルハンドラーに取られてしまいます。
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
</handlers>
HttpPlatformHandlerの本体設定で、IISが子プロセスとして起動するコマンドを定義しています。
<httpPlatform processPath="(python.exe または venv環境のpython.exe のフルパス)"
arguments="(アプリ名).py"
startupTimeLimit="120"
stdoutLogEnabled="true"
stdoutLogFile="(ログファイル保存先ディレクトリ)">
HttpPlatformHandlerは子プロセス起動時に空きポートをひとつ選び、%HTTPPLATFORM_PORT% というプレースホルダーとして提供します。
アプリ側はそのポートでlistenし、IISはそこへリバースプロキシします。
--port %HTTPPLATFORM_PORT% と書く方法が紹介されますが、このテンプレートではarguments内の置換が効かない環境を避けるため、環境変数として渡しています。uvicornは UVICORN_PORT 環境変数を自前で読むので、コード側で明示的にポートを渡さなくても正しいポートでlistenします。<environmentVariable> のvalue内の置換はarguments内より確実に動作する、という経験則に基づく設計です。
(アプリケーション配置相対URL) というサブパス配下に配置されていることをFastAPI/uvicornに伝えるためのものです(uvicornの --root-path 相当)。IISはサブアプリケーション宛のパスをそのまま子プロセスに転送するため、アプリ側がプレフィックスを知らないとリダイレクトやOpenAPIドキュメントのURLが壊れます。
<environmentVariables>
<environmentVariable name="UVICORN_PORT" value="%HTTPPLATFORM_PORT%" />
<environmentVariable name="PYTHONPATH" value="(実行するアプリケーションの絶対パス)" />
<environmentVariable name="ROOT_PATH" value="(実行するアプリケーションの相対URL)" />
<environmentVariable name="PYTHONUNBUFFERED" value="1" />
</environmentVariables>