2023年11月28日发(作者:)

HTTP304状态码的详细讲解

HTTP 304状态码的详细讲解

整个请求响应过程如下:

客户端在请求⼀个⽂件的时候,发现⾃⼰缓存的⽂件有 Last Modified ,那么在请求中会包含 If Modified Since ,这个时间就是缓存⽂件

Last Modified 。因此,如果请求中包含 If Modified Since,就说明已经有缓存在客户端。服务端只要判断这个时间和当前请求的⽂件的修

改时间就可以确定是返回 304 还是 200

对于静态⽂件,例如:CSS、图⽚,服务器会⾃动完成 Last Modified If Modified Since 的⽐较,完成缓存或者更新。但是对于动态页

⾯,就是动态产⽣的页⾯,往往没有包含 Last Modified 信息,这样浏览器、⽹关等都不会做缓存,也就是在每次请求的时候都完成⼀

200 的请求。

因此,对于动态页⾯做缓存加速,⾸先要在 Response HTTP Header 中增加 Last Modified 定义,其次根据 Request 中的 If Modified

Since 和被请求内容的更新时间来返回 200 或者 304 。虽然在返回 304 的时候已经做了⼀次数据库查询,但是可以避免接下来更多的数据

库查询,并且没有返回页⾯内容⽽只是⼀个 HTTP Header,从⽽⼤⼤的降低带宽的消耗,对于⽤户的感觉也是提⾼。当这些缓存有效的时

候,通过 Fiddler HttpWatch 查看⼀个请求会得到这样的结果:

第⼀次访问 200

F5刷新(第⼆次访问) 304

Ctrl+F5强制刷新 200

下⾯⽤Fiddler来查看上⾯的访问请求过程

第⼀次(⾸次)访问 200

第⼆次F5刷新访问 304

请求的头信息⾥多了 “If-Modified-Since","If-None-Match"

第三次 Ctrl+F5强制刷新 200同第⼀次,不贴图了

为什么要使⽤条件请求当⽤户访问⼀个⽹页时,条件请求可以加速⽹页的打开时间(因为可以省去传输整个响应体的时间),但仍然会有⽹络延

,因为浏览器还是得为每个资源⽣成⼀条条件请求,并且等到服务器返回HTTP/304响应,才能读取缓存来显⽰⽹页.更理想的情况是,服务器在

响应上指定Cache-ControlExpires指令,这样客户端就能知道该资源的可⽤时间为多长,也就能跳过条件请求的步骤,直接使⽤缓存中的资源

.可是,即使服务器提供了这些信息,在下列情况下仍然需要使⽤条件请求:

在超过服务器指定的过期时间之后

如果⽤户执⾏了刷新操作的话

在上节给出的图⽚中,请求头中包含了⼀个Pragma: no-cache.这是由于⽤户使⽤F5刷新了⽹页.如果⽤户按下了CTRL-F5 (有时称之为强刷-

hard refresh”),你会发现浏览器省略了If-Modified-SinceIf-None-Match请求头,也就是⽆条件的请求页⾯中的每个资源.

避免条件请求

通常来说,缓存是个好东西.如果你想提⾼⾃⼰⽹站的访问速度,缓存是必须要考虑的.可是在调试的时候,有时候需要阻⽌缓存,这样才能确保你

所访问到的资源是最新的.

你也许会有个疑问:“如果不改变⽹站内容,我怎么才能让Fiddler不返回304⽽返回⼀个包含响应体的HTTP/200响应呢?”

你可以在Fiddler中的⽹络会话(Web Sessions)列表中选择⼀条响应为HTTP/304的会话,然后按下U.Fiddler将会⽆条件重发

(Unconditionally reissue)这个请求.然后使⽤命compare命令对⽐⼀下两个请求有什么不同,对⽐结果如下,从中可以得知,Fiddler是通过省略条

件请求头来实现⽆缓存请求的:

Screenshot of Windiff of conditional and unconditional requests

如果你想全局阻⽌HTTP/304响应,可以这么做:⾸先清除浏览器的缓存,可以使⽤Fiddler⼯具栏上的Clear Cache按钮(仅能清除Internet

Explorer缓存),或者在浏览器上按CTRL+SHIFT+DELETE(所有浏览器都⽀持).在清除浏览器的缓存之后,回到Fiddler,在菜单中选择Rules >

Performance > Disable Caching选项,然后Fiddler就会:删除所有请求中的条件请求相同的请求头以及所有响应中的缓存时间相关的响应头.

,还会在每个请求中添加Pragma: no-cache请求头,在每个响应中添加Cache-Control: no-cache响应头,阻⽌浏览器缓存这些资源.

动态⽹页如何设置304

aspx页⾯为例,代码如下:

1. var request = t;

2. var response = se;

3. if (s["If-Modified-Since"].NotNullOrEmpty() || s["If-None-Match"].NotNullOrEmpty())

4. {

5. Code = 304;

6. return;

7. }

8. //304

情况下的操作

9. //

设置缓存选项

10. ();

11. ontent();

12. s["Last-Modified"] = ng("yyyy-MM-dd HH:mm:ss");

13. s["ETag"] = id;//id

这⾥假设的是根据不同的

14. ontrol = "private";

15. sAbsolute = ths(6);

ETag是什么意思?HTTP 协议规格说明定义ETag被请求变量的实体值 另⼀种说法是,ETag是⼀个可以与Web资源关联的记号

token)。典型的Web资源可以⼀个Web页,但也可能是JSONXML⽂档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头

中将其传送到客户端

web api的实现代码如下:

1. // GET /images/

2. [HttpGet]

3. public HttpResponseMessage Get(string filename)

4. {

5. HttpResponseMessage response = new HttpResponseMessage();

6.

7. .....

8. string etag = (""{0}"", 5);

9. var tag = rDefault();

10. if (ue && tag != null && == etag)

11. {

12. Code = ified;

13. }

14. else

15. {

16. //dealcode ......

17. on = 0;

18. Code = fullContent ? : lContent;

19. t = new StreamContent(responseStream);

20. tType = new MediaTypeHeaderValue(tType);

21. = new EntityTagHeaderValue(etag);

22. ontrol = new CacheControlHeaderValue();

23. = true;

24. = urs(480);

25. s = s(20);

26. dified = Date;

27. }

28. return response;

29. }

常见状态码:

⼀些常见的状态码为:

200 – 服务器成功返回⽹页

404 – 请求的⽹页不存在

503 – 服务器超时

下⾯提供 HTTP 状态码的完整列表。点击链接可了解详情。您也可以访问

1xx(临时响应)

表⽰临时响应并需要请求者继续执⾏操作的状态码。

100(继续)请求者应当继续提出请求。服务器返回此代码表⽰已收到请求的第⼀部分,正在等待其余部分。

101(切换协议)请求者已要求服务器切换协议,服务器已确认并准备切换。

2xx (成功)

表⽰成功处理了请求的状态码。

200(成功)

服务器已成功处理了请求。通常,这表⽰服务器提供了请求的⽹页。如果是对您的 ⽂件显⽰此状态码,则表

Googlebot 已成功检索到该⽂件。

201(已创建)请求成功并且服务器创建了新的资源。

202(已接受)服务器已接受请求,但尚未处理。

203(⾮授权信

服务器已成功处理了请求,但返回的信息可能来⾃另⼀来源。

息)

204(⽆内容)服务器成功处理了请求,但没有返回任何内容。

205(重置内

容)以输⼊新内容)。

206(部分内

容)

服务器成功处理了请求,但没有返回任何内容。与 204 响应不同,此响应要求请求者重置⽂档视图(例如,清除表单内容

服务器成功处理了部分 GET 请求。

3xx (重定向)

要完成请求,需要进⼀步操作。通常,这些状态码⽤来重定向。Google 建议您在每次请求中使⽤重定向不要超过 5 次。您可以使⽤⽹站管

理员⼯具查看⼀下 Googlebot 在抓取重定向⽹页时是否遇到问题。诊断下的页列出了由于重定向错误导致 Googlebot ⽆法抓取的⽹址。

300(多

种选针对请求,服务器可执⾏多种操作。服务器可根据请求者 (user agent) 选择⼀项操作,或提供操作列表供请求者选择。

择)

301(永

请求的⽹页已永久移动到新位置。服务器返回此响应(对 GET HEAD 请求的响应)时,会⾃动将请求者转到新位置。您应使⽤

久移

此代码告诉 Googlebot 某个⽹页或⽹站已永久移动到新位置。

动)

302(临

服务器⽬前从不同位置的⽹页响应请求,但请求者应继续使⽤原有位置来响应以后的请求。此代码与响应 GET HEAD 请求

时移 301 代码类似,会⾃动将请求者转到不同的位置,但您不应使⽤此代码来告诉 Googlebot 某个⽹页或⽹站已经移动,因

动) Googlebot 会继续抓取原有位置并编制索引。

303(查

请求者应当对不同的位置使⽤单独的 GET 请求来检索响应时,服务器返回此代码。对于除 HEAD 之外的所有请求,服务器会⾃动

307(临

服务器⽬前从不同位置的⽹页响应请求,但请求者应继续使⽤原有位置来响应以后的请求。此代码与响应 GET HEAD 请求

时重定 301 代码类似,会⾃动将请求者转到不同的位置,但您不应使⽤此代码来告诉 Googlebot

向)个页⾯或⽹站已经移动,因为 Googlebot 会继续抓取原有位置并编制索引。

4xx(请求错误)

这些状态码表⽰请求可能出错,妨碍了服务器的处理。

400(错误请

服务器不理解请求的语法。

求)

401(未授

权)

403(禁⽌)

请求要求⾝份验证。对于登录后请求的⽹页,服务器可能返回此响应。

服务器拒绝请求。如果您在 Googlebot 尝试抓取您⽹站上的有效⽹页时看到此状态码(您可以在 Google ⽹站管理员⼯具诊

断下的⽹络抓取页⾯上看到此信息),可能是您的服务器或主机拒绝了 Googlebot 访问。

服务器找不到请求的⽹页。例如,对于服务器上不存在的⽹页经常会返回此代码。

如果您的⽹站上没有 ⽂件,⽽您在 Google ⽹站管理员⼯具上看到此状态码,则这是正确的状态码。但是,如果您

⽂件⽽⼜看到此状态码,则说明您的 ⽂件可能命名错误或位于错误的位置(该⽂件应当位于顶级域,

名为 )。到)

如果对于 Googlebot 抓取的⽹址看到此状态码(在诊断标签的 上),则表⽰ Googlebot 跟随的可能是另⼀个页⾯的⽆效链

接(是旧链接或输⼊有误的链接)。

405(⽅法禁

禁⽤请求中指定的⽅法。

⽤)

406(不接

受)

⽆法使⽤请求的内容特性响应请求的⽹页。

404(未找

407(需要代

此状态码与 401(未授权)类似,但指定请求者应当授权使⽤代理。如果服务器返回

理授权)此响应,还表⽰请求者应当使⽤代理。

408(请求超

服务器等候请求时发⽣超时。

时)

409(冲突)

410(已删

除)的情况下,有时会⽤来替代 404 代码。如果资源已永久移动,您应使⽤ 301 指定资源的新位置。

服务器在完成请求时发⽣冲突。服务器必须在响应中包含有关冲突的信息。服务器在响应与前⼀个请求相冲突的 PUT 请求时

可能会返回此代码,以及两个请求的差异列表。

如果请求的资源已永久删除,服务器就会返回此响应。该代码与 404(未找到)代码类似,但在资源以前存在⽽现在不存在

411(需要有

服务器不接受不含有效内容长度标头字段的请求。

效长度)

412(未满⾜

服务器未满⾜请求者在请求中设置的其中⼀个前提条件。

前提条件)

413(请求实

服务器⽆法处理请求,因为请求实体过⼤,超出服务器的处理能⼒。

体过⼤)

414(请求

URI 请求的 URI(通常为⽹址)过长,服务器⽆法处理。

长)

415(不⽀持

请求的格式不受请求页⾯的⽀持。

的媒体类

型)

416(请求范

围不符合要如果页⾯⽆法提供请求的范围,则服务器会返回此状态码。

求)

417(未满⾜

服务器未满⾜期望请求标头字段的要求。

期望值)

5xx(服务器错误)

这些状态码表⽰服务器在处理请求时发⽣内部错误。这些错误可能是服务器本⾝的错误,⽽不是请求出错。