zoukankan      html  css  js  c++  java
  • Conditional GET Request(缓存协商)

    线上日志查到HTTP/1.1 412 Precondition Failed,一种追究下去,发现了很多关联的内容。

     

    1. 412的响应值代表了什么?
    问:
    It is unclear to me when you should and should not return a HTTP 412: Precondition Failed, error for a web service? I am thinking of using it when validating data. For example, if a client POST's XML data and that data is missing a required data element, then responding with a 412 and a description of the error.
    Does that align with the sprit of responding with an HTTP 412, or should something else be used (e.g. another http error code or web application exception)?

    答:
     
    If you look at RFC 2616 you'll see a number of request headers that can be used to apply conditions to a request:
    If-Match
    If-Modified-Since
    If-None-Match
    If-Range
    If-Unmodified-Since
    These headers contain 'preconditions', allowing the client to tell the server to only complete the request if certain conditions are met. For example, you use a PUT request to update the state of a resource, but you only want the PUT to be actioned if the resource has not been modified by someone else since your most recent GET.
    The response status code 412 (Precondition Failed) is typically used when these preconditions fail.
    Your example sounds like an invalid request (i.e. the client has submitted data that is invalid because of missing values). A status code of 400 (Bad Request) is more appropriate here IMO.




    2. Conditional GET Request(缓存协商)


    2.1 Conditional GET Request

    The HTTP Protocol defines a caching mechanism, in which the proxy web-servers can cache pages, files, images etc. Since caching is in place, There is a method which the servers are asked to return the document, either the “cached” or “live” document.
    This request of asking the server for a document considering a specific parameter is called a Conditional GET Request. In this request, a specific request header is sent If-Modified-Since. This header sends a RFC 2822 formatted date as the value. The proxy which is between the Server and the client checks the date, and the cached document, if the condition matches, A 304 Not Modified header is sent back to the client in the response.
    So consider a document /sample.html on example.com. Consider the very first request of the Client, Since this is the first request, the client does not know about the modified time, etc…
    Here goes the request header as follows…
    GET /sample.html HTTP/1.1
    Host: example.com
    Now the response that comes from the server is the document with the response headers. The response headers would be…
    HTTP/1.x 200 OK
    Via: The-proxy-name
    Content-Length: 32859
    Expires: Tue, 27 Dec 2005 11:25:11 GMT
    Date: Tue, 27 Dec 2005 05:25:11 GMT
    Content-Type: text/html; charset=iso-8859-1
    Server: Apache/1.3.33 (Unix) PHP/4.3.10
    Cache-Control: max-age=21600
    Last-Modified: Wed, 01 Sep 2004 13:24:52 GMT
    Etag: “4135cda4″
    Lets check what these headers mean..
        •    Cache-Control: It tells the client the maximum time in seconds to cache the document.
        •    Last-Modified: The document’s last modified date
        •    Etag: A unique hash for the document.
    Once the Server responds, the client caches the document and stores it for the specified amount of time, In this case for 21600 seconds.
    Next time when the user calls for the same document /sample.html within the specified cache time frame. The browser(client) will make a conditional get request, try to ask the server that if the document is modified after the specified time zone whose hashed value was the Etag value, ONLY THEN return a new document or else confirm that it is an old document.
    So the request header would be as…
    GET /sample.html HTTP/1.1
    Host: example.com
    If-Modified-Since: Wed, 01 Sep 2004 13:24:52 GMT
    If-None-Match: “4135cda4″
    The header is self explanatory, it is asking for a new document which modified after Wed, 01 Sep 2004 13:24:52. The If-None-Match specifies that the client has mapped the document with that Entity value. RFC 2616 specifies that if If-None-Match is not accompanied with If-Modified-Since then the server must not send a 304 (Not Modified) header.(当客户请求头中只包含If-None-Match而不包含If-Modified-Since,那么服务端是不准返回304的。)
    The response to the above request would be as.
    HTTP/1.x 304 Not Modified
    Via: The-proxy-server
    Expires: Tue, 27 Dec 2005 11:25:19 GMT
    Date: Tue, 27 Dec 2005 05:25:19 GMT
    Server: Apache/1.3.33 (Unix) PHP/4.3.10
    Keep-Alive: timeout=2, max=99
    Etag: “4135cda4″
    Cache-Control: max-age=21600
    The server confirms the that the document is not modified and sends a 304 Not Modified header.
    The client checks the 304 response header, and renders the document from the cache.

    2.2 Conditional GET Request 理解
    Conditional GET Request 就是常说的缓存协商。既然是协商 肯定是二个主体,指服务器与浏览器之间的协商。
    对于静态元素,服务端根据它的最后一次修改时间(可以通过stat命令获取)判断
    对于动态页面,需要在程序中进行判断.

    协商首先要区别哪些是服务端返回指令。哪些是浏览器请求指令。象expire,max-age,Last-Modified,Etag都是服务端返回的指令。If-Match等IF开头的指令都是浏览器请求指令。会者不会用到前者的指令,但是会用到前者的指令值。
    比如If-None-Match的值就是etag指令的值, If-Modified-Since的值就是Last-Modified指令的值。这样协商就变成你当初告诉我的现在还成立吗?

    3.  F5 / Ctrl F5 /转到与Conditional GET Request(缓存协商)的关系


    3.1 为什么Ctrl+F5明显要让网页Refresh慢一些?
    在浏览器里中,按F5键或者点击Toobar上的Refresh/Reload图标(简称F5),和做F5同时按住Ctrl键(简称Ctrl+F5),效果是明显不一样的,通常Ctrl+F5明显要让网页Refresh慢一些,到底两者有什么区别呢?
     HTTP Headers 里有Expires、Last-Modified/If-Modified-Since和ETag/If-None-Match这些字段,F5/Ctrl+F5和这些有莫大关系。
    假如我第一次访问过http://www.test.com,这个网页是个动态网页,每次访问都会去访问Server,但是它包含一个一个静态资源http://www.test.com/logo.gif,浏览器在显示这个网页之前需要发HTTP请求获取这个logo.gif文件,返回的HTTP response包含这样的Headers:
    Expires: Thu 27 Nov 2008 07:00:00 GMT
    Last-Modified: Fri 30 Nov 2007 00:00:00 GMT
    那么浏览器就会cache住这个logo.gif文件,直到2008年11月27日7点整,或者直到用户有意清空cache。
    下次我再通过bookmark或者通过在URI输入栏直接敲字的方法访问http://www.test.com的时候,浏览器一看本地有个logo.gif,而且它还没过期呢,就不会发HTTP request给server,而是直接把本地cache中的logo.gif显示了。
    F5的作用和直接在URI输入栏中输入然后回车是不一样的,F5会让浏览器无论如何都发一个HTTP Request给Server,即使先前的Response中有Expires Header。所以,当我在当前http://www.test.com网页中按F5的时候,浏览器会发送一个HTTP Request给Server,但是包含这样的Headers:
    If-Modified-Since: Fri 30 Nov 2007 00:00:00 GMT
    实际上Server没有修改这个logo.gif文件,所以返回一个304 (Not Modified),这样的Response很小,所以round-trip耗时不多,网页很快就刷新了。
    上面的例子中没有考虑ETag,最好就不要用ETag,但是如果Response中包含ETag,F5引发的Http Request中也是会包含If-None-Match的。

    那么Ctrl+F5呢? Ctrl+F5要的是彻底的从Server拿一份新的资源过来,所以不光要发送HTTP request给Server,而且这个请求里面连If-Modified-Since/If-None-Match都没有,这样就逼着Server不能 返回304,而是把整个资源原原本本地返回一份,这样,Ctrl+F5引发的传输时间变长了,自然网页Refresh的也慢一些。
    实 际上,为了保证拿到的是从Server上最新的,Ctrl+F5不只是去掉了If-Modified-Since/If-None-Match, 还需要添加一些HTTP Headers。(Ctrl+F5与F5的区别,去掉Conditional GET Request的指令,增加了Cache-Control: max-age=0这样的指令 )按照HTTP/1.1协议,Cache不光只是存在Browser终端,从Browser到Server之间的中间节点(比如 Proxy)也可能扮演Cache的作用,为了防止获得的只是这些中间节点的Cache,需要告诉他们,别用自己的Cache敷衍我,往Upstream 的节点要一个最新的copy吧。

    ctrl+F5时不同浏览器的头指令:
    在IE6中,Ctrl+F5会添加一个Header
    Pragma: no-cache
    在Firefox 2.0中,Ctrl+F5会添加两个
    Pragma: no-cache
    Cache-Control: max-age=0
    注意max-age=0与no-cache的区别就是前者会一直要求client到backend上的各个节点的缓存内容过期( revalidate cache-entry), 而后者直接是client到backend的请求.禁止使用varnish等缓存内容.




    3.2 各种刷新的区别:
    3.2.1 Conditional GET Request的目的就是通过请求和[快速]响应(304响应的包很小)进行缓存协商。

    3.2.2 Ctrl+F5不会使用Conditional GET Request指令。因为不需要协商。但是会直接请求服务端的内容。
    F5,Refresh会使用使用Conditional GET Request指令, IF指令的值是服务端第一次响应返回的Last-Modified,Etag的值。就好比向另一个人确认最初告诉我的内容是否还有用。类F5操作不会用到第一次返回的Expires, max-age。因为它主要用来协商。
    3.2.3地址栏输入地址&& 转到 都不需要协商,如果没过期,不发请求。直接通过expires,max-age判断本地缓存内容是否过期。


    所以类F5与Ctrl+ F5的的一个明显区别就是带不带Condition Get的头,比如If-Modified-Since,if-None-Match. 转到与其它方式显著区别是首先判断本地是否过期,未过期直接使用本地缓存的内容,不会象F5不判断直接发送Condition Get请求。



  • 相关阅读:
    javascript模块化进阶
    javascript模块化基础
    css架构探索
    javascript函数基础概念 (补充完结)
    聊聊圣杯布局
    javascript函数基础概念
    yum提示This system is not registered with RHN.RHN support will be disabled.
    Linux分区和挂载硬盘
    Thunderbird扩展
    yum install nginx
  • 原文地址:https://www.cnblogs.com/highriver/p/2680634.html
Copyright © 2011-2022 走看看