来自 httpHandler 的响应在客户端随机丢失字符

Response from httpHandler is randomly missing characters on client

问题:

当浏览器收到来自我们 .NET 站点的响应时,通常会随机丢失原始部分(在 two-character 块中)

详情:

我们有一个名为 CssCombineHandler 的自定义 httpHandler,它将多个 CSS 文件的内容合并到一个 axd 文件中。

在web.config中是这样指定的:

<httpHandlers>
  <add path="css.axd" verb="*" type="MyNamespace.CssCombineHandler, MyNamespace"/>
</httpHandlers>

它是通过这样的 URL 调用的...

http://example.com/css.axd?files=..%2fcss%2fFile1.css%2c..%2fcss%2fFile2.css%2c..%2fcss%2fFile3.css

files 参数中列出的所有文件都合并到响应中。

相关代码是这样的:

    context.Response.ClearHeaders()
    context.Response.ContentType = "text/css"        
    context.Response.Cache.SetExpires(someDate)
    context.Response.Cache.SetMaxAge(someOtherDate)
    context.Response.Cache.SetCacheability(HttpCacheability.Public)
    context.Response.Cache.VaryByParams("files") = True    
    context.Response.BufferOutput = False  'See notes about this below

    Dim responseBody As New StringBuilder()

    '(Loop through files here)
    responseBody.Append(File.ReadAllText(context.Server.MapPath(currentFileUri.AbsolutePath)))
    '(end loop)

    context.Response.Write(responseBody.ToString())  'Here it has the full, correct string!

但是当您检查响应时(例如在 Firefox 或 Chrome 开发工具的网络选项卡中),它通常至少有一个地方连续两个字符已被删除。效果是随机的,具体取决于它发生的位置,但是例如,原始的 CSS...

visibility:visible!important;

...可能会更改为...

visibilitvisible!important;

我在组合文件中看到这种情况发生 0-3 次,具体取决于文件的总大小。对组合文件内容的任何更改(即更改其中一个正在组合的文件,或更改正在组合的文件列表)都可能导致丢失的字符移动到不同的位置。

我尝试过的事情:

我还没有接触过这么多东西,所以请原谅我的无知。这是我到目前为止尝试过的。

这适用于较小的响应 但是 如果我合并了多个文件,就好像响应太大并且某些东西(.NET?IIS?)正在强制它回到分块模式,然后再次丢失字符。我不知道阈值,但是例如 15k 响应将正确缓冲,但 82k 响应不会

 context.Response.ContentEncoding = Encoding.UTF8
 context.Response.Charset = "UTF-8"

并更改为

File.ReadAllText(context.Server.MapPath(currentFileUri.AbsolutePath), Encoding.UTF8)

...但这并没有什么不同。这实际上是有道理的,因为我认为 Response.Write() 中的字符串已经正确,因此组合不同的文件似乎不是问题。

context.Response.AddHeader("Content-Length", "500000")
Dim bytes As Byte() = System.Text.Encoding.UTF8.GetBytes(responseBody.ToString())
context.Response.OutputStream.Write(bytes, 0, bytes.Length)

备注:

事实证明,我们有一个单独的 http 模块,我们在其中设置 Response.Filter 以动态替换 CSS 文件中的 URL 为环境的正确值(例如,测试版与生产 URL) .

显然,当您使用过滤器时,它会使用内部流或其他东西,我仍然不确定确切原因,但是组合各种流时出了点问题(当总内容对于一个流来说太大时? ) 到响应的最终输出中。

我们通过避免 运行 在组合的 css.axd 文件上使用此过滤器并仅在普通 css 文件上使用此过滤器来修复它(以防直接被击中)。然后在我们的 cssCombineHandler 中,我们 运行 在 response.write().[=12 之前的组合 CSS 字符串上使用相同的替换逻辑=]