我对 IIS 7 有一个奇怪的问题。
有时它似乎返回 304 而不是 200。
这是使用 Fiddler 捕获的示例请求:(
请注意,请求的文件尚未位于我的浏览器缓存中。)
GET https://[mysite]/Content/js/jquery.form.js HTTP/1.1 Accept: */* Referer: https://[mysite]/Welcome/News Accept-Language: sv-SE User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET4.0C; .NET4.0E) Accept-Encoding: gzip, deflate Host: [mysite] Connection: Keep-Alive Cache-Control: no-cache Cookie: ...
请注意,请求中没有 If-Modified-Since 或 If-None-Match。
但反应仍然是:
HTTP/1.1 304 Not Modified Cache-Control: public Expires: Tue, 02 Mar 2010 06:26:08 GMT Last-Modified: Mon, 22 Feb 2010 21:58:44 GMT ETag: "1CAB40A337D4200" Server: Microsoft-IIS/7.5 X-Powered-By: ASP.NET Date: Mon, 01 Mar 2010 17:06:34 GMT
有谁知道这里可能出了什么问题?
我在 Windows Web Server 2008 R2 上运行 IIS 7。
编辑:
我找到了一种解决方法,启用缓存然后在扩展级别禁用它对我来说是诀窍。
<configuration>
<system.webServer>
<caching enabled="true" enableKernelCache="true">
<profiles>
<add extension=".png" policy="DisableCache" kernelCachePolicy="DisableCache" />
<add extension=".gif" policy="DisableCache" kernelCachePolicy="DisableCache" />
<add extension=".js" policy="DisableCache" kernelCachePolicy="DisableCache" />
<add extension=".css" policy="DisableCache" kernelCachePolicy="DisableCache" />
</profiles>
</caching>
<staticContent>
<clientCache cacheControlMode="NoControl" />
</staticContent>
</system.webServer>
</configuration>
根据HTTP1.1 规范的第 14.9 节,Cache-Control 标头的
no-cache
指令只能由源服务器强制执行,这意味着 IIS 会忽略您请求中的标头。第 14.9.1 节将
public
、private
和定义no-cache
为限制可缓存内容的指令,这些指令只能由服务器强制执行。如果您不希望缓存 .js 文件,则需要
no-cache
在应用程序中设置指令(即 ASP.NET 代码),或者您需要更改Cache-Control
请求中的标头以使用该no-store
指令而不是no-cache
.编辑:
根据您的评论 - 是的,我假设您不希望缓存文件。那么,304 可能是由于文件位于 IIS 的内部缓存之一中而出现的。看看这些:
我遇到同样的问题已经有一段时间了,并且所有缓存都关闭了……但是,我在某个时候为 IIS7 安装了压缩模块,默认情况下,它在我现有的站点上启用了静态文件的压缩。我关闭了受影响站点的所有压缩功能,现在它们似乎可以正常工作。
我们也遇到了这个错误,但我们使用的是资产管理库(Cassette)。在对此问题进行广泛调查后,我们发现此问题的根本原因在于 ASP.NET、IIS 和 Cassette 的组合。我不确定这是否是您的问题(使用
Headers
API 而不是Cache
API),但模式似乎是相同的。错误 #1
Cassette 将
Vary: Accept-Encoding
标头设置为对捆绑包的响应的一部分,因为它可以使用 gzip/deflate 对内容进行编码:但是,ASP.NET 输出缓存将始终返回首先缓存的响应。例如,如果第一个请求有
Accept-Encoding: gzip
并且 Cassette 返回 gzip 压缩的内容,则 ASP.NET 输出缓存会将 URL 缓存为Content-Encoding: gzip
. 对相同 URL 但使用不同的可接受编码(例如 )的下一个请求Accept-Encoding: deflate
将返回缓存的响应Content-Encoding: gzip
。此错误是由 Cassette 使用
HttpResponseBase.Cache
API 设置输出缓存设置(例如Cache-Control: public
)但使用HttpResponseBase.Headers
API 设置Vary: Accept-Encoding
标头引起的。问题是 ASP.NETOutputCacheModule
不知道响应头;它只能通过Cache
API 工作。也就是说,它希望开发人员使用不可见的紧密耦合 API,而不仅仅是标准 HTTP。错误 #2
使用 IIS 7.5 (Windows Server 2008 R2) 时,错误 #1 可能会导致 IIS 内核和用户缓存出现单独的问题。例如,一旦使用 成功缓存了一个包
Content-Encoding: gzip
,就可以在 IIS 内核缓存中使用netsh http show cachestate
. 它显示带有 200 状态代码和“gzip”内容编码的响应。如果下一个请求具有不同的可接受编码(例如Accept-Encoding: deflate
)和与捆绑包哈希匹配的If-None-Match
标头,则进入 IIS 内核和用户模式缓存的请求将被视为未命中。因此,导致请求由返回 304 的 Cassette 处理:但是,一旦 IIS 的内核和用户模式处理了响应,他们将看到 URL 的响应发生了变化,并且应该更新缓存。如果
netsh http show cachestate
再次检查 IIS 内核缓存,缓存的 200 响应将替换为 304 响应。对捆绑包的所有后续请求,无论是否Accept-Encoding
将If-None-Match
返回 304 响应。我们看到了这个 bug 的破坏性影响,所有用户都被我们的核心脚本提供了 304,因为随机请求有一个意外的Accept-Encoding
和If-None-Match
.问题似乎是 IIS 内核和用户模式缓存无法根据
Accept-Encoding
标头而变化。作为这一点的证据,通过将Cache
API 与下面的解决方法一起使用,似乎总是会跳过 IIS 内核和用户模式缓存(仅使用 ASP.NET 输出缓存)。这可以通过netsh http show cachestate
使用下面的解决方法检查是否为空来确认。ASP.NET 直接与 IIS 工作线程通信,以根据请求选择性地启用或禁用 IIS 内核和用户模式缓存。我们无法在较新版本的 IIS(例如 IIS Express 10)上重现此错误。但是,错误 #1 仍然是可重现的。
我们对这个错误的最初修复是只对其他提到的 Cassette 请求禁用 IIS 内核/用户模式缓存。通过这样做,我们在我们的 Web 服务器前部署额外的缓存层时发现了错误 #1。查询字符串 hack 起作用的原因是,如果
OutputCacheModule
API未Cache
用于根据QueryString
QueryString
.解决方法
无论如何,我们一直在计划离开 Cassette,因此我们没有维护我们自己的 Cassette 分支(或尝试合并 PR),而是选择使用 HTTP 模块来解决这个问题。
我希望这对某人有帮助?!