Más contenido relacionado Similar a Http header的方方面面 (20) Http header的方方面面1. HTTP Header的方方面面 Tony Deng http://twitter.com/wolfdeng http://friendfeed.com/tonydeng http://delicious.com/wolf.deng http://wolfchina.blogbus.com 3. 什么是HTTP Header HTTP是“Hypertext Transfer Protocol”的缩写,整个万维网都在使用这种协议,几乎你在浏览器里看到的大部分内容都是通过http协议来传输的 HTTP是一个基于请求/响应模型的协议,每次的请求和响应都是能够自描述的。 HTTP Headers是HTTP请求和相应的核心,它承载了关于客户端浏览器,请求页面,服务器等相关的信息。 4. 如何才能看到HTTP Headers 可以使用firefox的插件 Firebug http://getfirebug.com/ https://addons.mozilla.org/zh-CN/firefox/addon/1843/ Live HTTP Headers https://addons.mozilla.org/zh-CN/firefox/addon/3829/ 6. Request HTTPHeaders 当你在浏览器地址栏里键入一个url,你的浏览器将会发出类似如下的http请求: POST /v2/rss/network/wolf.deng?src=ffbmext2.1.072 HTTP/1.1 Host: feeds.delicious.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6;ffbmext2.1.072 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 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: 115 Connection: keep-alive Authorization: Basic Y29va2llOmNvb2tpZQ== Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Content-Length: 121 Cookie: delicious_us_production=wKAmdMVbf6Puirvhqyt5EZohOKZSFQLAzT8fG2YbpuCrI58dVgL5PsKgtSoZYweu9iP7uw8yrEgP7E1Mh19STmdk7swRT_Q.Lsy6dygA__2GGz5GOQEbZQilhfYD43vmw7g7sF6vhVJ.zozzgDxB27WmCst.E5NIxU2.a5rZymPwjoVsIZMo6jvIuKwxk6FVQVOzNuR.ioBFtFK8r31tcHqAppaXOey9W5bt2Y9ImIh5eskaw41k3dedlmdiWkWlULkhgQjWcfQBLWMCWvil4d1xCfF_6mdNfEDgPT1ub9pddrBZHEnxJMxeFCJMzRfiCrxLfZnJm.w-; _user=wolf.deng%202.1%201274542193%20-1%201%2069ee445a6e6b9c5e55e7dbedbf8e966a%204Yi4QNm6kG7rtc.eIX_3C8yveFQ-; lt=d; FFDeliciousXT=version=2.0 Pragma: no-cache Cache-Control: no-cache _user=wolf.deng%25202.1%25201274542193%2520-1%25201%252069ee445a6e6b9c5e55e7dbedbf8e966a%25204Yi4QNm6kG7rtc.eIX_3C8yveFQ- 8. HTTP Request 的结构 被称作“Request-Line”的第一行包含三个部分: “method” 表明这是何种类型的请求. 最常见的请求类型有 GET, POST 和 HEAD. “path” 体现的是主机之后的路径. 例如, 当你请求 “http://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/”时 , path 就会是 “/tutorials/other/top-20-mysql-best-practices/”. “protocol” 包含有 “HTTP” 和版本号, 现代浏览器都会使用1.1. 剩下的部分每行都是一个“Name:Value”对。 它们包含了各式各样关于请求和你浏览器的信息。例如 “User-Agent“就表明了你浏览器 版本和你所用的操作系统。 “Accept-Encoding“会告诉服务器你的浏览可以接受类似gzip的压缩输出。 这些headers大部分都是可选的,当你去掉这些headers之后,你仍旧可以从服务器收到有效的响应。 HTTP 请求甚至可以被精简成这样子: GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1 Host: net.tutsplus.com 10. GET:获取一个文档 大部分被传输到浏览器的html,images,js,css, … 都是通过GET方法发出请求的。它是获取数据的主要方法。 例如,要获取Nettuts+的文章,http request的第一行通常看起来是这样的: GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1 一旦html加载完成,浏览器将会发送GET 请求去获取图片,就像下面这样: GET /wp-content/themes/tuts_theme/images/header_bg_tall.png HTTP/1.1 表单也可以通过GET方法发送,下面是个例子: <form action="foo.php" method="GET">First Name: <input name="first_name" type="text" />Last Name: <input name="last_name" type="text" /><input name="action" type="submit" value="Submit" /></form> 当这个表单被提交时,HTTP request 就会像这样: GET /foo.php?first_name=John&last_name=Doe&action=Submit HTTP/1.1... 你可以将表单输入通过附加进查询字符串的方式发送至服务器。 11. POST:发送数据至服务器 尽管你可以通过GET方法将数据附加到url中传送给服务器,但在很多情况下使用POST发送数据给服务器更加合适。通过GET发送大量数据是不现 实的,它有一定的局限性。 用POST请求来发送表单数据是普遍的做法。我们来把上面的例子改造成使用POST方式: <form action="foo.php" method="POST">First Name: <input name="first_name" type="text" />Last Name: <input name="last_name" type="text" /><input name="action" type="submit" value="Submit" /></form> 提交这个表单会创建一个如下的HTTP 请求: POST /foo.php HTTP/1.1Host: localhostUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7Keep-Alive: 300Connection: keep-aliveReferer: http://localhost/test.phpContent-Type: application/x-www-form-urlencodedContent-Length: 43first_name=John&last_name=Doe&action=Submit 这里有三个需要注意的地方: 第一行的路径已经变为简单的 /foo.php , 已经没了查询字符串。 新增了 Content-Type 和 Content-Lenght头部,它提供了发送信息的相关信息. 所有数据都在headers之后,以查询字符串的形式被发送. POST方式的请求也可用在AJAX,应用程序,cURL … 之上。并且所有的文件上传表单都被要求使用POST方式。 13. HTTP Headers 中的 HTTP请求 现在我们来看一些在HTTP headers中常见的HTTP请求信息。 Host 一个HTTP请求会发送至一个特定的IP地址,但是大部分服务器都有在同一IP地址下托管多个网站的能力,那么服务器必须知道浏览器请求的是哪个域 名下的资源。 Host: rlog.cn 这只是基本的主机名,包含域名和子级域名。 User-Agent User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729) 这个头部可以携带如下几条信息: 浏览器名和版本号. 操作系统名和版本号. 默认语言. 这就是某些网站用来收集访客信息的一般手段。例如,你可以判断访客是否在使用手机访问你的网站,然后决定是否将他们引导至一个在低分辨率下表现良好 的移动网站。 Accept-Language Accept-Language: en-us,en;q=0.5 这个信息可以说明用户的默认语言设置。如果网站有不同的语言版本,那么就可以通过这个信息来重定向用户的浏览器。 它可以通过逗号分割来携带多国语言。第一个会是首选的语言,其它语言会携带一个“q”值,来表示用户对该语言的喜好程度(0~1)。 Accept-Encoding Accept-Encoding: gzip,deflate 大部分的现代浏览器都支持gzip压缩,并会把这一信息报告给服务器。这时服务器就会压缩过的HTML发送给浏览器。这可以减少近80%的文件大 小,以节省下载时间和带宽。 14. Response HTTP Headers 当web服务器接收到之前的请求,会给出类似的响应 HTTP/1.1200 OK Date: Mon, 19 Jul 2010 13:40:03 GMT P3P: policyref="http://info.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAiIVDiCONiTELoOTPi OUR DELiSAMiOTRiUNRiPUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV" Last-Modified: Mon, 19 Jul 2010 13:40:03 +0000 Set-Cookie: delicious_us_production=f.RPhmyyeaMTaqrzmogv9WIGhABJwj2ZBXmfzl5LdKHdcuH0Pd0VbMLG3U6mhIJpZaaljQsKbSKdCV1pkYOm4eDHYj6ZHQZ6qBPlsa_nme9T9jDIs5WQlCKi6TSg5em31gME2FrLMivIoYvkugbLMh7QGa4I9W1rtzCcDvKQ.qs618aG_Izt4aBJK11c6TmV_YeW1cwx.Z1NuYmSBT4GDSwqEMrBMWtwB2VN3pYy96cW3rAzsdJqr_kizqLR74WHPXC6d1pSF.iyqb990xzQaDS7iqLmTCWt7bSd9zBfmh3Fd_e1VxPRFSk6Gn_3SiAwYAcv1PVedjk-; expires=Tue, 19-Jul-2011 13:40:03 GMT; path=/; domain=.delicious.com Content-Type: application/rss+xml; charset=utf-8 Cache-Control: private Age: 0 Transfer-Encoding: chunked Connection: keep-alive Server: YTS/1.17.21 16. http响应结构 第一个有价值的信息就是协议。目前服务器都会使用 HTTP/1.x 或者 HTTP/1.1。 接下来一个简短的信息代表状态。代码200意味着我们的请求已经发送成功了,服务器将会返回给我们所请求的文档,在头部信息之后。 我们都见过“404”页面。当我向服务器请求一个不存在的路径时,服务器就用用404来代替200响应我们。 余下的响应内容和HTTP请求相似。这些内容是关于服务器软件的,页面/文件何时被修改过,mime type 等等… 同样,这些头部信息也是可选的。 17. HTTP状态码 完整的HTTP状态码列表 http://en.wikipedia.org/wiki/List_of_HTTP_status_codes http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1 http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.1.1 200 用来表示请求成功. 200 成功 (OK) 前文已经提到,200是用来表示请求成功的。 206 部分内容 (Partial Content) 如果一个应用只请求某范围之内的文件,那么就会返回206. 这通常被用来进行下载管理,断点续传或者文件分块下载。 300 来表示重定向. 302(或307)临时移动(Moved Temporarily) 和 301 永久移动(Moved Permanently) 这两个状态会出现在浏览器重定向时。例如,你使用了类似 bit.ly 的网址缩短服务。这也是它们如何获知谁点击了他们链接的方法。 302和301对于浏览器来说是非常相似的,但对于搜索引擎爬虫就有一些差别。 打个比方,如果你的网站正在维护,那么你就会将客户端浏览器用302 重定向到另外一个地址。搜索引擎爬虫就会在将来重新索引你的页面。 但是如果你使用了301重定向,这就等于你告诉了搜索引擎爬虫:你的网站已经永久的移动 到了新的地址。 400 用来表示请求出现问题. 401 未经授权 (Unauthorized) 403 被禁止(Forbidden) 500 用来表示服务器出现问题. 这个代码通常会在页面脚本崩溃时出现。大部分CGI脚本都不会像PHP那样输出错误信息给浏览器。如果出现了致命的错误,它们只会发送一个500的状态 码。这时需要查看服务器错误日志来排错。 18. HTTP Headers 中的 HTTP响应 Cache-Control w3.org 的定义是:“The Cache-Control general-header field is used to specify directives which MUST be obeyed by all caching mechanisms along the request/response chain.” 其中“caching mechanisms” 包含一些你ISP可能会用到的 网关和代理信息。 例如: Cache-Control: max-age=3600, public “public”意味着这个响应可以被任何人缓存,“max-age” 则表明了该缓存有效的秒数。允许你的网站被缓存降大大减少下载时间和带宽,同时也提高的浏览器的载入速度。 也可以通过设置 “no-cache” 指令来禁止缓存: Cache-Control: no-cache 更多详情请参见w3.org。 Content-Type 这个头部包含了文档的”mime-type”。浏览器将会依据该参数决定如何对文档进行解析。例如,一个html页面(或者有html输出的php页面)将会返回这样的东西: Content-Type: text/html; charset=UTF-8 ‘text’ 是文档类型,‘html’则是文档子类型。 这个头部还包括了更多信息,例如 charset。 如果是一个图片,将会发送这样的响应: Content-Type: image/gif 浏览器可以通过mime-type来决定使用外部程序还是自身扩展来打开该文档。如下的例子降调用Adobe Reader: Content-Type: application/pdf 直接载入,Apache通常会自动判断文档的mime-type并且添加合适的信息到头部去。并且大部分浏览器都有一定程度的容错,在头部未提供或 者错误提供该信息的情况下它会去自动检测mime-type。 你可以在这里找到一个常用mime-type列表。 19. HTTP Headers 中的 HTTP响应 Content-Disposition 这个头部信息将告诉浏览器打开一个文件下载窗口,而不是试图解析该响应的内容。例如: Content-Disposition: attachment; filename="download.zip" 他会导致浏览器出现这样的对话框: 注意,适合它的Content-Type头信息同时也会被发送 Content-Type: application/zipContent-Disposition: attachment; filename="download.zip" 20. HTTP Headers 中的 HTTP响应 Content-Length 当内容将要被传输到浏览器时,服务器可以通过该头部告知浏览器将要传送文件的大小(bytes)。 Content-Length: 89123 对于文件下载来说这个信息相当的有用。这就是为什么浏览器知道下载进度的原因。 现在,我将Content-Length头部注释掉: 结果就变成了这样: 这个浏览器只会告诉你已下载了多少,但不会告诉你总共需要下载多少。而且进度条也不会显示进度。 21. HTTP Headers 中的 HTTP响应 Etag 这是另一个为缓存而产生的头部信息。它看起来会是这样: Etag: "pub1259380237;gz" 服务器可能会将该信息和每个被发送文件一起响应给浏览器。该值可以包含文档的最后修改日期,文件大小或者文件校验和。浏览 会把它和所接收到的文档一起缓存。下一次当浏览器再次请求同一文件时将会发送如下的HTTP请求: If-None-Match: "pub1259380237;gz" 如果所请求的文档Etag值和它一致,服务器将会发送304状态码,而不是2oo。并且不返回内容。浏览器此时就会从缓存加载该文件。 Last-Modified 顾名思义,这个头部信息用GMT格式表明了文档的最后修改时间: Last-Modified: Sat, 28 Nov 2009 03:50:37 GMT 它提供了另一种缓存机制。浏览器可能会发送这样的请求: If-Modified-Since: Sat, 28 Nov 2009 06:38:19 GMT 22. HTTP Headers 中的 HTTP响应 Location 这个头部是用来重定向的。如果响应代码为 301 或者 302 ,服务器就必须发送该头部。例如,当你访问 http://www.nettuts.com 时浏览器就会收到如下的响应: HTTP/1.x 301 Moved Permanently...Location: http://net.tutsplus.com/... 在PHP中你可以通过这种方式对访客重定向:header('Location: http://net.tutsplus.com/'); 默认会发送302状态码,如果你想发送301,就这样写: header('Location: http://net.tutsplus.com/', true, 301); Set-Cookie 当一个网站需要设置或者更新你浏览的cookie信息时,它就会使用这样的头部: Set-Cookie: skin=noskin; path=/; domain=.amazon.com; expires=Sun, 29-Nov-2009 21:42:28 GMTSet-Cookie: session-id=120-7333518-8165026; path=/; domain=.amazon.com; expires=Sat Feb 27 08:00:00 2010 GMT 每个cookie会作为单独的一条头部信息。注意,通过js设置cookie将不会体现在HTTP头中。 在PHP中,你可以通过setcookie()函 数来设置cookie,PHP会发送合适的HTTP 头。 setcookie("TestCookie", "foobar"); 它会发送这样的头信息: Set-Cookie: TestCookie=foobar 如果未指定到期时间,cookie就会在浏览器关闭后被删除。 23. HTTP Headers 中的 HTTP响应 WWW-Authenticate 一个网站可能会通过HTTP发送这个头部信息来验证用户。当浏览器看到头部有这个响应时就会打开一个弹出窗。 WWW-Authenticate: Basic realm="Restricted Area" 它会看起来像这样: Content-Encoding 这个头部通常会在返回内容被压缩时设置。 Content-Encoding: gzip