作爲一個實驗,我一直在嘗試創建一個IIS託管模塊來動態修改CSS文件。背後的故事是,所有的Web應用程序都保留一個共享和通用的版本號,我們附加到每個JS,CSS和圖像引用(HTML)中,並且我想修改CSS的實際內容以將版本號附加到圖像引用在CSS中。所以,舉例來說:自定義IIS模塊與gzip衝突
span.warning { background-image: url(warning-icon.png) }
應該變成:
span.warning { background-image: url(warning-icon.png?123) }
現在,我知道有很多不同的方法解決這個問題(和一些也許更好),但如果任何人都可以我想知道回答我關於我一直在玩的那個問題。
到目前爲止,我已經瞭解到託管的HTTP模塊不能直接修改響應流(我認爲),並且正確的方法是追加輸出過濾器來完成工作。我已經寫了下面的測試模塊:
public class HttpCSSModule : IHttpModule
{
public void Init(HttpApplication httpApplication)
{
httpApplication.BeginRequest += new EventHandler(
(s, e) => AttachFilter((HttpApplication)s));
}
private void AttachFilter(HttpApplication httpApplication)
{
HttpRequest httpRequest = httpApplication.Context.Request;
HttpResponse httpResponse = httpApplication.Context.Response;
if (httpRequest.Path.EndsWith(".css", StringComparison.CurrentCultureIgnoreCase))
{
if (!string.IsNullOrEmpty(httpRequest.Url.Query))
{
httpResponse.Filter = new CSSResponseStreamFilter(
httpResponse.Filter, httpRequest.Url.Query);
}
}
}
public void Dispose()
{
}
private class CSSResponseStreamFilter : Stream
{
private Stream inner;
private string version;
private MemoryStream responseBuffer = new MemoryStream();
public CSSResponseStreamFilter(Stream inner, string version)
{
this.inner = inner;
this.version = version;
}
public override void Close()
{
if (responseBuffer.Length != 0)
{
string stylesheet = Encoding.ASCII.GetString(
responseBuffer.GetBuffer(), 0, (int)responseBuffer.Length);
// crude, just testing
string versionedStylesheet = stylesheet.
Replace(".png", ".png" + version).
Replace(".jpg", ".jpg" + version).
Replace(".gif", ".gif" + version);
byte[] outputBytes = Encoding.ASCII.GetBytes(versionedStylesheet);
innerStream.Write(outputBytes, 0, outputBytes.Length);
}
innerStream.Close();
}
public override void Write(byte[] buffer, int offset, int count)
{
responseBuffer.Write(buffer, offset, count);
}
// other Stream members
}
}
模塊的工作原理,但並不總是和有件事情我不明白。最大的問題是當靜態文件壓縮打開時模塊不工作。當打開靜態文件壓縮時,對CSS文件的第一個請求就像往常一樣提供文件,但大概IIS會保留gzip版本,並且在任何子序列請求中,我的自定義流都會傳遞gzipped流。我還沒有找到檢測它的方法,但是可能存在更深層次的問題,因爲我實際上可能不瞭解IIS模塊應該如何工作。我的模塊應該對另一個模塊進行任何假設似乎是錯誤的,或者至少應該能夠定義它們在IIS配置中處理請求的順序。但是,這似乎沒有道理,因爲每個模塊都可以註冊以處理請求生命週期中的任何事件。
所以,如果我不得不重新制定我的想法,以更精緻的問題,這些問題將是:
我如何確保我的後處理/模塊稱爲文件由StaticFileModule模塊讀取和服務器之後,但在StaticCompressionModule之前?這個問題甚至有意義嗎?根據以上觀察,似乎有點矛盾。
我有同樣的問題,我正在工作幾個小時來解決它。 :(你可以向我解釋一下你是如何解決這個問題的嗎? – iboware 2012-11-12 11:59:13