HTTP 頭和 PHP header() 函數

http://unifreak.github.io/translation/Http_headers_and_PHP_header()_function

 

引言

許多初級到中級的的 PHP 程序員把 header() 函數看成某種神祕巫術. 他們能夠照着代碼示例把功能實現, 可是仍是不知道到底它是若是運做的. 我最開始就是這樣的.php

實際上它很是簡單. 在這篇文章中, 我會解釋 HTTP 頭(header) 是如何運做的, 它們與 PHP 的關係, 以及它們的 meta 標籤 equivalents(對應物)html

但願你讀完以後, 能更順手的使用 header() 函數, 甚至想出一些更多利用它的地方. 咱們也會講到其餘一些關於 HTTP 和 PHP 的重要話題. 可是在咱們開始講任何程序相關的東西以前, 咱們須要先快速(而且不完整的)過一遍 HTTP (HyperTex Transfer Protocol) 運做原理linux

HTTP 概覽

Headers: 對話中的詞語

HTTP 是 web 服務器和客戶端瀏覽器之間的數據傳輸(好比 web 頁面中的 HTML, 圖片, 文件)協議(‘規則’集合), 而且一般使用 80 端口. 這就是網站 URL 前面 ‘http://’ 的來源git

不少人最開始製做 web 頁面的時候, 他們先在本地電腦上寫 HTML, 在本地瀏覽器查看是否符合預期, 而後上傳到服務器, 就能夠在網上瀏覽這些頁面了. 看起來好像在不管在本地查看與在服務器上查看的頁面都同樣, 傳輸的數據只有這些 HTML 以及它包含的圖片. 可是實際上還有另一些許多你沒看到的信息 - 頭信息.程序員

頭信息能夠分爲兩大類: 你瀏覽器向服務器請求文件時發出的請求頭信息, 服務器提供文件給瀏覽器時發出的響應頭信息. 把這些頭信息看成瀏覽器和服務器對話時的詞語. 我喜歡把服務器想象爲圖書管理員, 把瀏覽器想象成正在請求圖書資源的學者. 瀏覽器走向位於服務檯 (80 端口) 的服務器, 說道, 「Hi, 我是 Mozilla, 我正在找這個編目號是 ‘www.expertsrt.com’ 的資源. 你能夠幫我找到它嗎?」 服務器聽到後迴應 「是的, 我找到了, 讓我把它給你. 這裏面是 HTML 文本, 它寫的是 ‘<html>...’」 瀏覽器開始從頭至尾的讀它, 而且遇到了一個圖片標籤, 因此向服務器要位於 src 屬性指定處的圖片. 服務器進行查找, 找到這個文件而後說道 「這是個 PNG 圖片, 它的數據是…」 你懂的.github

另外一個對話可能像這樣:web

瀏覽器: Hi, 我是 Mozilla, 能給我在 ‘www.expertsrt.com/moved.html’ 這裏的文件嗎?.sql

服務器: 那個文件已經不在那兒了, 他如今在 ‘www.expertsrt.com/newloc.html’.apache

瀏覽器: Hi, 我是 Mozilla, 能給我在 ‘www.expertsrt.com/newloc.html’ 這裏的文件嗎?編程

服務器: 我找到這個文件了. 查看它 10 秒鐘而後再向我問一次. 它是一個 HTML 文本文件, 它有這些內容…

…10 秒鐘…

瀏覽器: Hi, 我是 Mozilla, 能給我在 ‘www.expertsrt.com/newloc.html’ 這裏的文件嗎?

服務器: 我找到這個文件了. 查看它 10 秒鐘而後再向我問一次. 它是一個 HTML 文本文件, 它有這些內容…

…10 秒鐘…

瀏覽器: Hi, 我是 Mozilla, 能給我在 ‘www.expertsrt.com/newloc.html’ 這裏的文件嗎?

服務器: 我找到這個文件了. 查看它 10 秒鐘而後再向我問一次. 它一個 HTML 文本文件, 它有這些內容…

…諸如這般, 直到瀏覽器被用戶從新定向…

正如你所看到的, 使用頭信息能夠控制許多事情. 使用 header() 函數, 你可讓服務器發送你所需的頭信息, 這樣你能夠作除了發送 HTML 以外許多很酷的事情.

看看整個對話過程

在繼續以前, 讓咱們先不使用瀏覽器來查看一個 web 頁面, 這樣咱們能夠看到整個對話, 更好的瞭解 HTTP 頭的工做. 先打開命令行 (在 windows 中, 點擊開始菜單->運行, 輸入 cmd, 而後點擊 「OK」…若是你正使用 linux, 你或許已經知道怎麼打開了). 在命令行中輸入:

telnet expertsrt.com 80

而後回車. 這會連接到 expersrt.com 的 80 端口. 而後, 複製並粘貼下面的文字:

GET / HTTP/1.1
Host: expertsrt.com

若是你輸入或粘貼這些文字的時候, 命令行除了光標的閃爍沒看到任何動靜的話, 不要擔憂 – 它們確實被髮送到服務器了. 第一行說明你使用 GET 請求方法去獲取資源 / (這裏是目標主機上基目錄裏的文件), 而且你在使用 HTTP 1.1 版本. 第二行告訴服務器你想要鏈接到哪臺主機. 當你輸入 ‘expertsrt.com’ 後, 回車兩次 (只需兩次). 你應當馬上獲得相似下面的響應:

HTTP/1.1 301 Moved Permanently
Date: Wed, 08 Feb 2006 07:44:07 GMT
Server: Apache/2.0.54 (Debian GNU/Linux) mod_auth_pgsql/2.0.2b1 mod_ssl/2.0.54 OpenSSL/0.9.7e
Location: http://www.expertsrt.com/
Content-Length: 233
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>301 Moved Permanently</title> </head><body> <h1>Moved Permanently</h1> <p>The document has moved <a href="http://www.expertsrt.com/">here</a>.</p> </body></html> 

哎呀! 看起來好像咱們請求的文件已經不在那兒了; 它已經被移到新的地方了: http://www.expertsrt.com. 若是你使用瀏覽器, 你只會看到 HTML - 在第一個空白行以前的都是頭信息. 實際上, 現代瀏覽器比這更智能 - 當他們看到第三行的新的 URL 時, 會自動轉向那裏, 這樣你就不用手動再輸入這個新的 URL 了. 讓咱們去這個新的 URL. 這時可能你已經斷開鏈接了. 若是這樣, 只需按向上鍵, telnet 命令會出現, 而後回車以從新鏈接. 若是你沒有斷開鏈接, 那直接輸入下面的文字就行:

GET / HTTP/1.1
Host: www.expertsrt.com

而後回車兩次. 你會看到另外一個相似的響應, 告訴你那個頁面實際上在 http://www.expertsrt.com/index.php. 服務器真挑剔是否是? ;-) 重複上面的操做, 不過此次輸入

GET /index.php HTTP/1.1
Host: www.expertsrt.com

注意咱們想要的文件名在第一行. 這一次咱們屏幕被文字刷滿了: 這就是來自 ERT 主頁的 HTML. 這裏的頭信息看起來是這樣的

HTTP/1.1 200 OK
Date: Wed, 08 Feb 2006 08:20:07 GMT
Server: Apache/2.0.54 (Debian GNU/Linux) mod_auth_pgsql/2.0.2b1 mod_ssl/2.0.54 OpenSSL/0.9.7e
X-Powered-By: PHP/4.4.0
Transfer-Encoding: chunked
Content-Type: text/html

很簡單是否是? 咱們來繼續探討這跟你編程有什麼關係. 若是你不明白咱們講到的全部事情也沒有關係. 重要的是對瀏覽器和服務器如何交互的有個大體印象, 以及意識到並無什麼魔法在裏面. 最終就是這些

  1. 瀏覽器和服務器經過使用頭信息來進行交互
  2. 頭信息在主要內容以前發送, 而且用兩個 CRLF/換行符 來和主要內容分割開
  3. 在頭信息部分, 每一行就是一個頭. 首先是頭的名字, 而後是一個冒號一個空格, 而後是這個頭的名/值

    頭名: 頭值

  4. 頭信息能夠包括許多類型的信息和指示, 以便瀏覽器和服務器用來告知對方接下來該作什麼

提示: 若是你是那種刨根問底的人, 你能夠看看 RFC 2616, 那是 HTTP/1.1 的完整規範. 尤爲是 14 章, 包含每個頭的完整定義

PHP header(): 基礎

注意在咱們最終獲得的主頁中的 X-Powered-By: PHP/4.4.0 和 Content-Type: text/html 這兩個頭信息. PHP 一開始就被設計成輸出 HTML ( PHP 中的 H 即表明 ‘Hypertext’), 而且在 PHP 腳本第一次生成輸出(好比, 使用 echo)時, 會自動爲你包含這些頭信息. 這很是方便, 但也形成許多 PHP 新手對頭信息的困惑 - 在像 Perl 這樣不是一開始就被設計成用於 web 開發的語言中, 不包含你本身的頭而直接發送輸出會產生 ‘500 Internal Server Error’ 錯誤, 因此 Perl 的 web 開發者不得不當即學習關於頭信息的知識

header() 函數發送 HTTP 響應頭信息, 並且只作這件事

使用這個函數, 你可讓你的腳本發送你選擇的頭信息給瀏覽器, 創造一個很是有用的動態結果. 可是, 你須要知道關於 header() 函數的第一件事就是你必須在 PHP 發送任何輸出(這會使 PHP 自動發送默認的頭信息)以前使用它

我懷疑有哪一個 PHP 程序員沒有見到過以下的錯誤消息

Warning: Cannot modify header information - headers already sent by.....

如咱們所說的, 響應頭信息用一個空白行和主要內容分割. 這意味你僅能夠發送頭信息一次, 若是你的腳本有任何輸出 (即便一個在 <?php 標籤以前的空白行或空格), PHP 就會自動發送頭信息. 例如, 看一下下面這個腳本, 看起來邏輯上很正常:

Welcome to my website!<br /> <?php if($test){ echo "You're in!"; } else{ header('Location: http://www.mysite.com/someotherpage.php'); } ?> 

這個腳本判斷 $test 是否爲 true, 若是不是則使用 Location 頭重定向訪問者. 看到問題所在了嗎? ‘Welcome…’ 文字始終會發送出去, 因此默認的頭信息會自動被髮送. 在調用 header() 時已經太晚了: 用戶只看到一條錯誤消息 (若是你把錯誤報告關掉了, 則只會看到 ‘Welcome…’ 文字), 而不是被重定向

基本上有兩種解決方法. 第一個就是重寫代碼

<?php if($test){ echo 'Welcome to my website<br />You're in!'; } else{ header('Location: http://www.mysite.com/someotherpage.php'); } ?> 

第二個就是使用輸出緩衝, 這個解決方法更爲優雅易用. 在咱們上面的例子中, 重寫代碼並不困難, 可是試想一下若是有不少 HTML 須要移動位置 - 這樣作就會很麻煩, 也會讓咱們的代碼更難追蹤. 雖然咱們第一個示例致使了錯誤, 可是邏輯上是沒錯的. 輸出緩衝可讓你一直保留(‘緩衝’)輸出(即便是 PHP 代碼以外的 HTML)直到你明確指示了把輸出發送給瀏覽器. 這樣你就能夠隨意編寫你的代碼, 知道你指定了你須要指定的頭信息, 而後明確指示發送這些輸出. 兩個相關的函數是 ob_start()ob_flush(), ob_start() 用於打開輸出緩衝, ob_flush() 會發送緩衝了的輸出:

<?php ob_start(); //開始輸出緩衝 ?> Welcome to my website! <?php if(true){ echo "You're in!"; } else{ header('Location: http://www.mysite.com/someotherpage.php'); } ob_flush(); //輸出緩衝中的數據 ?> 

我鼓勵你讀一下全部關於輸出緩衝的函數, 很是有用. 你應當儘早的把輸出緩衝發送出去, 尤爲當你有許多東西想要發送的時候. 不然你的頁面會看起來加載的很慢, 由於全部的內容只有被組裝完畢後才發送, 而不是當可用的時候當即就被髮送出去.

提示: 第二個參數 若是你調用 header() 不止一次發送同一個頭, 這個頭的值將會是_最後_調用的 header() 中設置的值. 如,

<?php header('Some-Header: Value-1'); header('Some-Header: Value-2'); ?> 

會產生 Some-Header: Value-2 這個結果. 你能夠經過設置第二個參數來發送同一個頭兩次. 這個參數默認是 true. 若是你設置其爲 false, 那麼第二個頭值不會替換第一個, 而是兩個都被髮送. 因此下面的代碼

<?php header('Some-Header: Value-1'); header('Some-Header: Value-2', false); //不要替換第一個 ?> 

將會產生 Some-Header: Value-1, Value-2 這個結果. 你不多會用到這個, 可是知道它也不錯.

知道了 HTTP header 和 PHP 如何配合以後, 讓咱們來看一些更爲具體的例子.

PHP header(): 一些例子

提示: 下面這個代碼片段都是截取自完整的工做代碼. 當你在本身的程序中包含他們的時候, 記得定義全部你本身的變量, 賦給他們默認值, 以及遵循其餘最佳實踐.

使用 Location 頭重定向

咱們已經在上面看到過幾回了: 它會重定向瀏覽器.

<?php header('Location: http/www.mysite.com/new_location.html'); ?> 

雖然你給它一個相對 URL 沒準也能工做, 可是根據 HTTP 規範, 你真的應該使用一個絕對 URL.

一個容易犯的錯誤就是在使用了 Location header 以後不當即使用 exit 以結束執行 (你可能不是老是想要結束執行, 可是大部分時間是的). 之因此這是一個錯誤是由於 PHP 代碼會繼續執行, 即便用戶已經被重定向到新的 URL. 在最好的狀況下, 這會沒必要要的使用系統資源. 在最壞的狀況下, 你可能會執行一些讓本身後悔的操做. 看一下下面的代碼:

<?php //重定向訪問級別低於 4 的用戶 if (check_access_level($username) < 4){ header('Location: http://www.mysite.com/someotherpage.php'); } //向高於訪問級別 4 的用戶發送祕密郵件 mail_secret_code($username); echo 'The secret email is on its way!'; ?> 

未受權用戶的確被重定向了, 可是由於代碼會繼續執行, 他們一樣會收到郵件. 爲了不這種狀況, 針對已受權用戶的代碼能夠寫到 else{} 聲明中, 可是直接在 header() 後面使用 exit 來結束代碼執行會更爲乾淨容易一些.

<?php //重定向訪問級別低於 4 的用戶 if (check_access_level($username) < 4){ header('Location: http://www.mysite.com/someotherpage.php'); exit; //中止代碼執行 } //向高於訪問級別 4 的用戶發送祕密郵件 mail_secret_code($username); echo 'The secret email is on its way!'; ?> 

使用 Refresh 頭重定向

RefreshLocation 同樣能夠重定向用戶, 可是你能夠延遲重定向. 例如, 下面的代碼會在顯示當前頁面 10 秒鐘後重定向用戶到新的頁面:

<?php header('Refresh: 10; url=http://www.mysite.com/otherpage.php'); echo 'You will be redirected in 10 seconds'; ?> 

另外一個常見的用途就是經過重複的’重定向’一個頁面到它自身來強制更新頁面 (參見上面的第二個 ‘對話’). 例如, 這裏是一個簡單的例子, 頁面會從 10 開始向下數, 每一個數字之間有 3 秒間隔:

<?php if(!isset($_GET['n'])){ $_GET['n'] = 10; } if($_GET['n'] > 0){ header('Refresh: 3; url=' . $_SERVER['PHP_SELF'].'?n=' . ($_GET['n']-1) ); echo $_GET['n']; } else{ echo 'BLAST OFF!'; } ?> 

提示: 若是刷新時間設置成 0, 則 Refresh 頭實際上和 Location 頭徹底同樣

使用 Content-Type 頭來提供不一樣類型的文件以及生成動態內容

服務器用 Content-Type 頭告訴瀏覽器本身將要發送什麼類型的數據. 使用這個頭信息, 你可讓 PHP 腳本輸出任何類型的文件, 從純文本文件到圖片文件到 zip 文件等等. 下面的表格列舉了最經常使用的一個 MIME 類型:

經常使用 MIME 類型:

類型 描述
text/html HTML (PHP 默認)
text/plain 純文本
image/gif GIF 圖片
image/jpeg JPEG 圖片
image/png PNG 圖片
video/mpeg MPEG 視頻
audio/wav WAV 音頻
audio/mpeg MP3 音頻
video/mov mov 視頻
video/quicktime Quicktime 視頻
video/x-ms-wmv Windows WMV 視頻
audio/x-ms-wma Windows WMA 音頻
audio/x-realaudio RealPlayer 音頻/視頻 (.rm)
audio/x-pn-realaudio RealPlayer 音頻/視頻 (.ram)
video/x-msvideo ms 視頻
video/avi AVI 視頻
application/pdf PDF 文檔
application/msword MS Word .doc 文件
application/zip Zip 文件
application/octet-stream 其餘. 數據. 用於強制下載或使用應用打開.*
x-foo/x-bar 其餘. 數據. 用於強制下載或使用應用打開.*

你能夠用此來作一些有趣的事情. 好比, 你可能想要向用戶發用一個預先格式化過的文本文件, 而不是 HTML:

<?php header('Content-Type: text/plain'); echo $plain_text_content; ?> 

另或者你想要提示用戶下載文件, 而不是在瀏覽器中查看它. 使用 Content-Disposition 頭, 這很容易, 你甚至能夠推薦一個文件名給用戶:

<?php header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; ' .'filename="plain_text_file.txt"'); echo $plain_text_content; ?> 

另或者你須要提供文件文件, 可是又但願隱藏文件的真實路徑和名字, 而且只讓已登陸的用戶下載:

<?php if($b_is_logged_in){ header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; ' .'filename="'.$different_filename.'"'); readfile('/path/to/files/' . $filename); } else{ echo 'You are not authorized to view this file'; } ?> 

又或者你已經使用 PHP 的圖片函數動態生成了一個圖片, 想要展現給用戶. 你能夠建立一個 build_image.php 文件, 像這樣

<?php //生成圖片, 而後 header('Content-Type: image/jpeg'); imagejpeg($image_resouce); ?> 

提示: 小心 magic_quotes! PHP 會自動使用反斜槓轉移特殊字符, 這一開始看起來是個好主意, 可是大多數好的程序員認爲 (a) 這會鼓勵不去驗證輸入的粗心代碼, 而且 (b) 在良好的代碼中會產生本不應有 (若是 magic_quote 關閉) 的麻煩. 其中一個麻煩就是二進制數據被破壞. 在上面這個例子中, 若是 magic_quotes_runtime被啓用, 則 readfile() 輸出的數據可能被添加反斜槓, 致使發送給用戶的文件被破壞. 完美狀況下, 你應該在 php.ini 文件中關閉 magic_quotes_runtime 選項, 可是若是你沒有權限訪問這個配置文件, 你可使用 set_magic_quotes_runtime() 函數 (給它傳個數字 0) 關閉它.

使人高興的是, 最近的一次 PHP 開發者會議顯示, 在將來版本(6+) 的 PHP 中 magic quotes 會被棄用. 可是在全部人升級到這個版本的 PHP 以前, 記住這個致使的問題會節省你不少麻煩和疑問.

你能夠在 URL 中傳遞生成圖片所需的參數, 而後使用 $_GET 獲取它們. 而後在另外一個頁面, 你可使用 img 標籤來包含這個圖片:

<img src="build_image.php<?php echo "?$user_id&amp;$caption"; ?>"> 

可用的地方几乎講不完. 你 PHP 變成越多, 越會發現 Content-Type 頭真的是你的好朋友

提示: 瀏覽器處理各式 MIME類型 的_預期_方式以及_實際_方式可能並不一致 (尤爲是 Internet Explorer), 因此你最好是在你須要支持的瀏覽器中測試一下. PHP 參考中的用戶評論有許多關於此的技巧.

防止頁面緩存

PHP 頁面一般會生成很是動態的內容, 爲了防止用戶由於頁面緩存而錯過了更新過的頁面, 告訴瀏覽器不要緩存特定的頁面一般很是有用. 下面的代碼在可能會訪問你網站的瀏覽器中工做的很好:

<?php header('Cache-Control: no-cache, no-store, must-revalidate'); //HTTP/1.1 header('Expires: Sun, 01 Jul 2005 00:00:00 GMT'); header('Pragma: no-cache'); //HTTP/1.0 ?> 

Expires 頭能夠是任何已通過去的日期. 對於 MIME 類型, 瀏覽器 (尤爲是較老的) 可能不會老是正確的理解你的緩存指示 (雖然大部分現代瀏覽器會).

其餘應用

還有另一個可使用頭信息的地方, 好比設置 HTTP 響應碼, 或者執行 HTTP 認證 (若是你做爲 Apache 模塊來使用 PHP 的話). 如今, 你瞭解了 header() 如何工做及怎麼使用它, 你能夠用它作你以前想都沒想到的許多事情了.

PHP 中的請求頭信息

咱們講了怎麼使用響應頭信息了. 咱們還能夠從瀏覽器發給服務器的請求頭信息中獲取不少信息. 有兩種方法來獲取. 第一, 許多 [$_SERVER數組][server]中的值都是由傳來的請求頭信息決定的. 第二, 若是 PHP 是做爲 Apache 模塊使用的, apache_request_headers() 會返回一個包含全部請求頭信息的數組 (甚至那些不在 $_SERVER 中的).

安全第一: 不要信任請求頭信息

由於請求頭信息發自瀏覽器, 瀏覽器又能夠在客戶端被控制, 因此你永遠不要信任來自請求頭, 又和你站點安全緊密相關的頭信息. 一個很好的例子就是 $_SERVER['HTTP_REFERER']變量, 這個變量應該包含一個用戶轉自的源 URL. 一個新手的常見錯誤就是認爲他們可使用這個來確保用戶只會經過特定路徑來訪問頁面, 所以他們便無需關心服務器端的數據驗證. 例如, 看看下面的代碼, 它試着去確保數據是從一個特定的頁面發送過來的, 而不是從另外一個站點

<?php if($_SERVER['HTTP_REFERER'] != 'http://www.mysite.com/myform.html'){ header('Refresh: 5; url=http://www.mysite.com/myform.html'); echo 'You must use the form on my site...redirecting now.'; } else{ insert_data($_POST['var1'], $_POST['var2']); } ?> 

這或許會阻止那些不是很精通的黑客經過他的瀏覽器提交一個自定義的表單來提交數據, 可是任何一個稍微高深一些的黑客均可以經過使用 telnet 來提交數據, 包括請求頭信息

Referer: http://www.mysite.com/myform.html

而後輕易的躲過這層保護機制. 這裏所要講的重點是: 使用 HTTP 請求頭信息來統計一些數據以便提供更好的用戶體驗 - 大部分的請求頭信息都是發自真實的瀏覽器並且能夠被信任…可是不要在有關安全的問題上依賴任何請求 header

使用 HTTP 請求頭信息

你能夠用它作幾件事. 使用 $_SERVER['HTTP_USER_AGENT']你能夠探測用戶生成他使用的什麼瀏覽器. 你能夠檢查 $_SERVER['HTTP_ACCEPT_LANGUAGE'] (可能要配合 $_SERVER['HTTP_ACCEPT_CHARSET'] 和一些 IP 地理位置 ) 來決定向用戶展現什麼語言. 雖然 $_SERVER['HTTP_REFERER'] 對於安全目的並不能被依賴, 可是能夠用來統計你網站的流量, 或者根據用戶的訪問路徑來定製顯示內容. 若是由於某些緣由你想要操做原始的請求字符串, 你可使用 $_SERVER['QUERY_STRING']. 查看 $_SERVER['REQUEST_METHOD'] 能夠知道你的頁面是經過 GET 仍是 POST 方法訪問的. 還有不少能夠幫助你作許多有創意的事情的信息等着你去發現.

HTML meta 標籤中的 HTTP 頭信息 equivalents(對應物)

頗有可能在閱讀本文以前, 你已經用過下面的 HTML meta 標籤重定向用戶了:

<meta http-equiv="refresh" content="0;http://www.mysite.com/somepage.html" /> 

看起來很熟悉? ‘http-equiv’ meta 標籤即 HTTP 響應頭的’對應物’, 引入它們是爲了讓沒有服務器端編程能力的人在寫 HTML 頁面的時候也能使用強大的頭信息功能. 使用這些 meta 標籤很簡單: 它們能夠被放在文檔 <head> 中的任何地方, http-equiv 屬性包含頭名, content 屬性包含頭值.

我發現這些 meta 標籤最開始也會和 HTTP 頭同樣讓人困惑, 可是如今它們在你看來應該很簡單了. 雖然我更喜歡使用 PHP 的 header() 函數, 可是 meta 標籤的 HTTP equivalents 對於像指定字符集這樣的事情會更順手一些. 好比, 我常常在 HTML 頁面中使用 (有時候 PHP 頁面中也會用到):

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 

提示: 使用 meta 標籤來指定頭信息並不被一致的支持, 因此一般來說使用頭信息自己會更加安全和快速. 另外很明顯, 還有一些頭的名值對並不能用 meta equivalents 來指定: 在真正的頭信息被髮送, 瀏覽器已經把文檔讀取爲 HTML 以後, 你是不能再去設置 Content-Typeimage/png 的 ;-)

結語

如今咱們講完了, 你應該對 HTTP 的工做原理以及如何使用響應請求頭信息以及如何把它們應用到本身的代碼中有了很好的認識. 這些知識也會讓你在 web 應用的效率和安全方面有更審慎的思考. 我但願在你繼續編程的時候, 會發現你使用 HTTP 頭信息更加順手了, 也能經過使用它們讓你的工做更加輕鬆, 你的頁面更好了.

還有額外一點, 記住頭信息就像是詞語: 它們交流信息並請求某些操做被執行, 可是自己並不強制任何事情. 99.9% 的狀況下, 瀏覽器和服務器和諧合做, 事情發展很順利. 但記住在現實中, 是否是你會遇到一些混蛋 (黑客), 或者一些只想按照本身意願作事的東西 (Internet Explorer). web 開發從不少角度講是一個客服性質的工做, 因此你應該盡全力避免這些東西, 知足客戶的 ‘特殊須要’ :-)

相關文章
相關標籤/搜索