2月 122009
 

网页的缓存是由HTTP消息头中的“Cache-control”来控制的,常见的取值有private、no-cache、max-age、must-revalidate等,默认为private。其作用根据不同的重新浏览方式分为以下几种情况:
(1) 打开新窗口
如果指定cache-control的值为private、no-cache、must-revalidate,那么打开新窗口访问时都会重新访问服务器。而如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器,例如:
Cache-control: max-age=5
表示当访问此网页后的5秒内再次访问不会去服务器
(2) 在地址栏回车
如果值为private或must-revalidate(和网上说的不一样),则只有第一次访问时会访问服务器,以后就不再访问。如果值为no-cache,那么每次都会访问。如果值为max-age,则在过期之前不会重复访问。
(3) 按后退按扭
如果值为private、must-revalidate、max-age,则不会重访问,而如果为no-cache,则每次都重复访问
(4) 按刷新按扭
无论为何值,都会重复访问

当指定Cache-control值为“no-cache”时,访问此页面不会在Internet临时文章夹留下页面备份。
另外,通过指定“Expires”值也会影响到缓存。例如,指定Expires值为一个早已过去的时间,那么访问此网时若重复在地址栏按回车,那么每次都会重复访问:
Expires: Fri, 31 Dec 1999 16:00:00 GMT

在ASP中,可以通过Response对象的Expires、ExpiresAbsolute属性控制Expires值;通过Response对象的CacheControl属性控制Cache-control的值,例如:
Response.ExpiresAbsolute = #2000-1-1# ‘ 指定绝对的过期时间,这个时间用的是服务器当地时间,会被自动转换为GMT时间
Response.Expires = 20 ‘ 指定相对的过期时间,以分钟为单位,表示从当前时间起过多少分钟过期。
Response.CacheControl = "no-cache"

详细确切的定义建议参考rfc :http://www.w3.org/Protocols/rfc2616/rfc2616.html

 Posted by at 下午 9:15
1月 072009
 

下面是一个常见的获取用户ip的函数:

<?php
function getip
()
{
    if(
getenv("HTTP_CLIENT_IP") && getenv("HTTP_CLIENT_IP")!="unknown"
)
        
$ip getenv("HTTP_CLIENT_IP"
);
    elseif(
getenv("HTTP_X_FORWARDED_FOR") && getenv("HTTP_X_FORWARDED_FOR")!="unknown"
)
        
$ip getenv("HTTP_X_FORWARDED_FOR"
);
    elseif(
getenv("REMOTE_ADDR") && getenv("REMOTE_ADDR")!="unknown"
)
        
$ip getenv("REMOTE_ADDR"
);
    else    
        
$ip "none"

    return $ip;
}
?>

下面给出一个测试脚本:

<?php
$ch 
curl_init();
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1);
curl_setopt($ch,CURLOPT_HTTPHEADER,array(‘X_FORWARDED_FOR: 158.10.10.10’));
curl_setopt($ch,CURLOPT_HTTPHEADER,array(‘CLIENT_IP: 159.10.10.10’));
curl_setopt($chCURLOPT_URL,"http://10.10.10.21/test.php");
echo 
curl_exec($ch);
curl_close($ch);
exit;
?>

 Posted by at 上午 3:53
1月 062009
 

References

http1.0: RFC 1945.

http1.1: RFC 2068

 

Status Code

The Warning header

HTTP status codes indicate the success or failure of a request. For a successful response, the status code cannot provide additional advisory information, in part because the placement of the status code in the Status-Line, instead of in a header field, prevents the use of multiple status codes.

HTTP/1.1 introduces a Warning header, which may carry any number of subsidiary status indications. The intent is to allow a sender to advise the recipient that something may be unsatisfactory about an ostensibly successful response.

HTTP/1.1 defines an initial set of Warning codes, mostly related to the actions of caches along the response path. For example, a Warning can mark a response as having been returned by a cache during disconnected operation, when it is not possible to validate the cache entry with the origin server.

The Warning codes are divided into two classes, based on the first digit of the 3-digit code. One class of warnings must be deleted after a successful revalidation of a cache entry; the other class must be retained with a revalidated cache entry. Because this distinction is made based on the first digit of the code, rather than through an exhaustive listing of the codes, it is extensible to Warning codes defined in the future.

Other new status codes

There are 24 new status codes in HTTP/1.1; we have discussed 100 (Continue), 206 (Partial Content), and 300 (Multiple Choices) elsewhere in this paper. A few of the more notable additions include

* 409 (Conflict), returned when a request would conflict with the current state of the resource. For example, a PUT request might violate a versioning policy.

* 410 (Gone), used when a resource has been removed permanently from a server, and to aid in the deletion of any links to the resource.

Most of the other new status codes are minor extensions.

HTTP1.0

HTTP1.1

HTTP/1.0 does not define any 1xx status

codes and they are not a valid response to a HTTP/1.0 request.

100 Continue

101 Switching Protocols

Undifined

203 Non-Authoritative Information

Undifined

205 Reset Content

Undifined

206 Partial Content

Undifined

303 See Other

Undifined

305 Use Proxy

Undifined

402 Payment Required

Undifined

405 Method Not Allowed

Undifined

406 Not Acceptable

Undifined

407 Proxy Authentication Required

Undifined

408 Request Timeout

Undifined

409 Conflict

Undifined

410 Gone

Undifined

411 Length Required

Undifined

412 Precondition Failed

Undifined

413 Request Entity Too Large

Undifined

414 Request-URI Too Long

Undifined

415 Unsupported Media Type

Undifined

504 Gateway Timeout

Undifined

505 HTTP Version Not Supported

HTTP/1.0 -> HTTP/1.1

Changes to Simplify Multi-homed Web Servers and Conserve IP

Addresses

The requirements that clients and servers support the Host request-

header, report an error if the Host request-header (section 14.23) is

missing from an HTTP/1.1 request, and accept absolute URIs (section

5.1.2) are among the most important changes defined by this

specification.

Older HTTP/1.0 clients assumed a one-to-one relationship of IP

addresses and servers; there was no other established mechanism for

distinguishing the intended server of a request than the IP address

to which that request was directed. The changes outlined above will

allow the Internet, once older HTTP clients are no longer common, to

support multiple Web sites from a single IP address, greatly

simplifying large operational Web servers, where allocation of many

IP addresses to a single host has created serious problems. The

Internet will also be able to recover the IP addresses that have been

allocated for the sole purpose of allowing special-purpose domain

names to be used in root-level HTTP URLs. Given the rate of growth of

the Web, and the number of servers already deployed, it is extremely

important that all implementations of HTTP (including updates to

existing HTTP/1.0 applications) correctly implement these

requirements:

o Both clients and servers MUST support the Host request-header.

o Host request-headers are required in HTTP/1.1 requests.

o Servers MUST report a 400 (Bad Request) error if an HTTP/1.1

request does not include a Host request-header.

o Servers MUST accept absolute URIs.

Persistent

HTTP/1.0

experimental implementations of persistent connections are faulty,

and the new facilities in HTTP/1.1 are designed to rectify these

problems. The problem was that some existing 1.0 clients may be

sending Keep-Alive to a proxy server that doesn’t understand

Connection, which would then erroneously forward it to the next

inbound server, which would establish the Keep-Alive connection and

result in a hung HTTP/1.0 proxy waiting for the close on the

response. The result is that HTTP/1.0 clients must be prevented from

using Keep-Alive when talking to proxies.

original HTTP/1.0 form of persistent

connections.

When it connects to an origin server, an HTTP client MAY send the

Keep-Alive connection-token in addition to the Persist connection-

token:

Connection: Keep-Alive

An HTTP/1.0 server would then respond with the Keep-Alive connection

token and the client may proceed with an HTTP/1.0 (or Keep-Alive)

persistent connection.

An HTTP/1.1 server may also establish persistent connections with

HTTP/1.0 clients upon receipt of a Keep-Alive connection token.

However, a persistent connection with an HTTP/1.0 client cannot make

use of the chunked transfer-coding, and therefore MUST use a

Content-Length for marking the ending boundary of each message.

A client MUST NOT send the Keep-Alive connection token to a proxy

server as HTTP/1.0 proxy servers do not obey the rules of HTTP/1.1

for parsing the Connection header field.

In HTTP/1.0, most implementations used a new connection for each

request/response exchange. In HTTP/1.1, a connection may be used for

one or more request/response exchanges, although connections may be

closed for a variety of reasons .

Content Negotiation

  Web users speak many languages and use many character sets. Some Web resources are available in several variants to satisfy this multiplicity. HTTP/1.0 included the notion of content negotiation, a mechanism by which a client can inform the server which language(s) and/or character set(s) are acceptable to the user.

Content negotiation has proved to be a contentious and confusing area. Some aspects that appeared simple at first turned out to be quite difficult to resolve. For example, although current IETF practice is to insist on explicit character set labeling in all relevant contexts, the existing HTTP practice has been to use a default character set in most contexts, but not all implementations chose the same default. The use of unlabeled defaults greatly complicates the problem of internationalizing the Web.

HTTP/1.0 provided a few features to support content negotiation, but RFC1945 never uses that term and devotes less than a page to the relevant protocol features. The HTTP/1.1 specification specifies these features with far greater care, and introduces a number of new concepts.

The goal of the content negotiation mechanism is to choose the best available representation of a resource. HTTP/1.1 provides two orthogonal forms of content negotiation, differing in where the choice is made:

1.

In server-driven negotiation, the more mature form, the client sends hints about the user’s preferences to the server, using headers such as Accept-Language, Accept-Charset, etc. The server then chooses the representation that best matches the preferences expressed in these headers.

2.

In agent-driven negotiation, when the client requests a varying resource, the server replies with a 300 (Multiple Choices) response that contains a list of the available representations and a description of each representation’s properties (such as its language and character set). The client (agent) then chooses one representation, either automatically or with user intervention, and resubmits the request, specifying the chosen variant.

Although the HTTP/1.1 specification reserves the Alternates header name for use in agent-driven negotiation, the HTTP working group never completed a specification of this header, and server-driven negotiation remains the only usable form.

Some users may speak multiple languages, but with varying degrees of fluency. Similarly, a Web resource might be available in its original language, and in several translations of varying faithfulness. HTTP introduces the use of quality values to express the importance or degree of acceptability of various negotiable parameters. A quality value (or qvalue) is a fixed-point number between 0.0 and 1.0. For example, a native speaker of English with some fluency in French, and who can impose on a Danish-speaking office-mate, might configure a browser to generate requests including

Accept-Language: en, fr;q=0.5, da;q=0.1

Because the content-negotiation mechanism allows qvalues and wildcards, and expresses variation across many dimensions (language, character-set, content-type, and content-encoding) the automated choice of the best available” variant can be complex and might generate unexpected outcomes. These choices can interact with caching in subtle ways.

Content negotiation promises to be a fertile area for additional protocol evolution. For example, the HTTP working group recognized the utility of automatic negotiation regarding client implementation features, such as screen size, resolution, and color depth. The IETF has created the Content Negotiation working group to carry forward with work in the area.

Other

A server MUST NOT send

transfer-codings to an HTTP/1.0 client.

 Posted by at 下午 7:38
1月 062009
 

19 附录
19.1 互联网媒体类型message/http和application/http
这篇文档除了定义HTTP/1.1协议外,还用作互联网媒介类型"message/http"和"application/http"的规范。此类型用于封装一个HTTP请求消息或响应消息,这假设此类型遵循MIME对 所有“消息”类型关于行长度和编的限制。application/http类型可以用来封装一个或者更多HTTP请求或响应信息(非混合的)的传输路径(pipeline)。下列是在IANA[17]注册的。

        媒介类型名称:    message

        媒介次类型名称: http

        必须参数:        无

        可选参数:        版本,信息类型

        版本:封装信息的HTTP版本号(例如,"1.1")。如果不存在,版本可以从消息的第一行确定。

        信息类型:信息类型–"请求"或者"响应"。如果不存在,类型可以从报文的第一行确定。  

        编码考虑:只有"7bit","8bit",或者"二进制"是允许的。

        安全考虑:无

        媒介类型名称:    application

        媒介次类型名称: http

        必须参数:        无

        可选参数:        版本,信息类型

        版本:封装信息的HTTP版本号(例如,"1.1")。如果不存在,版本可以从报文的第一行确定。

        信息类型:信息类型–"request"或者"response"。如果不存在,类型可以从报文的第一行确定。      

        编码考虑:用这种类型封装的HTTP信息是"二进制"的格式;当通过E-mail传递的时候一种合适的内容传输编码是必须的。

        安全考虑:无          

19.2 互联网媒体类型multipart/byteranges
当一个HTTP206(部分内容)响应信息包含多个范围的内容(请求响应的内容有多个非重叠的范围),这些是作为一个多部分消息主体来被传送的。这种用途的媒体类型被称作"multipart/byteranges"。

multipart/byteranges媒体类型包括两个或者更多的部分,每一个都有自己Content-type和Content-Range头域。必需的分界参数(boundary parameter)指定分界字符串,此分界字符串用来隔离每一部分。

        媒介类型名称:    multipart

        媒介次类型名称: byteranges

        必须参数:        boundary

        可选参数:        无

        编码考虑:只有"7bit","8bit",或者"二进制"是允许的。

        安全考虑:无          

例如:

HTTP/1.1 206 Partial Content

   Date: Wed, 15 Nov 1995 06:25:24 GMT

   Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT

   Content-type:multipart/byteranges;boundary=THIS_STRING_SEPARATES

   –THIS_STRING_SEPARATES

   Content-type: application/pdf

   Content-range: bytes 500-999/8000

   …第一部分…

   –THIS_STRING_SEPARATES

   Content-type: application/pdf

   Content-range: bytes 7000-7999/8000

   …第二部分

   –THIS_STRING_SEPARATES–

注意:

在实体(entity)中,在第一个分界字符串之前可以有多余的CRLFs。

虽然RFC 2046 [40]允许分界字符串加引号,但是一些现有的实现会不正确的处理分界字符串

许多浏览器和服务器是按照字节范围标准的早期草案关于使用multipart/x-byteranges媒体类型来进行编码的的,这个草案不总是完全和HTTP/1.1中描述的版本兼容。

19.3 宽松的应用程序 (Tolerent Applications)
虽然这篇文档列出了HTTP/1.1消息所必须的元素,但是并不是所有的程序在实现的时候都是正确的。因此我们建议当偏差可以明确解释的时候,运算程序对这种偏差应该是宽容的。

客户端应该宽松的解析Status-Line(状态行);服务器也应该宽松的解析Request-Line(请求行)。特别的,他们应该可以接受头域之间任何数量的SP或HT字符,即使协议规定只有一个SP。

消息头域的行终结符是CRLF。然而,当解析这样的头域时,我们建议应用程序能识别单一LF作为行终结符并能忽略CR。

实体主体(entity-body)的字符集应该被标记为应用于实体主体字符编码的最小公分母,并且期望不对实体进行标记要优于对实体标记为US-ASCII或ISO-8859-1。见3.7.1和3.4.1。

对关于日期分析和编码的要求的额外规则以及其它对日期编码的潜在问题包含:

Ø         HTTP/1.1客户端和缓存应该假定一个似乎是50多年以后的RFC-850日期实际上是过去的(这有助于解决"2000年"问题)。

Ø         一个HTTP/1.1的实现可以内部地表示一个比正确日期值更早的已解析后的Expires日期,但是一定不要(MUST NOT)内部地表示一个比正确日期值更迟的已解析过的Expires日期。

Ø         所有过期日期相关的计算必须用GMT时间。本地时区一定不能(MUST NOT)影响年龄或过期时间的计算。

Ø         如果一个HTTP头域不正确的携带了一个非GMT时间区的日期值,那么必须利用最保守的可能转换把此日期值转换成GMT时间值。

19.4 HTTP实体和RFC 2045实体之间的区别
HTTP/1.1使用了许多Internet Mail(RFC 822 [9])和Multipurpose Internet Mail Extensions(MIME [7])里定义的结构,去允许实体以多种表现形式和扩展机制去传输。然而,RFC2045讨论邮件,并且HTTP有许多不同于RFC2045里描述的特征。这些不同被小心地挑选出来优化二进制连接的性能,为了允许使用新的媒体类型有更大的灵活性,为了使时间比较变得容易,和为了承认一些早期HTTP服务器和客户端的实效。

本附录描述了HTTP协议不同于RFC 2045的特殊区域。在严格的MIME环境中的代理和网关应该意识到这些不同并且在必要的时候要提供合适地转换。从MIME环境到HTTP的代理服务器和网关也需要意识到这些不同因为一些转换可能是需要的。

19.4.1 MIME版本(MIME-Version)
HTTP不是一个遵守MIME的协议。然而HTTP/1.1消息可以(MAY)包含一个单独的MIME-Version常用头域用来指出什么样的MIME协议版本被用于去构造消息。利用MIME-Version头域指明完全遵循MIME协议的消息(在RFC2045[7])。代理/网关要保证完全遵守MIME协议当把HTTP消息输出到严格MIME环境的时候。

    MIME-Version   = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT

在HTTP/1.1用的缺省值是MIME1.0版本。然而,HTTP/1.1消息的解析和语义是由本文档而不是MIME规范定义的。

19.4.2转换到规范化形式 (Conversion to Canoical Form)
RFC 2045 [7]需要一个Internet mail实体在被传输之前要被转换成一个规范化的形式,这在RFC2049[48]里第四章里描述的。这篇文档的3.7.1节描述了当用HTTP协议传输时允许使用的”text”子媒体类型的形式。RFC2046要求以类型为“text”的内容要用CRLF表示为换行符,以及在换行符外禁止使用CR或LF。

RFC 2046需要像在"text"类型的内容里一样,用CRLF表示行间隔符并禁止在行间隔符序列以外使用CR或者LF。HTTP允许CRLF,单个CR,和单个LF来表示一个换行符在一个文本内容消息中。

在可能的地方,从HTTP到严格MIME环境的代理或网关应该(SHOULD)把RFC2049里描述的text媒体类型里所有换行符转换成RFC2049里CRLF的规范形式。然而,注意这可能在Content-Encoding出现的时候,以及HTTP允许利用一些没有利用13和10代表CR和LF的字符集时候都会变得复杂。

实现者应该注意转换将会破坏任何应用于源内容(original content)的密码校验和,除非源内容已经是规范化形式。因此,对任何在HTTP中使用校验和的内容被建议要表示为规范化形式。

19.4.3日期格式的转换 (Conversion of Date Formate)
为了简化日期比较的过程,HTTP/1.1使用了一个限制的日期格式(3.3.1节)。其它协议的代理和网关应该保证任何消息里出现的Date头域应该遵循HTTP/1.1规定的格式,如果有必要需要重写此日期。

19.4.4 Content-Encoding头域介绍 (Introduction of Content-Encoding)
RFC 2045不包含任何等价于HTTP/1.1里Content-Encoding头域的概念。因为这个头域作为媒体类型(media type)的修饰,从HTTP协议到MIME遵守的协议的代理和网关在转发消息之前必须既能改变Content-Type头域的值,也能解码实体主体(entity-body).。(一些为Internet mail类型的Content-Type的实验性的应用已经使用了一个媒体类型参数“; conversions=<content-coding>”去执行等价于Content-Encoding的功能。然而,此参数并不是RFC2045的部分)

19.4.5没有Content-Transfer-Encoding头域
HTTP不使用RFC 2045里的Content-Transfer-Encoding(CTE)头域。从使用MIME协议到HTTP的代理和网关在把响应消息发送给HTTP客户端之前必须删除任何非等价(non-identity,译注:identity编码,表示没有进行任何编码)CTE("quoted-printable"或"base64")编码。

从HTTP到MIME协议遵循的代理和网关要确保消息在那个协议安全传输上是用正确的格式和正确的编码,“安全传输”是通过使用的协议的限制而被定义的。这样一个代理或网关应该用合适的Content-Transfer-Encoding头域来标记数据如果这样做将提高安全传输的可能性。

19.4.6 Transfer-Encoding头域的介绍
HTTP/1.1介绍了Transfer-Encoding头域(14.41节)。代理/网关在转发经由MIME协议的消息之前必须移除任何传输编码。

一个解码"chunked"传输代码(3.6节)的程序可以用代码表示如下:

       length := 0

       read chunk-size, chunk-extension (if any) and CRLF

       while (chunk-size > 0) {

          read chunk-data and CRLF

          append chunk-data to entity-body

          length := length + chunk-size

          read chunk-size and CRLF

       }

       read entity-header

       while (entity-header not empty) {

          append entity-header to existing header fields

          read entity-header

       }

       Content-Length := length

       Remove "chunked" from Transfer-Encoding

19.4.7 MHTML和行长度限制
和MHTML实现共享代码的HTTP实现需要了解MIME行长度限制。因为HTTP没有这个限制,HTTP并不折叠长行。用HTTP传输的MHTML消息遵守所有MHTML的规定,包括行长度的限制和折叠,规范化等,因为HTTP传输所有消息主体(见3.7.2)并且不解析消息的内容和消息中包含任何MIME头域。

19.5 其它特征
RFC 1945和RFC 2068里一些协议元素被一些已经存在的HTTP实现使用,但是这些协议元素对于大多数HTTP/1.1应用程序既不兼容也不正确。实现者被建议去了解这些特征,但是不能依赖于它们的出现或不依赖于与其它HTTP/1.1应用程序的互操作性。这些特征中的一些特征描述了实验性的特征,以及还有一些特征描述了没有在基本HTTP/1.1规范里被描述的实验性部署特征。

一些其它头域,如Content-Dispositon和Title头域,他们来自于SMTP和MIME协议,他们同样经常被实现(见2076[37]).

19.5.1 Content-Disposition
Content-Disposition响应头域被建议作为一个这样的用途,那就是如果用户请求要使内容被保存为一个文件,那么此头域被源服务器使用去建议的一个缺省的文件名。此用途来自于RFC1806[35]关于对Content-Disposition的定义。

        content-disposition = "Content-Disposition" ":"

                              disposition-type *( ";" disposition-parm )

        disposition-type = "attachment" | disp-extension-token

        disposition-parm = filename-parm | disp-extension-parm

        filename-parm = "filename" "=" quoted-string

        disp-extension-token = token

        disp-extension-parm = token "=" ( token | quoted-string )

一个例子是:

      Content-Disposition: attachment; filename="fname.ext"

接收用户的代理不应该(SHOULD NOT)关注任何在filename-parm参数中出现的文件路径信息,这个参数被认为在这次仅仅是应用于HTTP实现。文件名应该(SHOULD)只被当作一个终端组件。

如果此头域用于一个Content-Type为application/octet-stream响应里,那么含义就是用户代理不应该展现响应,但是它应该直接进入一个‘保存响应为…’对话框。

见15.5节关于Content-Disposition的的安全问题。

19.6 和以前版本的兼容
要求和以前的版本的兼容超出了协议规范的范围。然而HTTP/1.1有意设计成很容易支持以前的版本。必须值得注意的是,在写这份规范的时候,我们希望商业的HTTP/1.1服务器去:

      –接受HTTP/0.9,1.0和1.1请求的请求行(Request-Line)格式;

      –理解HTTP/0.9,1.0或1.1格式中的任何有效请求;

      –恰当地用客户端使用的主要版本来响应。

并且我们希望HTTP/1.1的客户端:

      –接受HTTP/1.0和1.1响应的状态行(Status-Line)格式;

      –懂得HTTP/0.9,1.0或1.1的格式的任何有效的响应。

对大多数HTTP/1.0的实现,每一个连接要在请求之前被客户端建立,并且在发送响应之后要被服务器关闭。一些实现了在RFC 2068 [33]的19.7.1节描述的持久连接的Keep-Alive版本。

19.6.1对HTTP/1.0的改变
这一部分总结HTTP/1.0和HTTP/1.1之间主要的区别。

19.6.1.1 对多主机web服务器和保留IP地址简化的改变
客户端和服务器必须支持Host请求头域,并且如果Host请求头域在HTTP/1.1请求里缺少,那么服务器应该报告一个错误,并且服务器能接受一个绝对URIs(5.1.2节),对于这个要求是在此规范里最重要的改变。上面的改变将允许互联网,一旦旧的客户端不再常用时,去支持一个IP地址的多个web站点,这大大简化了大型运算的web服务器,在那里分配多个IP地址给一个主机(host)会产生很严重的问题。此互联网照样能恢复这样一个IP地址,此IP地址作为特殊目的被分配给被用于根级HTTPURLs的域名。给定web的增长速度,服务器的部署数量部,那么所有HTTP实现(包括对已存HTTP/1.0应用程序)应该正确地满足下面这些需求:

    –客户端和服务器都必须(MUST)支持Host请求头域。

    –发送HTTP/1.1请求的客户端必须(MUST)发送Host头域。

    –如果HTTP/1.1请求不包括Host请求头域,服务器就必须(MUST)报告错误400(Bad Request)。

    –服务器必须(MUST)接受绝对URIs(absolute URIs)。

19.6.2和HTTP/1.0持续连接的兼容
一些客户端和服务器可能希望和一些对以前持续连接实现的HTTP/1.0客户端和服务器兼容。HTTP/1.0持久连接需要显示地协商,因为它们不是缺省的行为。持久连接的HTTP/1.0实验性的实现有错误,并且HTTP/1.1里的新的功能被设计成去矫正这些问题。此问题是一些已经存在的1.0客户端可能会发送Keep-Alive头域给不理解连接的代理服务器,然后代理服务器会把此Keep-Alive转发给下一个入流(inbound)服务器。所以HTTP/1.0客户端必须禁止利用Keep-Alive当和代理会话的时候。

然而,和代理进行会话最重要是利用持久连接,所以那个禁止很显然不能被接受。因此,我们需要一些其它的机制去指明需要一个持久连接,并且它必须能安全的使用甚至当和忽略连接的老代理。持久连接缺省是为HTTP/1.1消息的;为了声明非持久连接(见14.10节),我们介绍一个新的关键字(Connection:close)。

持久连接的源HTTP/1.0的形式(the Connection: Keep-Alive and Keep-Alive 头域)在RFC2068里说明

19.6.3对RFC 2068的改变
这篇规范已经被仔细的审查来纠正关键字的用法和消除它们的歧义;RFC 2068在遵守RFC 2119 [34] 制定的协定方面有很多问题。

澄清哪个错误代码将会使入流服务器失灵(例如DNS失灵)。(10.5.5节)

Create有一个特点当一个资源第一次被创建的时候必须需要一个Etag。(10.2.2节)

Content-Base头域从此规范里删除了:它无法广泛的实现,并且在没有健壮的扩展机制的情况下,没有简单的,安全的方式去介绍它。并且,它以一种相似的而不是相同的方式在MHTML[45]里被使用。

 Posted by at 下午 7:37
9月 242008
 
HTTP Keep Alive

Http Keep-Alive seems to be massively misunderstood. Here’s a short description of how it works, under both 1.0 and 1.1, with some added information about how Java handles it.

Http operates on what is called a request-response paradigm. This means that a _client_ generates a request for information, and passes it to the server, which answers it. In the original implementation of HTTP, each request created a new socket connection to the server, sent the request, then read from that connection to get the response.

This approach had one big advantage – it was simple. Simple to describe, simple to understand, and simple to code. It also had one big disadvantage – it was slow. So, keep-alive connections were invented for HTTP.
HTTP/1.0

Under HTTP 1.0, there is no official specification for how keepalive operates. It was, in essence, tacked on to an existing protocol. If the browser supports keep-alive, it adds an additional header to the request:

Connection: Keep-Alive

Then, when the server receives this request and generates a response, it also adds a header to the response:

Connection: Keep-Alive

Following this, the connection is NOT dropped, but is instead kept open. When the client sends another request, it uses the same connection. This will continue until either the client or the server decides that the conversation is over, and one of them drops the connection.
HTTP/1.1

Under HTTP 1.1, the official keepalive method is different. All connections are kept alive, unless stated otherwise with the following header:

Connection: close

The Connection: Keep-Alive header no longer has any meaning because of this.

Additionally, an optional Keep-Alive: header is described, but is so underspecified as to be meaningless. Avoid it.
Not reliable

HTTP is a stateless protocol – this means that every request is independent of every other. Keep alive doesn抰 change that. Additionally, there is no guarantee that the client or the server will keep the connection open. Even in 1.1, all that is promised is that you will probably get a notice that the connection is being closed. So keepalive is something you should not write your application to rely upon.
KeepAlive and POST

The HTTP 1.1 spec states that following the body of a POST, there are to be no additional characters. It also states that "certain" browsers may not follow this spec, putting a CRLF after the body of the POST. Mmm-hmm. As near as I can tell, most browsers follow a POSTed body with a CRLF. There are two ways of dealing with this: Disallow keepalive in the context of a POST request, or ignore CRLF on a line by itself. Most servers deal with this in the latter way, but there’s no way to know how a server will handle it without testing.
Java abstraction – client side

On the client side, Java abstracts the notion of a keepalive request away from the programmer. The HttpURLConnection class implements keepalive automatically, without intervention being either required or possible on the part of the programmer. It does this through an internal cache of client connections, which is maintained as one of the implementation details of the class. Incidentally, this means that keepalive is an implementation detail of the Javasoft class library, which may or may not be available in other class libraries.
Java abstraction – server side

On the server side, Java again abstracts out the notion of a keepalive request. The HttpServlet, HttpServletRequest, and HtppServletResponse classes implement keepalive automatically. In this case, however, some intervention is possible. As mentioned in the KeepAliveServlet that comes with the JavaWebServer, the actual keepalive behavior that occurs depends on two factors: setting content length, and size of output. If content length is set as part of the response, keepalive will be used if the client supports it. If content length is not set, the servlet implementation will attempt to buffer the response to determine it’s content length. If the buffering is successful, keepalive will be used. In the Javasoft implementation, a 4k buffer is used. This means that if the content length is not set, and the amount of data returned is over 4k, keepalive will not be used. As with HttpURLConnection, this is an implementation detail of the Javasoft class library, which may or may not be available in other class libraries.

SO_KEEPALIVE包由TCP处理,而Keep-Alive由HTTP处理,keep-alive是需要客户端支持,so_KEEPALIVE是利用了tcp的双向全双工连接特性,在web-server端可以不断开连接,来接受客户端更多的请求,应该是能够改善连接时间,不过似乎在连接非常多的情况下会大大加重服务器负担,需要tcp/ip协议盏支持,并且不同客户端之间有不同的设定
在观测时发现以下现象:当keepalive off时的值与keepalive on时的值比较得以下结果:

ps -ef|grep httpd|wc -l的值小。
netstat -an | grep :80 |wc -l的值大。
 

摘自:http://hi.baidu.com/toughguy/blog/item/626410fb51abfa176d22eb38.html

 Posted by at 上午 3:59
7月 262008
 

通过浏览器内置的认证窗口进行认证并不神奇,其实只要服务器端发送一个状态为401的响应头,浏览器就会弹出认证窗口,带用户输入用户名,密码点击确定后,将用户名密码以 base64_encode(username:password) 的方式放在http header里再次请求,发送给服务器;下面是第一次请求的响应头:
HTTP/1.1 401 Unauthorized
Transfer-Encoding: chunked
Status: 401
X-Powered-By: PHP/5.2.0
WWW-Authenticate: Basic realm="My Realm"
Content-type: text/html
Date: Sat, 26 Jul 2008 16:49:27 GMT
Server: LightTPD/1.4.19 (Win32)

下面是第二次的请求头:
GET /http_auth.php HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, */*
Accept-Language: zh-cn
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; WPS)
Host: ljj.cn
Connection: Keep-Alive
Authorization: Basic bW1tOm5ubg==

关键就在红字部分,其中 bW1tOm5ubg== 就是我的用户名和密码,有兴趣的话可以用base64_decode() 解开看看,就像处理进程cookie那样,浏览器会记住用户名密码,每次请求该页都带上该header,知道浏览器关闭。

 Posted by at 上午 10:56
6月 262008
 

1) 什么是”Last-Modified”?
  在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样:
  Last-Modified: Fri, 12 May 2006 18:53:33 GMT
  客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过:
  If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
  如果服务器端的资源没有变化,则自动返回 HTTP 304 (Not Changed.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
  2) 什么是”Etag”?
  HTTP 协议规格说明定义ETag为“被请求变量的实体值” (参见 —— 章节 14.19)。 另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式:
  ETag: "50b1c1d4f775c61:df3"
  客户端的查询更新格式是这样的:
  If-None-Match: W/"50b1c1d4f775c61:df3"
  如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。本人测试Etag主要在断点下载时比较有用。
  Last-Modified和Etags如何帮助提高性能?
  聪明的开发者会把Last-Modified 和ETags请求的http报头一起使用,这样可利用客户端(例如浏览器)的缓存。因为服务器首先产生 Last-Modified/Etag标记,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其(客户端)缓存。
  过程如下:

        

  1. 客户端请求一个页面(A)。
  2.     

  3. 服务器返回页面A,并在给A加上一个Last-Modified/ETag。
  4.     

  5. 客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。
  6.     

  7. 客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。
  8.     

  9. 服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。

相关资料:

使用ETags减少Web应用带宽和负载
http://www.infoq.com/cn/articles/etags

如何利用客户端缓存对网站进行优化?
http://blog.csdn.net/houjianxun/archive/2007/09/25/1799328.aspx
有.NET示例代码

Python:Http Web服务->处理 Last-Modified 和 ETag
http://www.woodpecker.org.cn/diveintopython/http_web_services/index.html

在基于Spring及Hibernate应用程序中使用ETags降低带宽占用和服务器压力
http://www.blogjava.net/AllanZ/archive/2007/07/13/130111.html

Header Field Definitions
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

 Posted by at 上午 7:51
6月 262008
 

HTTP 知识点之一:头部解释

============================================================================================================================
1. Accept:告诉WEB服务器自己接受什么介质类型,*/* 表示任何类型,type/* 表示该类型下的所有子类型,type/sub-type。

2. Accept-Charset:   浏览器申明自己接收的字符集
   Accept-Encoding:  浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate)
   Accept-Language::浏览器申明自己接收的语言
                      语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等。

3. Accept-Ranges:WEB服务器表明自己是否接受获取其某个实体的一部分(比如文件的一部分)的请求。
                  bytes:表示接受,none:表示不接受。

4. Age:当代理服务器用自己缓存的实体去响应请求时,用该头部表明该实体从产生到现在经过多长时间了。

5. Authorization:当客户端接收到来自WEB服务器的 WWW-Authenticate 响应时,用该头部来回应自己的身份验证信息给WEB服务器。

6. Cache-Control:请求:no-cache(不要缓存的实体,要求现在从WEB服务器去取)
                       max-age:(只接受 Age 值小于 max-age 值,并且没有过期的对象)
                       max-stale:(可以接受过去的对象,但是过期时间必须小于 max-stale 值)
                       min-fresh:(接受其新鲜生命期大于其当前 Age 跟 min-fresh 值之和的缓存对象)
                  响应:public(可以用 Cached 内容回应任何用户)
                        private(只能用缓存内容回应先前请求该内容的那个用户)
                        no-cache(可以缓存,但是只有在跟WEB服务器验证了其有效后,才能返回给客户端)
                        max-age:(本响应包含的对象的过期时间)
                  ALL:  no-store(不允许缓存)

7. Connection:请求:close(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,断开连接,不要等待本次连接的后续请求了)。
                     keepalive(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,保持连接,等待本次连接的后续请求)。
               响应:close(连接已经关闭)。
                     keepalive(连接保持着,在等待本次连接的后续请求)。
   Keep-Alive:如果浏览器请求保持连接,则该头部表明希望 WEB 服务器保持连接多长时间(秒)。
               例如:Keep-Alive:300

8. Content-Encoding:WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。
                     例如:Content-Encoding:gzip                  
   Content-Language:WEB 服务器告诉浏览器自己响应的对象的语言。

   Content-Length:  WEB 服务器告诉浏览器自己响应的对象的长度。
                     例如:Content-Length: 26012
   Content-Range:   WEB 服务器表明该响应包含的部分对象为整个对象的哪个部分。
                     例如:Content-Range: bytes 21010-47021/47022
   Content-Type:    WEB 服务器告诉浏览器自己响应的对象的类型。
                     例如:Content-Type:application/xml

9. ETag:就是一个对象(比如URL)的标志值,就一个对象而言,比如一个 html 文件,如果被修改了,其 Etag 也会别修改,
         所以,ETag 的作用跟 Last-Modified 的作用差不多,主要供 WEB 服务器判断一个对象是否改变了。
         比如前一次请求某个 html 文件时,获得了其 ETag,当这次又请求这个文件时,浏览器就会把先前获得的 ETag 值发送给
         WEB 服务器,然后 WEB 服务器会把这个 ETag 跟该文件的当前 ETag 进行对比,然后就知道这个文件有没有改变了。
        

10. Expired:WEB服务器表明该实体将在什么时候过期,对于过期了的对象,只有在跟WEB服务器验证了其有效性后,才能用来响应客户请求。
             是 HTTP/1.0 的头部。
             例如:Expires:Sat, 23 May 2009 10:02:12 GMT

11. Host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号。
          例如:Host:rss.sina.com.cn

12. If-Match:如果对象的 ETag 没有改变,其实也就意味著对象没有改变,才执行请求的动作。
    If-None-Match:如果对象的 ETag 改变了,其实也就意味著对象也改变了,才执行请求的动作。

13. If-Modified-Since:如果请求的对象在该头部指定的时间之后修改了,才执行请求的动作(比如返回对象),否则返回代码304,告诉浏览器该对象没有修改。
                       例如:If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMT
    If-Unmodified-Since:如果请求的对象在该头部指定的时间之后没修改过,才执行请求的动作(比如返回对象)。

14. If-Range:浏览器告诉 WEB 服务器,如果我请求的对象没有改变,就把我缺少的部分给我,如果对象改变了,就把整个对象给我。
              浏览器通过发送请求对象的 ETag 或者 自己所知道的最后修改时间给 WEB 服务器,让其判断对象是否改变了。
              总是跟 Range 头部一起使用。

15. Last-Modified:WEB 服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间等等。
                   例如:Last-Modified:Tue, 06 May 2008 02:42:43 GMT

16. Location:WEB 服务器告诉浏览器,试图访问的对象已经被移到别的位置了,到该头部指定的位置去取。
              例如:Location:http://i0.sinaimg.cn/dy/deco/2008/0528/sinahome_0803_ws_005_text_0.gif

17. Pramga:主要使用 Pramga: no-cache,相当于 Cache-Control: no-cache。
            例如:Pragma:no-cache

18. Proxy-Authenticate: 代理服务器响应浏览器,要求其提供代理身份验证信息。
    Proxy-Authorization:浏览器响应代理服务器的身份验证请求,提供自己的身份信息。

19. Range:浏览器(比如 Flashget 多线程下载时)告诉 WEB 服务器自己想取对象的哪部分。
           例如:Range: bytes=1173546-

20. Referer:浏览器向 WEB 服务器表明自己是从哪个 网页/URL 获得/点击 当前请求中的网址/URL。
             例如:Referer:http://www.sina.com/

21. Server: WEB 服务器表明自己是什么软件及版本等信息。
            例如:Server:Apache/2.0.61 (Unix)

22. User-Agent: 浏览器表明自己的身份(是哪种浏览器)。
                例如:User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14

23. Transfer-Encoding: WEB 服务器表明自己对本响应消息体(不是消息体里面的对象)作了怎样的编码,比如是否分块(chunked)。
                       例如:Transfer-Encoding: chunked

24. Vary: WEB服务器用该头部的内容告诉 Cache 服务器,在什么条件下才能用本响应所返回的对象响应后续的请求。
          假如源WEB服务器在接到第一个请求消息时,其响应消息的头部为:Content-Encoding: gzip; Vary: Content-Encoding
          那么 Cache 服务器会分析后续请求消息的头部,检查其 Accept-Encoding,是否跟先前响应的 Vary 头部值一致,即是否使用
          相同的内容编码方法,这样就可以防止 Cache 服务器用自己 Cache 里面压缩后的实体响应给不具备解压能力的浏览器。
          例如:Vary:Accept-Encoding

25. Via: 列出从客户端到 OCS 或者相反方向的响应经过了哪些代理服务器,他们用什么协议(和版本)发送的请求。
          当客户端请求到达第一个代理服务器时,该服务器会在自己发出的请求里面添加 Via 头部,并填上自己的相关信息,当下一个代理服务器
          收到第一个代理服务器的请求时,会在自己发出的请求里面复制前一个代理服务器的请求的Via 头部,并把自己的相关信息加到后面,
          以此类推,当 OCS 收到最后一个代理服务器的请求时,检查 Via 头部,就知道该请求所经过的路由。
          例如:Via:1.0 236-81.D07071953.sina.com.cn:80 (squid/2.6.STABLE13)

============================================================================================================================
HTTP 请求消息头部实例:
Host:rss.sina.com.cn
User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14
Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language:zh-cn,zh;q=0.5
Accept-Encoding:gzip,deflate
Accept-Charset:gb2312,utf-8;q=0.7,*;q=0.7
Keep-Alive:300
Connection:keep-alive
Cookie:userId=C5bYpXrimdmsiQmsBPnE1Vn8ZQmdWSm3WRlEB3vRwTnRtW   <-- Cookie
If-Modified-Since:Sun, 01 Jun 2008 12:05:30 GMT
Cache-Control:max-age=0

HTTP 响应消息头部实例:
Status:OK – 200                                                <-- 响应状态码,表示 web 服务器处理的结果。
Date:Sun, 01 Jun 2008 12:35:47 GMT
Server:Apache/2.0.61 (Unix)
Last-Modified:Sun, 01 Jun 2008 12:35:30 GMT
Accept-Ranges:bytes
Content-Length:18616
Cache-Control:max-age=120
Expires:Sun, 01 Jun 2008 12:37:47 GMT
Content-Type:application/xml
Age:2
X-Cache:HIT from 236-41.D07071951.sina.com.cn                  <-- 反向代理服务器使用的 HTTP 头部
Via:1.0 236-41.D07071951.sina.com.cn:80 (squid/2.6.STABLE13)
Connection:close
=============================================================================================================================

 Posted by at 上午 7:45
6月 262008
 

Etag 是URL的Entity Tag,用于标示URL对象是否改变,区分不同语言和Session等等。具体内部含义是使服务器控制的,就像Cookie那样。它有一些好处和特点:

1、有些URL是多语言的网页,相同的URL会返回不同的东东。还有不同的Session有不同的Cookie也就有不同的内容。这种情况下如果过Proxy,Proxy就无法区分导致串门,只能简单的取消cache功能。Etag解决了这个问题,因为它能区分相同URL不同的对象。

2、老的HTTP标准里有个Last-Modified+If-Modified-Since表明URL对象是否改变。Etag也具有这种功能,因为对象改变也造成Etag改变,并且它的控制更加准确。Etag有两种用法 If-Match/If-None-Match,就是如果服务器的对象和客户端的对象ID(不)匹配才执行。这里的If-Match/If-None-Match都能一次提交多个Etag。If-Match可以在Etag未改变时断线重传。If-None-Match可以刷新对象(在有新的Etag时返回)。

3、Etag中有种Weak Tag,值为 W/"xxxxx"。他声明Tag是弱匹配的,只能做模糊匹配,在差异达到一定阀值时才起作用。

4、Etag对于cache CGI页面很有用。特别是论坛,论坛有办法为每个帖子页面生成唯一的Etag,在帖子未改变时,查看话题属性比较Etag就能避免刷新帖子,减少CGI操作和网络传输。ownsky现在的看帖就返回Etag,减少论坛负担。

5、针对搂主问题加一点,Etag在不同URL之间没有可比性。也就是不同URL相同Etag没有特别意义。

 Posted by at 上午 7:38
6月 112008
 

http协议里控制浏览器缓存的头有三个Cache-Control,Expires,Last-Modified
对于静态页面还有Etag。
一、先来看第一种情况:apache 静态页面
apache发送给客户端的静态页面一般包含Last-Modified和Etag,这两个标签的值来自静态文件的修改时间和inode,
下面是截取得apache返回客户端的头
———
Last-Modified: Fri, 26 Jan 2007 01:53:34 GMT
ETag: "3f9f640-318-cb9f8380"
———
搜索引擎之所以喜欢静态文件是因为有这两个标识,可以判断文件是否更新过

二、PHP等动态页面
由于php是动态生成的,它的内容是不能根据php程序的时间来确定最后修改日期,所以默认php返回客户端的时候补包含任何缓存控制,要想利用好缓存就必须了解缓存机制,和理减少b,s的交互,缩减带宽流量,减轻服务器负担…好处多多

三、缓存控制的具体含义
先解释一下本人经过测试理解的这几个标签的含义
Cache-Control:指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age。各个消息中的指令含义如下:
Public指示响应可被任何缓存区缓存。
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
no-cache指示请求或响应消息不能缓存
no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
php用法:
在输出之前用header(),(如果使用ob_start()可以将header放在程序任意地方)
header(‘Cache-Control: max-age=8’);
max-age=8表示最大生存期8秒,超过8秒浏览器必须去服务器重新读取,这个时间是以用户的读取页面开始计时的,而Expires是绝对时间。
Expires:缓存过期的绝对时间,如果过了它指定的那个时间点,浏览器就不认缓存了,要去服务器重新请求一份最新的。

Last-Modified:文档的最后修改时间,它的妙用就是:1 如果是静态文件,客户端会发上来它缓存里的时间,apache会来比对,如果发现没有修改就直接返回一个头,状态码是304,字节数非常少,(高级版本还会增加比较Etag来确定文件是否变化)
2 php动态文件: 客户端发上比对时间,php会判断是否修改,如果修改时间相同,就只会返回1024字节,至于为什么返回1024不得而知,如果你的php生成的文件非常大,它也只返回1024,所以比较省带宽,客户端会根据服务器端发过来的修改时间自动从缓存文件里显示。

注:如果没有Last-Modified头,Cache-Control和Expires也是可以起作用的,但每次请求要返回真实的文件字节数,而不是1024

四、HOW ?
静态页面不用去管它了,如果想更好的控制静态页面的缓存,apache有几个模块可以很好的控制,这里不讨论
php页面:
这里分两种:1 不经常改动的页面,类似新闻发布,这类页面的特点:第一次发布之后会有几次改动,随着时间推移基本不会再修改。控制策略应该是:1第一次发布之发送Last-Modified,max-age设定1天,修改过之后更新Last-Modified,max-age时间随着修改次数正常。这样似乎比较繁琐,还要记录修改次数,也可以预计一下下次可能的修改时间用Expires指定到大概时间过期
php代码:
//header(‘Cache-Control: max-age=86400’);//缓存一天
header(‘Expires: Mon, 29 Jan 2007 08:56:01 GMT’);//指定过期时间
header(‘Last-Modified: ‘.gmdate(‘D, d M Y 01:01:01′,$time).’ GMT’);//格林尼治时间,$time是文件添加时候的时间戳
2 经常改动的页面  类似bbs,论坛程序,这种页面更新速度比较快,缓存的主要作用是防止用户频繁刷新列表,导致服务器数据库负担,既要保证更新的及时性,也要保证缓存能被利用
这里一般用Cache-Control来控制,根据论坛的发帖的频率灵活控制max-age。
header(‘Cache-Control: max-age=60’);//缓存一分钟
header(‘Last-Modified: ‘.gmdate(‘D, d M Y 01:01:01′,$time).’ GMT’);//格林尼治时间,$time是帖子的最后更新时间戳

五 额外
1 刷新,转到,强制刷新的区别
浏览器上有刷新和转到按键,有的浏览器支持用ctrl+F5强制刷新页面,它们的区别是什么?
转到:用户点击链接就是转到,它完全使用缓存机制,如果有Last-Modified那么不会和服务器通讯,用抓包工具可以查看到发送字节是0byte,如果缓存过期,那么它会执行F5刷新的动作。
刷新(F5):这种刷新也是根据缓存是否有Last-Modified来决定,如果有会转入304或1024(php),如果没有最后更新时间那么去服务器读取,返回真实文档大小
强制刷新:完全抛弃缓存机制,去服务器读取最新文档,向服务器发送的header如下
Cache-Control: no-cache

2 调试工具
查看浏览器和服务器交互比较好的工具是httpwatch pro,现在的版本4.1,支持ie7
还有别的代理抓包工具可以分析,http debugging。没用过,还有tcp抓包工具,2000自带的network monitor不过不是专门针对http的比较难用

六 声明
本文作者保留所有权力,允许被自由查看和转载,但必须指明作者(Ash)和源网址(www.cosrc.com);不允许商用

 

相关资料:
http://www.zgkw.cn/FORUMS/forums/59660/ShowThread.aspx
http://www.javaeye.com/topic/119336
http://www.happyshow.org/article/209.html

 Posted by at 上午 1:42