瀏覽器網址列**不會改變**。使用者輸入 `https://user.example.com`,DNS 解析至同一台 Web Server,IIS 接收請求,ASP.NET `HttpModule` 在管線早期攔截,**內部**將路徑重寫為 `https://example.com/User.aspx?username=user`,後續處理完全基於重寫後的路徑。使用者感知不到任何轉向。
例:`{subdomain}.example.com` → `/User/Profile.aspx?domain={subdomain}`
using System;
using System.Web;
public class SubdomainRewriter : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += OnBeginRequest;
}
private void OnBeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpContext context = app.Context;
string host = context.Request.Url.Host.ToLower(); // 如: user.example.com
string[] parts = host.Split('.');
// 判斷是否為二級域名 (排除 www、本機、IP)
if (parts.Length == 3 && parts[1] == "example" && parts[2] == "com" && parts[0] != "www")
{
string subdomain = parts[0]; // user
string rewritePath = $"/User/Profile.aspx?domain={subdomain}";
// 內部重寫:瀏覽器網址不變
context.RewritePath(rewritePath);
}
}
public void Dispose() { }
}
IIS 6 / 傳統管線模式:
<system.web>
<httpModules>
<add name="SubdomainRewriter" type="MyNamespace.SubdomainRewriter, MyAssembly" />
</httpModules>
</system.web>
IIS 7+ / 整合管線模式 (建議):
<system.webServer>
<modules>
<add name="SubdomainRewriter" type="MyNamespace.SubdomainRewriter, MyAssembly" preCondition="managedHandler" />
</modules>
</system.webServer>
手寫 HttpModule 適合簡單規則。複雜專案建議使用:
<system.webServer>
<rewrite>
<rules>
<rule name="Subdomain to User Profile" stopProcessing="true">
<match url="^(.*)$" />
<conditions>
<add input="{HTTP_HOST}" pattern="^([^.]+)\.example\.com$" />
<add input="{C:1}" pattern="^www$" negate="true" />
</conditions>
<action type="Rewrite" url="/User/Profile.aspx?domain={C:1}" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
任意二級域名實現核心:DNS 泛域名解析 + IIS 繫結 + ASP.NET 管線早期 `HttpModule`/`URL Rewrite Module` 內部重寫。採用 IIS 原生 URL Rewrite Module 為首選,效能最佳、規則聲明式、支援豐富條件與輸出重寫。手寫 HttpModule 適合輕量專案或特殊邏輯需求。