这就是某些网站用来收集访客信息的一般手段。例如,你可以判断访客是否在使用手机访问你的网站,然后决定是否将他们引导至一个在低分辨率下表现良好的移动网站。
在PHP中,可以通过 $_SERVER['HTTP_USER_AGENT'] 来获取User-Agent
if ( strstr($_SERVER['HTTP_USER_AGENT'],'MSIE 6') ) {
echo "Please stop using IE6!";
}
Accept-LanguageAccept-Language: en-us,en;q=0.5
这个信息可以说明用户的默认语言设置。如果网站有不同的语言版本,那么就可以通过这个信息来重定向用户的浏览器。
它可以通过逗号分割来携带多国语言。第一个会是首选的语言,其它语言会携带一个“q”值,来表示用户对该语言的喜好程度(0~1)。
在PHP中用 $_SERVER["HTTP_ACCEPT_LANGUAGE"] 来获取这一信息。
if (substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2) == 'fr') {
header('Location: http://french.mydomain.com');
}
Accept-EncodingAccept-Encoding: gzip,deflate
大部分的现代浏览器都支持gzip压缩,并会把这一信息报告给服务器。这时服务器就会压缩过的HTML发送给浏览器。这可以减少近80%的文件大小,以节省下载时间和带宽。
在PHP中可以使用 $_SERVER["HTTP_ACCEPT_ENCODING"] 获取该信息。 然后调用ob_gzhandler()方法时会自动检测该值,所以你无需手动检测。
// enables output buffering
// and all output is compressed if the browser supports it
ob_start('ob_gzhandler');
If-Modified-Since如果一个页面已经在你的浏览器中被缓存,那么你下次浏览时浏览器将会检测文档是否被修改过,那么它就会发送这样的头部:
If-Modified-Since: Sat, 28 Nov 2009 06:38:19 GMT
如果自从这个时间以来未被修改过,那么服务器将会返回“304 Not Modified”,而且不会再返回内容。浏览器将自动去缓存中读取内容
在PHP中,可以用$_SERVER['HTTP_IF_MODIFIED_SINCE'] 来检测。
// assume $last_modify_time was the last the output was updated
// did the browser send If-Modified-Since header?
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
// if the browser cache matches the modify time
if ($last_modify_time == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
// send a 304 header, and no content
header("HTTP/1.1 304 Not Modified");
exit;
}
}
还有一个叫Etag的HTTP头信息,它被用来确定缓存的信息是否正确,稍后我们将会解释它。
Cookie顾名思义,他会发送你浏览器中存储的Cookie信息给服务器。
Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120; foo=bar
它是用分号分割的一组名值对。Cookie也可以包含session id。
在PHP中,单一的Cookie可以访问$_COOKIE数组获得。你可以直接用$_SESSION array获取session变量。如果你需要session id,那么你可以使用session_id()函数代替cookie。
echo $_COOKIE['foo'];
// output: bar
echo $_COOKIE['PHPSESSID'];
// output: r2t5uvjq435r4q7ib3vtdjq120
session_start();
echo session_id();
// output: r2t5uvjq435r4q7ib3vtdjq120
Referer顾名思义, 头部将会包含referring url信息。
例如,我访问Nettuts+的主页并点击了一个链接,这个头部信息将会发送到浏览器:
Referer: http://net.tutsplus.com/
在PHP中,可以通过 $_SERVER['HTTP_REFERER'] 获取该值。
if (isset($_SERVER['HTTP_REFERER'])) {
$url_info = parse_url($_SERVER['HTTP_REFERER']);
// is the surfer coming from Google?
if ($url_info['host'] == 'www.google.com') {
parse_str($url_info['query'], $vars);
echo "You searched on Google for this keyword: ". $vars['q'];
}
}
// if the referring url was:
// http://www.google.com/search?sou ... ;oq=&aqi=g-p1g9
// the output will be:
// You searched on Google for this keyword: http headers
You may have noticed the word “referrer” is misspelled as “referer”. Unfortunately it made into the official HTTP specifications like that and got stuck.
Authorization当一个页面需要授权,浏览器就会弹出一个登陆窗口,输入正确的帐号后,浏览器会发送一个HTTP请求,但此时会包含这样一个头部:
Authorization: Basic bXl1c2VyOm15cGFzcw==
包含在头部的这部分信息是base64 encoded。例如,base64_decode(‘bXl1c2VyOm15cGFzcw==’) 会被转化为 ‘myuser:mypass’ 。
在PHP中,这个值可以用$_SERVER['PHP_AUTH_USER'] 和 $_SERVER['PHP_AUTH_PW'] 获得。
更多细节我们会在WWW-Authenticate部分讲解。
HTTP Headers 中的 HTTP响应现在让我了解一些常见的HTTP Headers中的HTTP响应信息。
在PHP中,你可以通过 header() 来设置头部响应信息。PHP已经自动发送了一些必要的头部信息,如 载入的内容,设置 cookies 等等… 你可以通过 headers_list() 函数看到已发送和将要发送的头部信息。你也可以使用headers_sent()函数来检查头部信息是否已经被发送。
Cache-Controlw3.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列表。
在PHP中你可以通过 finfo_file() 来检测文件的ime-type。
Content-Disposition这个头部信息将告诉浏览器打开一个文件下载窗口,而不是试图解析该响应的内容。例如:
Content-Disposition: attachment; filename="download.zip"
他会导致浏览器出现这样的对话框:
注意,适合它的Content-Type头信息同时也会被发送
Content-Type: application/zip
Content-Disposition: attachment; filename="download.zip"
Content-Length当内容将要被传输到浏览器时,服务器可以通过该头部告知浏览器将要传送文件的大小(bytes)。
Content-Length: 89123
对于文件下载来说这个信息相当的有用。这就是为什么浏览器知道下载进度的原因。
例如,这里我写了一段虚拟脚本,来模拟一个慢速下载。
// it's a zip file
header('Content-Type: application/zip');
// 1 million bytes (about 1megabyte)
header('Content-Length: 1000000');
// load a download dialogue, and save it as download.zip
header('Content-Disposition: attachment; filename="download.zip"');
// 1000 times 1000 bytes of data
for ($i = 0; $i < 1000; $i++) {
echo str_repeat(".",1000);
// sleep to slow down the download
usleep(50000);
}
结果将会是这样的:
现在,我将Content-Length头部注释掉:
// it's a zip file
header('Content-Type: application/zip');
// the browser won't know the size
// header('Content-Length: 1000000');
// load a download dialogue, and save it as download.zip
header('Content-Disposition: attachment; filename="download.zip"');
// 1000 times 1000 bytes of data
for ($i = 0; $i < 1000; $i++) {
echo str_repeat(".",1000);
// sleep to slow down the download
usleep(50000);
}
结果就变成了这样:
这个浏览器只会告诉你已下载了多少,但不会告诉你总共需要下载多少。而且进度条也不会显示进度。
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
$modify_time = filemtime($file);
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modify_time) . " GMT");
它提供了另一种缓存机制。浏览器可能会发送这样的请求:
If-Modified-Since: Sat, 28 Nov 2009 06:38:19 GMT
在If-Modified-Since一节我们已经讨论过了。
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 GMT
Set-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就会在浏览器关闭后被删除。
WWW-Authenticate一个网站可能会通过HTTP发送这个头部信息来验证用户。当浏览器看到头部有这个响应时就会打开一个弹出窗。
WWW-Authenticate: Basic realm="Restricted Area"
它会看起来像这样:
在PHP手册的一章中就有一段简单的代码演示了如果用PHP做这样的事情:
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
Content-Encoding这个头部通常会在返回内容被压缩时设置。
Content-Encoding: gzip
在PHP中,如果你调用了ob_gzhandler()函数,这个头部将会自动被设置。
原文:HTTP headers 详细介绍