Skip to content

MS_ISAPIandHttpPlatformHandler

nishi_74322014 edited this page Aug 21, 2026 · 2 revisions

ISAPI、HttpPlatformHandler

概要

ISAPIと、HttpPlatformHandlerについて。

補足(この 2 つを並べる意味): 一見無関係に見えるが、
**どちらも「IIS に別の処理系を載せる仕組み」**であり、
世代が違うという関係にある。

【第1世代】ISAPI(1996〜)           … C/C++ の DLL を IIS に直接ロード
             ↓ 危険(プロセス内で動く)・作るのが大変
【第2世代】CGI / FastCGI            … 別プロセス。パイプで通信
             ↓ 遅い / Windows と相性が悪い
【第3世代】HttpPlatformHandler(2015) … 別プロセス。HTTP で通信
             ↓
【現在】  ASP.NET Core モジュール(ANCM) … 上記の後継。Kestrel を起動

つまり、**「IIS 以外のもの(PHP、Node.js、Java、
ASP.NET Core)をどうやって IIS の下でホストするか」**という
一貫した課題への、時代ごとの回答が並んでいる。

ISAPI 側は過去の遺産の理解として、
HttpPlatformHandler 側は現在の ANCM の前身として読むとよい
IISの動作モデル)。

ISAPI

ISAPIエクステンション

概要

  • DLL として IIS に直接ロードされるため、オーバーヘッドが少なく高性能・高機能
  • 直接呼び出すこともスクリプトマッピングすることも可能。

開発

以下のインターフェイスを実装(DLL なので以下の関数をエクスポート)

  • GetExtensionVersion
    DLL の読み込み時に呼び出される。
  • HttpExtensionProc
    HTTP リクエストを処理する。
  • TerminateExtension
    DLL のアンロード時に呼び出される。

実行

  • (まだロードされていない場合)DLL をロード。
  • ロード後、IIS は、
    • DLL の GetExtensionVersion メソッドを呼び出す。
    • EXTENSION_CONTROL_BLOCK を作成する。
    • HttpExtensionProc メソッドの引数に ECB のポインタを指定し呼び出す。
  • ISAPI Extension DLL は、ECB を使用して処理を行う。

ECB

  • ECB : Extension Control Block
  • ECB には、以下が含まれる。
    • 基本的なデータブロック
      • QueryString, Method…
      • データバッファとデータ長等
    • 関数ポインタ
      • GetServerVariable
      • WriteClient
      • ReadClient
      • ServerSupportFunction

移行メモ(体裁): 原典の「ECB には、如何含まれる含まれる。」は
以下が含まれる。」の誤変換+重複であるため修正した。

補足(ISAPI が廃れた理由): 「オーバーヘッドが少なく高性能」という
利点は事実だが、それはIIS のプロセス内で直接動くことの裏返しでもある。

問題 内容
クラッシュが IIS を巻き込む ネイティブ コードのバグでワーカー プロセスごと落ちる
メモリ リークが蓄積する プロセスが長時間動くため
マルチスレッド前提 スレッド セーフに書く必要があり、難易度が高い
移植性が無い Windows / IIS 専用
開発コスト C/C++ で低レベルな API を扱う

このため、

  • 安全性を取るなら別プロセス(CGI / FastCGI / HttpPlatformHandler)、
  • 生産性を取るならマネージド コード(ASP.NET の HttpHandler / HttpModule)

という方向に置き換わっていった。

現在 ISAPI の知識が必要になるのは、

  • クラシック モードで動く古い ISAPI 拡張の保守
  • aspnet_isapi.dll の挙動の理解
    (クラシック モードでは ASP.NET 自体が ISAPI 拡張として動く)

といった場面に限られる。

ISAPIフィルタ

概要

  • ISAPI エクステンションと並び、
    IIS の早期のバージョンから実装されている API。
  • 主に、HTTP のフィルタ、書き換え、HTTP 圧縮などを目的とした API。

開発

  • 以下のインターフェイスを実装(DLL なので以下の関数をエクスポート)
    • GetFilterVersion
      DLL の読み込み時に呼び出される。
    • HttpFilterProc
      通知ごとにそれぞれ特有のデータを受け取る。
      戻り値でフィルターの動作を細かく制御できる。
    • TerminateFilter
      DLL のアンロード時に呼び出される。
  • ポイント
    • AllocMem
      • フィルタ内でメモリを割り当てるときは AllocMem を使う
      • AllocMem で割り当てたメモリは自動的に解放される
    • pFilterContext
      • 初期値は NULL
      • ユーザーデータの格納場所
    • SF_STATUS_REQ_READ_NEXT

実行

(記載なし)

通知 / 戻り値

# 通知 説明
1 SF_NOTIFY_READ_RAW_DATA クライアントが要求を送信した際。
2 SF_NOTIFY_PREPROC_HEADERS 各要求に対して発生。ヘッダーの前処理を完了後に発生。
3 SF_NOTIFY_URL_MAP 物理パスに変換しているときに発生。ヘッダーの前処理を完了後、1 回以上発生。
4 SF_NOTIFY_AUTHENTICATION 匿名リクエスト、authorization header を含むリクエストの度に発生。直後、IIS はクライアントの認証を試みる。
5 SF_NOTIFY_AUTH_COMPLETE 認証完了後に発生。HTTP メソッド、URL、バージョン、ヘッダの表示と変更が可能。
6 SF_NOTIFY_READ_RAW_DATA ※ チャンクなどで以降のクライアント・データを受信した際。
7 SF_NOTIFY_SEND_RESPONSE 要求が処理され、ヘッダがクライアントに返送される前に発生。
8 SF_NOTIFY_SEND_RAW_DATA クライアントにデータを返信した際。
9 SF_NOTIFY_END_OF_REQUEST 各要求の終わりに発生。HTTP 要求が完了した際。
10 SF_NOTIFY_LOG IIS がログに要求を書き込む直前に発生。
11 SF_NOTIFY_END_OF_NET_SESSION TCP/IP 接続が閉じられると発生

移行メモ(正誤): 原典の項番 4 の「リクエストのに発生」は
「リクエストのに発生」の誤変換であるため修正した。
また、表の直後に「126/5000」「HTTP要求が完了し、」という
翻訳ツールの出力が混入したと思われる断片が残っていたため、
文意から項番 9 の説明に統合した。

  • 戻り値
# 戻り値 説明
1 SF_STATUS_REQ_FINISHED フィルタが HTTP 要求を処理しました。サーバーはセッションを切断する必要があります。
2 SF_STATUS_REQ_FINISHED_KEEP_CONN #1 と同じだが、キープアライブの際は切断しない。
3 SF_STATUS_REQ_NEXT_NOTIFICATION 通知チェーンの次のフィルタを呼び出す。
4 SF_STATUS_REQ_HANDLED_NOTIFICATION このフィルタは通知の処理を完了(次のフィルタを呼び出さない)
5 SF_STATUS_REQ_ERROR エラー発生。GetLastError でエラーをクライアントに通知。
6 SF_STATUS_REQ_READ_NEXT Raw 読み取り通知の場合にのみ有効。

補足(この通知一覧は「パイプラインの順序」を表している): 11 個の通知は
要求が処理される順序に並んでおり、
ASP.NET の HttpApplication のイベントと対応する。

ISAPI フィルタの通知 ASP.NET の対応するイベント
SF_NOTIFY_PREPROC_HEADERS BeginRequest
SF_NOTIFY_AUTHENTICATION AuthenticateRequest
SF_NOTIFY_AUTH_COMPLETE PostAuthenticateRequest
SF_NOTIFY_URL_MAP MapRequestHandler
SF_NOTIFY_SEND_RESPONSE PreSendRequestHeaders
SF_NOTIFY_END_OF_REQUEST EndRequest
SF_NOTIFY_LOG LogRequest

統合モードでネイティブ モジュールとマネージド モジュールが
混在できる
のは、この順序が 1 本に統合されたからである
IISの動作モデル)。

したがって、現在 ISAPI フィルタでやっていたことは、

用途 現在の手段
URL 書き換え URL Rewrite モジュール(設定のみ)
認証の差し込み HttpModule
HTTP 圧縮 IIS の標準機能(動的圧縮/静的圧縮)
ログの加工 高度なログ、カスタム フィールド

で代替でき、新規に ISAPI フィルタを書く理由はほぼ無い

HttpPlatformHandler

概要

  • 統合モード」の動作モデルで動作する。
  • ARRに似ているが、
    • リモート・サーバーではなく、特定のアウト・プロセスのみを対象にしている。
      アウト・プロセス(指定された実行ファイルのプロセス)の管理までを行う。
    • プロキシでは無いので、HTTPS トラフィックは全て HTTP にオフロードされて渡される。
  • CGI / FastCGI にも似ているが、
    • FastCGI(NamedPipe or TCP)に近い用途だが、HTTP を使用する。
    • CGI / FastCGI よりも実用的なパフォーマンスを出せる

補足(この 3 者の比較が本節の要点): 「ARR に似ている」「CGI に似ている」と
2 方向から説明されているが、表にすると位置付けが明確になる。

ARR FastCGI HttpPlatformHandler
転送先 リモート サーバ ローカルの別プロセス ローカルの別プロセス
プロトコル HTTP FastCGI(独自バイナリ) HTTP
プロセスの起動・管理 しない(相手は既に動いている) する する
主な用途 負荷分散、リバース プロキシ PHP Node.js、Java、Python、ASP.NET Core

つまり HttpPlatformHandler は
**「ARR のプロトコル(HTTP)+ FastCGI のプロセス管理」**という
組み合わせである。

HTTP を使う利点は大きく、

  • 相手が普通の Web サーバでよい(Node.js の http.createServer 等がそのまま使える)、
  • デバッグしやすい(HTTP なので中身が見える)、
  • 言語・処理系を選ばない

という汎用性を得た。
これが後の **ASP.NET Core モジュール(ANCM)**に繋がる。

なお「HTTPS が HTTP にオフロードされる」点は重要で、

影響 対処
アプリ側からは HTTP に見える X-Forwarded-Proto ヘッダーで判定する
リダイレクト URL が http:// になる 転送ヘッダーの処理を有効化
クライアント IP が取れない X-Forwarded-For を見る

ASP.NET Core では ForwardedHeaders ミドルウェア
この処理を担当する。

設定

HttpHandler の追加

HttpApplication(Global.asax)、HttpModule、HttpHandlerを参照。

  • パス指定(基本的には、全てのパス)
  • HTTP メソッドを指定(基本的には、全ての HTTP メソッド)
  • 起動する実行ファイルを指定。

テンプレート

Web.configに設定を行う。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
    </handlers>
    <httpPlatform processPath="startup.bat" arguments="">
      <environmentVariables>
        <environmentVariable name="PORT" value="%HTTP_PLATFORM_PORT%" />
      </environmentVariables>
    </httpPlatform>
  </system.webServer>
</configuration>

補足(%HTTP_PLATFORM_PORT% が仕組みの核心): このテンプレートで
最も重要なのは環境変数 HTTP_PLATFORM_PORT である。

① IIS が空いているポートを 1 つ選ぶ(例: 30125)
② 環境変数 HTTP_PLATFORM_PORT=30125 を設定して子プロセスを起動
③ 子プロセス(アプリ)は、そのポートで listen する
④ IIS は受け取った要求を http://localhost:30125/ へ転送する

つまり、ポート番号を固定で決め打ちしないという設計であり、
これにより

  • 同一サーバで複数のアプリを共存できる(ポート衝突しない)、
  • アプリ プールのリサイクル時も自動で追随する

という利点が得られる。

アプリ側は
この環境変数を読んで listen ポートを決める必要がある。
ASP.NET Core では UseIISIntegration()(または ANCM)が
自動的にこれを処理する。

設定項目

  • handlers - add 要素
    • processPath
      起動する実行ファイル
    • arguments
      実行ファイルに渡されるコマンドライン引数
    • startupTimeLimit
      起動完了までの最大時間
    • startupRetryCount
      起動失敗時のリトライ回数
    • requestTimeout
      HTTP リクエストのタイムアウト時間
    • rapidFailsPerMinute
      ラピッドフェール保護されるまでの失敗回数/分
    • stdoutLogEnabled
      標準出力、標準エラー出力のログ保存
    • stdoutLogFile
      ログファイルのパス
  • httpPlatform 要素
    • environmentVariables - environmentVariable 要素
      • ポート番号
      • リモートデバッグ用ポート番号

移行メモ(構成): 原典では processPath 以下の設定項目が
「handlers - add 要素」の配下に列挙されていたが、
テンプレートを見れば分かるとおり
これらは httpPlatform 要素の属性である。
原典どおりの構成で移行したが、実際の記述位置に注意が要る。

補足(stdoutLogEnabled は障害調査の生命線): 別プロセスで動く以上、
アプリが起動に失敗しても IIS 側には理由が分からない
ブラウザには

HTTP Error 502.5 - Process Failure

のような素っ気ないエラーしか出ない。

このとき、stdoutLogEnabled="true" にしておけば、
アプリが標準出力/標準エラーに出した内容
(例外のスタック トレース、設定ファイルの読み込み失敗など)が
ファイルに残る。原因はほぼここに書かれている

注意点として、

注意 内容
ログ フォルダを事前に作る 無いと出力されない
書き込み権限 アプリ プールの ID に必要
本番では無効に戻す ファイルが際限なく増える

がある。恒久的な有効化ではなく、障害時に一時的に有効化するのが正しい。

注意

ASP.NET をホストするワーカープロセスである w3wp.exeprocessPath に指定できない模様。
(ASP.NET の中では HttpPlatformHandler を使用できないので、潔く HttpHandler(HttpApplication(Global.asax)、HttpModule、HttpHandler)を使用する。)

補足(最新化:HttpPlatformHandler の後継): HttpPlatformHandler は
**ASP.NET Core モジュール(ANCM)**に発展的に置き換わった。

HttpPlatformHandler ASP.NET Core モジュール(ANCM)
対象 任意の実行ファイル ASP.NET Core に特化
ホスティング アウトプロセスのみ インプロセス(既定)/アウトプロセス
性能 プロセス間 HTTP のホップあり インプロセスならホップ無し
現状 保守のみ 現行

ANCM のインプロセス ホスティングでは、
w3wp.exe の中で Kestrel が動く
本文の「w3wp.exeprocessPath に指定できない」という制約が、
別の方式で解決された格好になる。

一方、PHP / Node.js / Java を IIS でホストしたい場合は、
HttpPlatformHandler が今も使える
(PHP は FastCGI、Node.js は iisnode という選択肢もある)。

参考

Web/DB プログラミング徹底解説

しばやん雑記

関連

HttpHandler

HttpApplication(Global.asax)、HttpModule、HttpHandler


Tags: 移行, Windows, IIS

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally