Http 協議php
重要性:html
1. 不管之後用 WebService 仍是用 rest 做大型架構,都離不開。chrome
WebService = Http 協議 + XML編程
Rest = HTTP 協議 + Jsonjson
各類 API , 通常也是用 http + XML/json 來實現vim
2. 以及 Ajax 的學習數組
什麼是協議 ( 就是客戶端問服務器答)瀏覽器
計算機中的協議和現實中的協議是同樣的,一式雙份/多份. 雙方/多方都聽從共同的一個規範, 這個規範就能夠稱爲協議。計算機之因此能全世界互通,協議是功不可沒,若是沒有協議,計算機各說各話,誰都聽不懂.緩存
Ftp, http, smtp, pop, tcp/ip 協議的安全
Http 協議的工做流程
客戶端 服務器(Apache/Nginx/..../iis)
0: 原始狀態,客戶端和服務器之間沒有關係
鏈接: 就是網絡上的虛擬電路,像 QQ, 是和服務器一直鏈接
1: 創建鏈接,客戶端發送請求,服務器沿着鏈接返回響應信息
2: 客戶端收到響應(html 代碼)
3: 斷開鏈接
HTTP 請求信息和響應信息的格式
GET 請求
請求:
1. 請求行
請求方法: GET/POST/HEAD/PUT/DELETE/TRACE/OPTIONS
HEAD 和 GET 基本一致,只是不返回內容,好比只是確認一個內容好比照片是否存在,不須要返回的時候,或只是檢測服務器的狀態
WEB SERVER 未必容許或者支持這些方法,不支持的話會返回 405: Method is not allowed
PUT 是用於往服務器上放資源
TRACE: 是你用了代理上網,你想看看代理有沒有修改/篡改你的HTTP請求,能夠用TRACE測試
OPTIONS: 用於查看服務器容許了那些方法
請求路徑: 也就是請求的資源,URL 的一部分
所用協議: 也就是請求全部的協議版本,基本都是 HTTP/1.1
2. 請求頭信息: 如: Host: localhost。 頭信息和主體信息以前必須有一個空行,即便沒有主體信息。
頭信息是很是豐富的,並且豐富的頭信息也是學習重點
3. 請求主體信息 (無關緊要)
響應
1. 響應行
協議版本
狀態碼: 用來反映服務器的響應結果,常見的
200 OK,服務器成功返回頁面
301/2, 永久/臨時重定向
304 Not Modified - 未修改,就是說取的是本地緩存。(原理是在服務器的響應頭信息中,有Last-Modified 和 E-Tag, 用來標誌服務端的文件是否修改,則再次請求的時候,客戶端的請求頭中會有 If-Modifed-since 和 If-None-Match 信息,來判斷是否須要從新請求
307 - 重定向中保護原有的請求數據,Get 沒有必要用, POST 會用到
404 NOT FOUND, 403 FORBIDDEN, 503 服務器內部錯誤
狀態文字:是用來描述狀態碼的,便於觀察
狀態碼 |
定義 |
1xx 報告 |
接收到請求,繼續進程,留做往後拓展 |
2xx 成功 |
操做成功接收,被理解,並被接受 |
3xx 重定向 |
爲了完成請求,必須採起進一步措施 |
4xx 客戶端出錯 |
請求的語法有錯誤或不能徹底被知足 |
5xx 服務器出錯 |
服務器沒法完成明顯有效的請求 |
2. 響應頭信息 (格式爲Key: value)
content-length: 接下來主體的長度
3. 響應主體 (可能有)
例:
HTTP/1.1 200 OK
content-type: text/html
content-length: 5
hello
Q:HTTP 協議必定要瀏覽器發送麼
A:
POST 請求
1. 在使用 POST 發送請求是,頭信息中必需要加上 content-length 信息
2. 同時須要告訴服務器 content-type: application/x-www-form-urlencoded
常見的type 見附錄
text/xml
application/json
multipart/form-data
application/x-www-form-urlencoded
要求能模擬下載,註冊,登錄
HTTP協議是超文本傳送協議(HyperText Transfer Protocol)的縮寫,它是萬維網(World Wide Web,www,也簡稱爲Web)的基礎。HTTP協議設計之初就是爲了實現Web的想法。HTTP協議位於TCP/IP協議棧的應用層。
咱們在瀏覽器的地址欄裏輸入的網站地址叫作URL(UniformResourceLocator,統一資源定位符)。就像每家每戶都有一個門牌地址同樣,每一個網頁也都有一個Internet地址。當你在瀏覽器的地址框中輸入一個URL或是單擊一個超級連接時,URL就肯定了要瀏覽的地址。瀏覽器經過超文本傳輸協議(HTTP),將Web服務器上站點的網頁代碼提取出來,並呈現出客戶端須要的網頁。
HTTP協議使用的默認端口是80,同時也支持自定義端口。
HTTP協議到如今爲止總共經歷了3個版本的演化,第一個HTTP協議誕生於1989年3月。當時Berners-Lee向 CERN(Conseil Europeen pour la Recherche Nucleaire,歐洲核能研究所)提交了一篇名爲《信息管理的一個提議》的文章。文章中提出了www網絡的構想,不過僅僅在不少方面都只關注了概念,而沒涉及到細節。
第一個HTTP協議的版本是HTTP 0.9,它的組成極其簡單,由於它只容許客戶端發送GET這一種請求,它不包含協議頭,每一個請求只有一句話,例如:
GET /index.html
因爲沒有協議頭,形成了HTTP 0.9協議只支持一種內容,即純文本。不過網頁仍然支持用HTML語言格式化,同時沒法插入圖片。因此HTTP 0.9可以支持的應用實在太有限了。一次HTTP 0.9的傳輸首先要創建一個由客戶端到Web服務器的TCP鏈接,由客戶端發起一個請求,而後由Web服務器返回頁面內容,而後鏈接會關閉。若是請求的頁面不存在,也不會返回任何錯誤碼。
HTTP 0.9的缺點是顯著的,但至少實現了第一代的Web。
HTTP協議的第二個版本是HTTP 1.0,直到HTTP 1.0成爲最重要的面向事務的應用層協議。該協議對每一次請求/響應,一樣是創建並關閉一次鏈接。其特色是簡單、易於管理,因此它符合了你們的須要,獲得了普遍的應用。
而且HTTP 1.0最顯著的變化之一是開始支持客戶端經過POST方法向Web服務器提交數據。今後客戶端與Web服務器之間再也不只能單向地獲取數據,而能夠實現交互,所以CGI(Common Gate Interface,通用網關接口)開始流行起來,Web上開始出現留言板、論壇等豐富的應用。
HTTP 1.0還有個顯著的變化是經過HTTP協議頭能夠支持各類媒體類型。今後Web上再也不僅僅是純文本的頁面,好比圖像經過<img>的HTML標記開始出現。
除了以上幾個新特性,HTTP 1.0支持長鏈接(但默認仍是使用短鏈接),緩存機制,以及身份認證。
雖然說HTTP協議的設計是向前兼容的,但目前不少瀏覽器和Web服務器都強制要求HTTP協議版本至少是1.0。
HTTP協議的第三個版本是HTTP 1.1,它就是目前使用最普遍的協議版本。這個版本的HTTP協議已經穩定了,跟HTTP 1.0相比,它新增了不少引人注目的新特性,好比Host協議頭,一個HTTP請求的頭中能夠包含一句例如:
Host: vimer.cn
今後一個Web服務器能夠支持掛載多個域名了,無需每一個域名都使用獨立IP,每一個網站可使用虛擬主機。
另外一個HTTP 1.1的新特性是支持部份內容請求/響應,這意味着當客戶端請求的數據量很大時,能夠分屢次發起請求,每次請求只要求獲取整塊數據的一部分。Web服務器也能夠分屢次響應,每次只返回整塊數據的一部分。這使得流媒體得以實現。
從HTTP 1.1開始,客戶端默認與Web 服務器創建長鏈接,這種鏈接適合Web上數據量較大的豐富應用,使得資源消耗更少。
QzHTTP就是一個支持HTTP 1.1協議的Web Server。
2.HTTP協議內容介紹
HTTP協議經過URI(Uniform Resource Identifiers,統一資源定位符)來訪問資源。根據RFC 1808的官方定義,一個完整URI的組成以下:
http://myname:mypass@www.vimer.cn:80/mydir/myfile.html?myvar=myvalue#myfrag
URI字段
表 2.1
URI部分 |
意義 |
http |
協議名稱 |
myname |
用戶名(可選) |
mypass |
密碼(可選) |
主機網絡地址 |
|
80 |
端口號(可選) |
/mydir/myfile.html |
資源路徑 |
myvar=myvalue |
查詢字符串(可選) |
myfrag |
錨點(可選) |
可見協議名稱用「://」結束,用戶名和密碼以「:」分隔,以「@」結束,端口號與主機網絡地址以「:」分隔,資源路徑與查詢字符串以「?」分隔,錨點以#開頭。
而且,只有協議名稱、主機網絡地址和資源路徑是必須包含在URI裏的。
一個更常見的例子以下:
在這裏面,http是協議,www.vimer.cn是主機網絡地址,注意末尾的/就是資源路徑,這是必須的。當咱們平時使用Web瀏覽器訪問時,只須要輸入www.vimer.cn就能夠訪問,這是因爲Web瀏覽器替咱們自動補齊了前面的http://和最後的/,Web瀏覽器發起請求時使用的URI仍是完整的,Web瀏覽器並不強制用戶輸入格式規範的URI。
HTTP協議的交互主要由請求和響應組成,請求是指客戶端發起向Web服務器請求資源的消息,而響應是Web服務器根據客戶端的請求回送給客戶端的資源消息。
發出的請求信息(Request Message)包括如下幾部分:
l 請求行,例如GET /images/logo.gif HTTP/1.1,表示從/images 目錄下請求logo.gif 這個文件。
l (請求)頭,例如Accept-Language: en
l 空行
l 可選的消息體
請求行和標題必須以<CR><LF> 做爲結尾(也就是,回車而後換行)。空行內必須只有<CR><LF>而無其餘空格。在HTTP/1.1 協議中,全部的請求頭,除Host外,都是可選的。
請求方法(Request Method)
HTTP/1.1協議中共定義了八種方法(有時也叫「動做」)來代表Request-URI指定的資源的不一樣操做方式:
l OPTIONS
返回服務器針對特定資源所支持的HTTP請求方法。也能夠利用向Web服務器發送’*’的請求來測試服務器的功能性。
l HEAD
向服務器索要與GET請求相一致的響應,只不過響應體將不會被返回。這一方法能夠在沒必要傳輸整個響應內容的狀況下,就能夠獲取包含在響應消息頭中的元信息。
l GET
向特定的資源發出請求。注意:GET方法不該當被用於產生「反作用」的操做中,例如在Web 應用程序中。其中一個緣由是GET可能會被網絡蜘蛛等隨意訪問。
l POST
向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會致使新的資源的創建和/或已有資源的修改。
l PUT
向指定資源位置上傳其最新內容。
l DELETE
刪除指定資源。
l TRACE
回顯服務器收到的請求。
l CONNECT
HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。
方法名稱是區分大小寫的。當某個請求所針對的資源不支持對應的請求方法的時候,服務器應當返回狀態碼405(Method Not Allowed);當服務器不認識或者不支持對應的請求方法的時候,應當返回狀態碼501(Not Implemented)。
HTTP服務器至少應該實現GET和HEAD方法,其餘方法都是可選的,可選方法中還有一個重要的方法是POST。固然,全部的方法支持的實現都應當符合下述的方法各自的語義定義。此外,除了上述方法,特定的HTTP服務器還可以擴展自定義的方法。
一個GET請求的示例如圖2.3所示:
圖2.3 HTTP請求
GET 表明方法名,後面的/表明資源路徑,HTTP/1.1表示協議版本。下面都是協議頭部分,常見的頭字段如表2.2所示。
HTTP協議頭字段
表2.2
頭字段 |
定義 |
Accept |
客戶端能夠處理的媒體類型(MIME-Type),按優先級排序;在一個以逗號爲分隔的列表中,能夠定義多種類型和使用通配符 |
Accept-Language |
客戶端支持的天然語言列表 |
Accept-Encoding |
客戶端支持的編碼列表 |
User-Agent |
客戶端環境類型 |
Host |
服務器端的主機地址 |
Connection |
鏈接類型,默認爲Keep-Alive |
HTTP協議是Web內容的容器。一個示例HTTP響應如圖2.4所示:
圖2.4 HTTP響應
每一個響應由HTTP協議頭和Web內容構成。Web服務器收到一個請求,就會馬上解釋請求中所用到的方法,並開始處理應答。服務器的響應消息也包含頭字段形式的協議頭。響應的格式在RFC2616中定義以下:
Status-Line*
(( general-header)| response-header | entity-header)CRLF)
CRLF
[ message-body ]
響應消息的第一行是狀態行(Stauts-Line),由協議版本以及數字狀態碼和相關的文本短語組成,各部分間用空格符隔開,除了最後的回車或換行外,中間不容許有回車換行。
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
狀態碼是試圖理解和知足請求的三位數字的整數碼, 緣由短語(Reason-Phrase)是爲了給出的關於狀態碼的文本描述。狀態碼用於控制條件,而緣由短語(Reason-Phrase)是讓用戶便於閱讀。客戶端不須要檢查和顯示緣由短語。
狀態碼的第一位數字定義響應類型。後兩位數字沒有任何分類角色。第一位數字有五種值,如表2.3所示。
HTTP響應狀態碼
表 2.3
狀態碼 |
定義 |
1xx 報告 |
接收到請求,繼續進程 |
2xx 成功 |
步驟成功接收,被理解,並被接受 |
3xx 重定向 |
爲了完成請求,必須採起進一步措施 |
4xx 客戶端出錯 |
請求包括錯的順序或不能完成 |
5xx 服務器出錯 |
服務器沒法完成顯然有效的請求 |
下面列舉了爲HTTP/1.1定義的狀態碼值,和對應的緣由短語(Reason-Phrase)的例子。
l 客戶端錯誤
「100″ : Continue 繼續
「101″ : witching Protocols 交換協議
l 成功
「200″ : OK
「201″ : Created 已建立
「202″ : Accepted 接收
「203″ : Non-Authoritative Information 非認證信息
「204″ : No Content 無內容
「205″ : Reset Content 重置內容
「206″ : Partial Content 部份內容
l 重定向
「300″ : Multiple Choices 多路選擇
「301″ : Moved Permanently 永久轉移
「302″ : Found 暫時轉移
「303″ : See Other 參見其它
「304″ : Not Modified 未修改
「305″ : Use Proxy 使用代理
「307″ : Temporary Redirect
l 客戶方錯誤
「400″ : Bad Request 錯誤請求
「401″ : Unauthorized 未認證
「402″ : Payment Required 須要付費
「403″ : Forbidden 禁止
「404″ : Not Found 未找到
「405″ : Method Not Allowed 方法不容許
「406″ : Not Acceptable 不接受
「407″ : Proxy Authentication Required 須要代理認證
「408″ : Request Time-out 請求超時
「409″ : Conflict 衝突
「410″ : Gone 失敗
「411″ : Length Required 須要長度
「412″ : Precondition Failed 條件失敗
「413″ : Request Entity Too Large 請求實體太大
「414″ : Request-URI Too Large 請求URI太長
「415″ : Unsupported Media Type 不支持媒體類型
「416″ : Requested range not satisfiable
「417″ : Expectation Failed
l 服務器錯誤
「500″ : Internal Server Error 服務器內部錯誤
「501″ : Not Implemented 未實現
「502″ : Bad Gateway 網關失敗
「503″ : Service Unavailable
「504″ : Gateway Time-out 網關超時
「505″ : HTTP Version not supported HTTP版本不支持
HTTP狀態碼是可擴展的。HTTP應用程序不須要理解全部已註冊狀態碼的含義,儘管那樣的理解顯而易見是很合算的。可是,應用程序必須瞭解由第一位數字指定的狀態碼的類型,任何未被識別的響應應被看做是該類型的x00狀態,有一個例外就是未被識別的響應不能緩存。例如,若是客戶端收到一個未被識別的狀態碼431,則能夠安全的假定請求有錯,而且它會對待此響應就像它接收了一個狀態碼是400的響應。在這種狀況下,用戶代理(user agent)應當把實體和響應一塊兒提交給用戶,由於實體極可能包括人可讀的關於解釋不正常狀態的信息。報文最後是實體信息,即客戶請求獲得的HTTP服務器上的資源內容
這應該是最多見的 POST 提交數據的方式了。瀏覽器的原生 form 表單,若是不設置 enctype 屬性,那麼最終就會以 application/x-www-form-urlencoded 方式提交數據。請求相似於下面這樣(無關的請求頭在本文中都省略掉了):
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
首先,Content-Type 被指定爲 application/x-www-form-urlencoded;其次,提交的數據按照 key1=val1&key2=val2 的方式進行編碼,key 和 val 都進行了 URL 轉碼。大部分服務端語言都對這種方式有很好的支持。例如 PHP 中,$_POST['title'] 能夠獲取到 title 的值,$_POST['sub'] 能夠獲得 sub 數組。
不少時候,咱們用 Ajax 提交數據時,也是使用這種方式。例如 JQuery 和 QWrap 的 Ajax,Content-Type 默認值都是「application/x-www-form-urlencoded;charset=utf-8」。
multipart/form-data
這又是一個常見的 POST 數據提交的方式。咱們使用表單上傳文件時,必須讓 form 的 enctyped 等於這個值。直接來看一個請求示例:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
這個例子稍微複雜點。首先生成了一個 boundary 用於分割不一樣的字段,爲了不與正文內容重複,boundary 很長很複雜。而後 Content-Type 裏指明瞭數據是以 mutipart/form-data 來編碼,本次請求的 boundary 是什麼內容。消息主體裏按照字段個數又分爲多個結構相似的部分,每部分都是以 --boundary 開始,緊接着內容描述信息,而後是回車,最後是字段具體內容(文本或二進制)。若是傳輸的是文件,還要包含文件名和文件類型信息。消息主體最後以 --boundary-- 標示結束。關於 mutipart/form-data 的詳細定義,請前往 rfc1867 查看。
這種方式通常用來上傳文件,各大服務端語言對它也有着良好的支持。
上面提到的這兩種 POST 數據的方式,都是瀏覽器原生支持的,並且現階段原生 form 表單也只支持這兩種方式。可是隨着愈來愈多的 Web 站點,尤爲是 WebApp,所有使用 Ajax 進行數據交互以後,咱們徹底能夠定義新的數據提交方式,給開發帶來更多便利。
application/json
application/json 這個 Content-Type 做爲響應頭你們確定不陌生。實際上,如今愈來愈多的人把它做爲請求頭,用來告訴服務端消息主體是序列化後的 JSON 字符串。因爲 JSON 規範的流行,除了低版本 IE 以外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會趕上什麼麻煩。
JSON 格式支持比鍵值對複雜得多的結構化數據,這一點也頗有用。記得我幾年前作一個項目時,須要提交的數據層次很是深,我就是把數據 JSON 序列化以後來提交的。不過當時我是把 JSON 字符串做爲 val,仍然放在鍵值對裏,以 x-www-form-urlencoded 方式提交。
Google 的 AngularJS 中的 Ajax 功能,默認就是提交 JSON 字符串。例以下面這段代碼:
var data = {'title':'test', 'sub' : [1,2,3]};
$http.post(url, data).success(function(result) {
...
});
最終發送的請求是:
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"title":"test","sub":[1,2,3]}
這種方案,能夠方便的提交複雜的結構化數據,特別適合 RESTful 的接口。各大抓包工具如 Chrome 自帶的開發者工具、Firebug、Fiddler,都會以樹形結構展現 JSON 數據,很是友好。但也有些服務端語言尚未支持這種方式,例如 php 就沒法經過 $_POST 對象從上面的請求中得到內容。這時候,須要本身動手處理下:在請求頭中 Content-Type 爲 application/json 時,從 php://input 裏得到原始輸入流,再 json_decode 成對象。一些 php 框架已經開始這麼作了。
固然 AngularJS 也能夠配置爲使用 x-www-form-urlencoded 方式提交數據。若有須要,能夠參考這篇文章。
text/xml 個人博客以前提到過 XML-RPC(XML Remote Procedure Call)。它是一種使用 HTTP 做爲傳輸協議,XML 做爲編碼方式的遠程調用規範。典型的 XML-RPC 請求是這樣的: POST http://www.example.com HTTP/1.1 Content-Type: text/xml <!--?xml version="1.0"?--> <methodcall> <methodname>examples.getStateName</methodname> <params> <param> <value><i4>41</i4></value> </params> </methodcall> XML-RPC 協議簡單、功可以用,各類語言的實現都有。它的使用也很普遍,如 WordPress 的 XML-RPC Api,搜索引擎的 ping 服務等等。JavaScript 中,也有現成的庫支持以這種方式進行數據交互,能很好的支持已有的 XML-RPC 服務。不過,我我的以爲 XML 結構仍是過於臃腫,通常場景用 JSON 會更靈活方便。