HttpPlatformHandler をインストールする

Master Mole
質問: サービス化はイヤ
IISサーバーでPythonのアプリケーションを配置することになったのですが、Pythonのアプリケーションをサービス化して、IISでリダイレクトする配置手順を 案内されました。さらにSSL対応も別途必要とのことで、作業コストが大きすぎると文句を言ったところ、 HttpPlatformHandler を利用して、IISから透過的にPythonアプリケーションを実行できる手順を案内されました。
HttpPlatformHandler とは何なのでしょうか?また、HttpPlatformHandlerのインストールが必要とのことです。インストール手順を教えてください。

HttpPlatformHandler とは

Microsoft 製の IIS モジュールで、IIS の背後で、IIS 以外のプロセスを起動・管理し、リクエストを受け渡しするモジュールです。 IIS は本来 ASP.NET / .NET を動かすためのものですが、Python・Java・Node.js など IIS が直接実行できない言語のアプリを IIS 配下で動かすために、このモジュールが用意されています。

リクエストが来ると、HttpPlatformHandler は web.config に書かれた processPathargumentsを使って子プロセスを自分で起動します。 そして IIS が割り当てた内部ポート(%HTTPPLATFORM_PORT%)番号を環境変数でアプリに渡し、すべてのリクエストをそのポートへ転送します。

HttpPlatformHandler をインストールする:画像1

このモジュールが面倒を見てくれること
役割内容
プロセスの起動 初回アクセス時(または AlwaysRunning 設定時はサイト起動時)に python.exe を自動起動します。
プロセスの監視・再起動 アプリがクラッシュしたら自動で起動し直します。
ライフサイクル連動 IIS のアプリプール停止・リサイクルに合わせてプロセスも停止します。
ポート管理 空きポートを動的に割り当て、アプリに通知(ポート衝突を自分で気にしなくてよい)
環境変数・ログ web.config で環境変数を渡し、標準出力をファイルに記録します。

HttpPlatformHandler のインストール

HttpPlatformHandler のページ (https://www.iis.net/downloads/microsoft/httpplatformhandler) にアクセスします。
ページ内の[x64 installer]のリンクをクリックします。
HttpPlatformHandler をインストールする:画像2

リンクをクリックするとインストーラーがダウンロードできます。
HttpPlatformHandler をインストールする:画像3

インストーラーを実行します。下図のダイアログが表示されます。
HttpPlatformHandler をインストールする:画像4

[I accept the terms in the license agreement]のチェックボックスをクリックします。チェック 後、[Install]ボタンをクリックします。
HttpPlatformHandler をインストールする:画像5

インストールが始まります。
HttpPlatformHandler をインストールする:画像6

インストールが完了すると、下図の画面が表示されます。[Finish] ボタンをクリックしてインストーラーを終了します。
HttpPlatformHandler をインストールする:画像7

web.configの書式

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が子プロセスとして起動するコマンドを定義しています。

  • processPath: venv内のpython.exeを直接指定。これによりvenvにインストールされたパッケージがそのまま使えます(venvのpython.exeを叩けばactivate不要)。
  • arguments: 起動スクリプトの.pyファイル。相対パスなので、作業ディレクトリ(既定でWeb.configのあるフォルダ)基準で解決されます。
  • startupTimeLimit="120": プロセス起動からポートが応答可能になるまでの猶予が120秒。既定値(10秒程度)では、WD-Taggerのようにモデルロードに時間がかかるアプリは起動失敗(502)になるため延長されています。
  • stdoutLogEnabled / stdoutLogFile: 子プロセスの標準出力・標準エラーを (ログ保存先)\stdout_<タイムスタンプ>_<PID>.log のような名前で書き出します。フォルダの事前作成とIIS_IUSRSへの書き込み権限付与が前提です。
<httpPlatform processPath="(python.exe または venv環境のpython.exe のフルパス)"
              arguments="(アプリ名).py"
              startupTimeLimit="120"
              stdoutLogEnabled="true"
              stdoutLogFile="(ログファイル保存先ディレクトリ)">

環境変数によるポート受け渡し

HttpPlatformHandlerは子プロセス起動時に空きポートをひとつ選び、%HTTPPLATFORM_PORT% というプレースホルダーとして提供します。 アプリ側はそのポートでlistenし、IISはそこへリバースプロキシします。

  • UVICORN_PORT: 通常は arguments に --port %HTTPPLATFORM_PORT% と書く方法が紹介されますが、このテンプレートではarguments内の置換が効かない環境を避けるため、環境変数として渡しています。uvicornは UVICORN_PORT 環境変数を自前で読むので、コード側で明示的にポートを渡さなくても正しいポートでlistenします。<environmentVariable> のvalue内の置換はarguments内より確実に動作する、という経験則に基づく設計です。
  • PYTHONPATH: アプリのルートをモジュール検索パスに追加。作業ディレクトリ問題でimportが失敗するのを防ぐ保険です。
  • ROOT_PATH: これはHttpPlatformHandlerの機能ではなくアプリ側の約束事で、(アプリケーション配置相対URL) というサブパス配下に配置されていることをFastAPI/uvicornに伝えるためのものです(uvicornの --root-path 相当)。IISはサブアプリケーション宛のパスをそのまま子プロセスに転送するため、アプリ側がプレフィックスを知らないとリダイレクトやOpenAPIドキュメントのURLが壊れます。
  • PYTHONUNBUFFERED=1: Pythonの出力バッファリングを無効化。これがないとstdoutログがプロセス異常終了時に欠落したり、リアルタイムに書き出されなかったりします。stdoutLogEnabledとセットで実質必須です。
<environmentVariables>
  <environmentVariable name="UVICORN_PORT" value="%HTTPPLATFORM_PORT%" />
  <environmentVariable name="PYTHONPATH" value="(実行するアプリケーションの絶対パス)" />
  <environmentVariable name="ROOT_PATH" value="(実行するアプリケーションの相対URL)" />
  <environmentVariable name="PYTHONUNBUFFERED" value="1" />
</environmentVariables>

補足:uvicorn

Master Mole
質問: uvicorn?
uvicorn って何ですか?
プロテ
uvicornとは
uvicornは、PythonのASGI(Asynchronous Server Gateway Interface)対応の高速なWebサーバーです。 FastAPIやStarletteといった非同期Webフレームワークで書かれたアプリを、実際にHTTPリクエストを受け付ける形で動かすためのものです。
WSGIに対するgunicornやmod_wsgiのASGI版、という理解が一番近いです。Webフレームワーク(FastAPIなど)は「リクエストが来たらこう処理する」というロジックを書く場所で、それ自体はソケットを開いてHTTPを喋る機能を持ちません。 その間を埋めて、実際にポートでlistenしてHTTPを解釈し、ASGIの規約に従ってアプリ関数を呼び出すのがuvicornの役割です。


Master Mole
うーん
良くわっかんねーけど、インストールして配置した動いたんで、まいっか~
プロテ
Mole君へ。
「動いたからまいっか~」は、エンジニアリングの世界では正式な技術判断のひとつです。ISO規格にはありませんが、全世界のサーバーの約半分がこの判断基準で今日も稼働しています。 ただし覚えておいてください。uvicornは今この瞬間も、あなたが理解していないことを理解した上で、黙ってポートをlistenし続けています。IISが払い出したポート番号を環境変数越しに受け取り、文句ひとつ言わずに。彼らは知っているのです。「良くわっかんねーけど動いた」の裏側で、startupTimeLimitの120秒間、誰にも見られずモデルをロードしていた孤独を。 いつかWeb.configを開いて「これ全部消したらどうなるんだろう」と思う日が来るでしょう。その好奇心が芽生えた日が、まいっか~卒業式です。それまでは、logsフォルダの書き込み権限と共にあらんことを。 ——なお「動いてるものは触るな」も同じく国際的に承認された技術判断なので、卒業はいつでも延期できます。


AuthorPortraitAlt
著者
iPentecのプログラマー、最近はAIの積極的な活用にも取り組み中。
とっても恥ずかしがり。
作成日: 2026-06-10