IIS 7.0 核心架構革新
IIS 7.0 採用全模組化架構,所有功能(靜態檔案服務、驗證、壓縮、ASP.NET 執行)皆為可替換的模組。請求處理管線整合 ASP.NET,使 managed code 可參與所有請求階段,不限於 .aspx 檔案。
兩種模組開發路徑
| 特性 | C++ 原生模組 API | ASP.NET Managed 模組 |
| 效能 | 極高 (原生碼) | 高 (CLR 執行) |
| 開發難度 | 高 | 低 (熟悉 C#/VB.NET) |
| API 豐富度 | 完整 IIS 功能 | 完整 IIS + .NET Framework |
| 部署 | 註冊 DLL | 放入 Bin/GAC + web.config |
| 除錯 | Windbg/SOS | Visual Studio 直接偵錯 |
Managed 模組開發實作:回應修改模組
1. 實作 IHttpModule
public class ResponseModifierModule : IHttpModule {
public void Init(HttpApplication context) {
context.ReleaseRequestState += OnReleaseRequestState;
}
private void OnReleaseRequestState(object sender, EventArgs e) {
HttpApplication app = (HttpApplication)sender;
HttpResponse response = app.Response;
// 僅處理 HTML 回應
if (response.ContentType?.StartsWith("text/html") == true) {
response.Filter = new ResponseModifierStream(response.Filter, GetRules());
}
}
private List GetRules() {
// 從設定檔讀取替換規則
return ConfigurationManager.GetSection("responseModifier/rules") as List;
}
public void Dispose() { }
}
2. 自訂 Stream 進行內容替換
public class ResponseModifierStream : Stream {
private readonly Stream _baseStream;
private readonly List _rules;
private readonly MemoryStream _buffer = new MemoryStream();
public ResponseModifierStream(Stream baseStream, List rules) {
_baseStream = baseStream;
_rules = rules;
}
public override void Write(byte[] buffer, int offset, int count) {
_buffer.Write(buffer, offset, count);
}
public override void Close() {
_buffer.Position = 0;
using (var reader = new StreamReader(_buffer, Encoding.UTF8)) {
string html = reader.ReadToEnd();
// 套用所有替換規則
foreach (var rule in _rules) {
html = Regex.Replace(html, rule.Pattern, rule.Replacement, rule.Options);
}
byte[] data = Encoding.UTF8.GetBytes(html);
_baseStream.Write(data, 0, data.Length);
}
_baseStream.Close();
}
// 其他 Stream 抽象方法轉給 _baseStream...
}
自定義設定區段與 IIS Manager 整合
1. 定義設定區段
<configSections>
<section name="responseModifier"
type="ResponseModifier.Configuration.ResponseModifierSection, ResponseModifier" />
</configSections>
<responseModifier>
<rules>
<add pattern="<!--\s*DEBUG\s*-->" replacement=""
options="IgnoreCase" description="移除 DEBUG 註解" />
<add pattern="https://oldsite\.com" replacement="https://newsite.com"
description="網域遷移" />
<add pattern="</body>" replacement="<script src='/tracking.js'></script></body>"
description="植入追蹤碼" />
</rules>
</responseModifier>
2. 設定區段類別
public class ResponseModifierSection : ConfigurationSection {
[ConfigurationProperty("rules")]
public ReplaceRuleCollection Rules => (ReplaceRuleCollection)this["rules"];
}
[ConfigurationCollection(typeof(ReplaceRule), AddItemName = "add")]
public class ReplaceRuleCollection : ConfigurationElementCollection {
protected override ConfigurationElement CreateNewElement() => new ReplaceRule();
protected override object GetElementKey(ConfigurationElement element)
=> ((ReplaceRule)element).Pattern;
}
public class ReplaceRule : ConfigurationElement {
[ConfigurationProperty("pattern", IsRequired = true)]
public string Pattern => (string)this["pattern"];
[ConfigurationProperty("replacement", IsRequired = true)]
public string Replacement => (string)this["replacement"];
[ConfigurationProperty("options", DefaultValue = RegexOptions.None)]
public RegexOptions Options => (RegexOptions)this["options"];
[ConfigurationProperty("description")]
public string Description => (string)this["description"];
}
IIS Manager 管理介面開發
1. 模組註冊 (web.config 或 applicationHost.config)
<system.webServer>
<modules>
<add name="ResponseModifier"
type="ResponseModifier.ResponseModifierModule, ResponseModifier"
preCondition="managedHandler" />
</modules>
</system.webServer>
2. 建立 IIS Manager UI 模組
- 參考
Microsoft.Web.Management.dll
- 實作
IModule、IModuleProvider
- 使用 WinForms/WPF 建立規則編輯介面
- 透過
ConfigurationService 讀寫設定
部署策略
| 環境 | 部署方式 | 注意事項 |
| 開發機 | Visual Studio F5 偵錯 | 直接修改 applicationHost.config |
| 測試/Staging | XCopy / Web Deploy | 需管理員權限註冊模組 |
| 生產環境 | Web Deploy / MSI 安裝包 | 建議使用 preCondition="integratedMode" |
| 伺服器場 | 共用設定 + 中央憑證存儲 | 同步 applicationHost.config |
效能最佳化建議
- 非同步模組:實作
IHttpAsyncHandler 避免阻塞執行緒
- 快取編譯規則:Regex 物件建立成本高,啟動時預編譯並快取
- 限制處理範圍:透過
preCondition 或程式碼判斷 Content-Type、URL 路徑
- 串流處理:大型回應使用串流式替換,避免完整緩衝到記憶體
- 監控指標:記錄處理耗時、替換次數、錯誤率至 ETW/EventLog
遷移自 ISAPI Filter/Extension 的關鍵點
- ISAPI Filter →
IHttpModule (事件模型相似)
- ISAPI Extension →
IHttpHandler + 路由對應
- 原生 C++ 程式碼可透過 P/Invoke 或 C++/CLI 混合模組重用
- 註冊方式從註冊表改為
system.webServer/modules