一、http概述 超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最為廣泛的一種網路協議。所有的WWW文件都必須遵守這個標準。設計HTTP最初的目的是為了提供一種發佈和接收HTML頁面的方法。 HTTP是一個客戶端和伺服器端請求和應答的標準(TCP)。 ...
一、http概述
超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最為廣泛的一種網路協議。所有的WWW文件都必須遵守這個標準。設計HTTP最初的目的是為了提供一種發佈和接收HTML頁面的方法。
HTTP是一個客戶端和伺服器端請求和應答的標準(TCP)。客戶端是終端用戶,伺服器端是網站。通過使用Web瀏覽器、網路爬蟲或者其它的工具,客戶端發起一個到伺服器上指定埠(預設埠為80)的HTTP請求。
HTTP就是一個通信規則,通信規則規定了客戶端發送給伺服器的內容格式,也規定了伺服器發送給客戶端的內容格式。客戶端發送給伺服器的格式叫“請求協議”;伺服器發送給客戶端的格式叫“響應協議”。
特點:
- HTTP叫超文本傳輸協議,基於請求/響應模式
- HTTP是無狀態協議
通過HTTP或者HTTPS協議請求的資源由統一資源標示符(Uniform Resource Identifiers)(或者,更準確一些,URLs)來標識。
URL:統一資源定位符,就是一個網址:協議名://功能變數名稱:埠/路徑,例如:http://www.oldboy.cn:80/index.html
二、http工作流程
HTTP協議採用了請求/響應模型。客戶端向伺服器發送一個請求,請求頭包含請求的方法、URL、協議版本、以及包含請求修飾符、客戶信息和內容的類似於MIME的消息結構。伺服器以一個狀態行作為響應,響應的內容包括消息協議的版本,成功或者錯誤編碼加上包含伺服器信息、實體元信息以及可能的實體內容。
通常HTTP消息包括客戶機向伺服器的請求消息和伺服器向客戶機的響應消息。這兩種類型的消息由一個起始行,一個或者多個頭域,一個指示頭域結束的空行和可選的消息體組成。HTTP的頭域包括通用頭,請求頭,響應頭和實體頭四個部分。每個頭域由一個功能變數名稱,冒號(:)和域值三部分組成。功能變數名稱是大小寫無關的,域值前可以添加任何數量的空格符,頭域可以被擴展為多行,在每行開始處,使用至少一個空格或製表符。 1. 請求協議請求協議的格式如下:
請求首行; // 請求方式 請求路徑 協議和版本,例如:GET /index.html HTTP/1.1 請求頭信息;// 請求頭名稱:請求頭內容,即為key:value格式,例如:Host:localhost 空行; // 用來與請求體分隔開 請求體。 // GET沒有請求體,只有POST有請求體。
瀏覽器發送給伺服器的內容就這個格式的,如果不是這個格式伺服器將無法解讀!在HTTP協議中,請求有很多請求方法,其中最為常用的就是GET和POST。
1.1 GET請求
HTTP預設的請求方法就是GET
- 沒有請求體
- 數據長度沒有限制,但實際上不同的瀏覽器廠商會對數據長度進行限制,詳見此篇博文
- GET請求數據會暴露在瀏覽器的地址欄中
GET請求常用的操作:
- 在瀏覽器的地址欄中直接給出URL,那麼就一定是GET請求
- 點擊頁面上的超鏈接也一定是GET請求
- 提交表單時,表單預設使用GET請求,但可以設置為POST
1 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 2 Accept-Encoding:gzip, deflate, sdch 3 Accept-Language:zh-CN,zh;q=0.8 4 Cache-Control:no-cache 5 Connection:keep-alive 6 Cookie:csrftoken=z5H43ZwARx7AIJ82OEizBOWbsAQA2LPk 7 Host:127.0.0.1:8090 8 Pragma:no-cache 9 Upgrade-Insecure-Requests:1 10 User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.89 Safari/537.36 11 Name 12 login/ 13 requests ❘ 737 B transferred ❘ Finish: 5 ms ❘ DOMContentLoaded: 14 ms ❘ Load: 14 ms
- GET 127.0.0.1:8090/login HTTP/1.1:GET請求,請求伺服器路徑為 127.0.0.1:8090/login ,協議為1.1;
- Host:localhost:請求的主機名為localhost;
- *User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0:與瀏覽器和OS相關的信息。有些網站會顯示用戶的系統版本和瀏覽器版本信息,這都是通過獲取User-Agent頭信息而來的;
- 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:客戶端支持的編碼;
- Connection: keep-alive:客戶端支持的鏈接方式,保持一段時間鏈接,預設為3000ms;
- Cookie: JSESSIONID=369766FDF6220F7803433C0B2DE36D98:因為不是第一次訪問這個地址,所以會在請求中把上一次伺服器響應中發送過來的Cookie在請求中一併發送去過;這個Cookie的名字為JSESSIONID。
HTTP無狀態:無狀態是指協議對於事務處理沒有記憶能力,伺服器不知道客戶端是什麼狀態。從另一方面講,打開一個伺服器上的網頁 和你之前打開這個伺服器上的網頁之間沒有任何聯繫 如果你要實現一個購物車,需要藉助於Cookie或Session或伺服器端API(如NSAPI and ISAPI)記錄這些信息,請求伺服器結算頁面時同時將這些信息提交到伺服器 當你登錄到一個網站時,你的登錄狀態也是由Cookie或Session來“記憶”的,因為伺服器並不知道你是否登錄 優點:伺服器不用為每個客戶端連接分配記憶體來記憶大量狀態,也不用在客戶端失去連接時去清理記憶體,以更高效地去處理WEB業務 缺點:客戶端的每次請求都需要攜帶相應參數,伺服器需要處理這些參數 容易犯的誤區: 1、HTTP是一個無狀態的面向連接的協議,無狀態不代表HTTP不能保持TCP連接,更不能代表HTTP使用的是UDP協議(無連接) 2、從HTTP/1.1起,預設都開啟了Keep-Alive,保持連接特性,簡單地說,當一個網頁打開完成後,客戶端和伺服器之間用於傳輸 HTTP數據的TCP連接不會關閉,如果客戶端再次訪問這個伺服器上的網頁,會繼續使用這一條已經建立的連接 3、Keep-Alive不會永久保持連接,它有一個保持時間,可以在不同的伺服器軟體(如Apache)中設定這個時間註意點
1.2 POST請求
- 數據不會出現在地址欄中
- 數據的大小沒有上限
- 有請求體
- 請求體中如果存在中文,肯定會使用URL編碼
username=%E5%BC%A0%E4%B8%89&password=123 我們都知道Http協議中參數的傳輸是"key=value"這種鍵值對形式的,如果要傳多個參數就需要用“&”符號對鍵值對進行分割。如"name1=value1&name2=value2",這樣在服務端在收到這種字元串的時候,會用“&”分割出每一個參數,然後再用“=”來分割出參數值。 針對“name1=value1&name2=value2”我們來說一下客戶端到服務端的概念上解析過程: 上述字元串在電腦中用ASCII嗎表示為: 6E616D6531 3D 76616C756531 26 6E616D6532 3D 76616C756532。 6E616D6531:name1 3D:= 76616C756531:value1 26:& 6E616D6532:name2 3D:= 76616C756532:value2 服務端在接收到該數據後就可以遍歷該位元組流,首先一個位元組一個位元組的吃,當吃到3D這位元組後,服務端就知道前面吃得位元組表示一個key,再向後吃,如果遇到26,說明從剛纔吃的3D到26位元組之間的是上一個key的value,以此類推就可以解析出客戶端傳過來的參數。 現在有這樣一個問題,如果我的參數值中就包含=或&這種特殊字元的時候該怎麼辦。 比如說“name1=value1”,其中value1的值是“va&lu=e1”字元串,那麼實際在傳輸過程中就會變成這樣“name1=va&lu=e1”。我們的本意是就只有一個鍵值對,但是服務端會解析成兩個鍵值對,這樣就產生了歧義。 如何解決上述問題帶來的歧義呢?解決的辦法就是對參數進行URL編碼 URL編碼只是簡單的在特殊字元的各個位元組前加上%,例如,我們對上述會產生歧義的字元進行URL編碼後結果:“name1=va%26lu%3D”,這樣服務端會把緊跟在“%”後的位元組當成普通的位元組,就是不會把它當成各個參數或鍵值對的分隔符。為何需要URL編碼
使用表單可以發POST請求,但表單預設是GET
1 <form action="" method="post"> 2 關鍵字:<input type="text" name="keyword"/> 3 <input type="submit" value="提交"/> 4 </form>
1 Request Headers 2 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 3 Accept-Encoding:gzip, deflate 4 Accept-Language:zh-CN,zh;q=0.8 5 Cache-Control:no-cache 6 Connection:keep-alive 7 Content-Length:13 8 Content-Type:application/x-www-form-urlencoded 9 Cookie:csrftoken=z5H43ZwARx7AIJ82OEizBOWbsAQA2LPk 10 Host:127.0.0.1:8090 11 Origin:http://127.0.0.1:8090 12 Pragma:no-cache 13 Referer:http://127.0.0.1:8090/login/ 14 Upgrade-Insecure-Requests:1 15 User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) 16 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.89 Safari/537.36 17 18 Form Data 19 username:yuan
POST請求是可以有體的,而GET請求不能有請求體。
- Referer: http://localhost:8080/hello/index.jsp:請求來自哪個頁面,例如你在百度上點擊鏈接到了這裡,那麼Referer:http://www.baidu.com;如果你是在瀏覽器的地址欄中直接輸入的地址,那麼就沒有Referer這個請求頭了;
- Content-Type: application/x-www-form-urlencoded:表單的數據類型,說明會使用url格式編碼數據;url編碼的數據都是以“%”為首碼,後面跟隨兩位的16進位。
- Content-Length:13:請求體的長度,這裡表示13個位元組。
- keyword=hello:請求體內容!hello是在表單中輸入的數據,keyword是表單欄位的名字。
Referer請求頭是比較有用的一個請求頭,它可以用來做統計工作,也可以用來做防盜鏈。
統計工作:我公司網站在百度上做了廣告,但不知道在百度上做廣告對我們網站的訪問量是否有影響,那麼可以對每個請求中的Referer進行分析,如果Referer為百度的很多,那麼說明用戶都是通過百度找到我們公司網站的。
防盜鏈:我公司網站上有一個下載鏈接,而其他網站盜鏈了這個地址,例如在我網站上的index.html頁面中有一個鏈接,點擊即可下載JDK7.0,但有某個人的微博中盜鏈了這個資源,它也有一個鏈接指向我們網站的JDK7.0,
也就是說登錄它的微博,點擊鏈接就可以從我網站上下載JDK7.0,這導致我們網站的廣告沒有看,但下載的卻是我網站的資源。這時可以使用Referer進行防盜鏈,在資源被下載之前,我們對Referer進行判斷,如果請求來自本網站,那麼允許下載,
如果非本網站,先跳轉到本網站看廣告,然後再允許下載。
2. 響應協議
響應協議的格式如下:
- 響應首行;
- 響應頭信息;
- 空行;
- 響應體
響應內容是由伺服器發送給瀏覽器的內容,瀏覽器會根據響應內容來顯示。遇到<img src=''>會開一個新的線程載入,所以有時圖片多的話,內容會先顯示出來,然後圖片才一張張載入出來。
1 Request URL:http://127.0.0.1:8090/login/ 2 Request Method:GET 3 Status Code:200 OK 4 Remote Address:127.0.0.1:8090 5 Response Headers 6 view source 7 Content-Type:text/html; charset=utf-8 8 Date:Wed, 26 Oct 2016 06:48:50 GMT 9 Server:WSGIServer/0.2 CPython/3.5.2 10 X-Frame-Options:SAMEORIGIN 11 12 <!DOCTYPE html> 13 <html lang="en"> 14 <head> 15 <meta charset="UTF-8"> 16 <title>Title</title> 17 </head> 18 <body> 19 <form action="/login/" method="post"> 20 用戶名:<input type="text" name="username"/> 21 <input type="submit" value="提交"/> 22 </form> 23 </body> 24 </html>
- HTTP/1.1 200 OK:響應協議為HTTP1.1,狀態碼為200,表示請求成功,OK是對狀態碼的解釋;
- Server:WSGIServer/0.2 CPython/3.5.2:伺服器的版本信息;
- Content-Type: text/html;charset=UTF-8:響應體使用的編碼為UTF-8;
- Content-Length: 724:響應體為724位元組;
- Set-Cookie: JSESSIONID=C97E2B4C55553EAB46079A4F263435A4; Path=/hello:響應給客戶端的Cookie;
- Date: Wed, 25 Sep 2012 04:15:03 GMT:響應的時間,這可能會有8小時的時區差;
2.2 狀態碼
響應頭對瀏覽器來說很重要,它說明瞭響應的真正含義。例如200表示響應成功了,302表示重定向,這說明瀏覽器需要再發一個新的請求。
消息 | 描述 |
---|---|
100 Continue | 伺服器僅接收到部分請求,但是一旦伺服器並沒有拒絕該請求,客戶端應該繼續發送其餘的請求。 |
101 Switching Protocols | 伺服器轉換協議:伺服器將遵從客戶的請求轉換到另外一種協議。 |
消息 | 描述 |
---|---|
200 OK | 請求成功(其後是對GET和POST請求的應答文檔。) |
201 Created | 請求被創建完成,同時新的資源被創建。 |
202 Accepted | 供處理的請求已被接受,但是處理未完成。 |
203 Non-authoritative Information | 文檔已經正常地返回,但一些應答頭可能不正確,因為使用的是文檔的拷貝。 |
204 No Content | 沒有新文檔。瀏覽器應該繼續顯示原來的文檔。如果用戶定期地刷新頁面,而Servlet可以確定用戶文檔足夠新,這個狀態代碼是很有用的。 |
205 Reset Content | 沒有新文檔。但瀏覽器應該重置它所顯示的內容。用來強制瀏覽器清除表單輸入內容。 |
206 Partial Content | 客戶發送了一個帶有Range頭的GET請求,伺服器完成了它。 |
消息 | 描述 |
---|---|
300 Multiple Choices | 多重選擇。鏈接列表。用戶可以選擇某鏈接到達目的地。最多允許五個地址。 |
301 Moved Permanently | 所請求的頁面已經轉移至新的url。 |
302 Found | 所請求的頁面已經臨時轉移至新的url。 |
303 See Other | 所請求的頁面可在別的url下被找到。 |
304 Not Modified | 未按預期修改文檔。客戶端有緩衝的文檔併發出了一個條件性的請求(一般是提供If-Modified-Since頭表示客戶只想比指定日期更新的文檔)。伺服器告訴客戶,原來緩衝的文檔還可以繼續使用。 |
305 Use Proxy | 客戶請求的文檔應該通過Location頭所指明的代理伺服器提取。 |
306 Unused | 此代碼被用於前一版本。目前已不再使用,但是代碼依然被保留。 |
307 Temporary Redirect | 被請求的頁面已經臨時移至新的url。 |
304響應 當用戶第一次請求index.html時,伺服器會添加一個名為Last-Modified響應頭,這個頭說明瞭index.html的最後修改時間,瀏覽器會把index.html內容,以及最後響應時間緩存下來。當用戶第二次請求index.html時,
在請求中包含一個名為If-Modified-Since請求頭,它的值就是第一次請求時伺服器通過Last-Modified響應頭髮送給瀏覽器的值,即index.html最後的修改時間,If-Modified-Since請求頭就是在告訴伺服器,我這裡瀏覽器緩存的index.html最後修改時間是這個, 您看看現在的index.html最後修改時間是不是這個,如果還是,那麼您就不用再響應這個index.html內容了,我會把緩存的內容直接顯示出來。而伺服器端會獲取If-Modified-Since值,與index.html的當前最後修改時間比對,
如果相同,伺服器會發響應碼304,表示index.html與瀏覽器上次緩存的相同,無需再次發送,瀏覽器可以顯示自己的緩存頁面,如果比對不同,那麼說明index.html已經做了修改,伺服器會響應200。
消息 | 描述 |
---|---|
400 Bad Request | 伺服器未能理解請求。 |
401 Unauthorized | 被請求的頁面需要用戶名和密碼。 |
401.1 | 登錄失敗。 |
401.2 | 伺服器配置導致登錄失敗。 |
401.3 | 由於 ACL 對資源的限制而未獲得授權。 |
401.4 | 篩選器授權失敗。 |
401.5 | ISAPI/CGI 應用程式授權失敗。 |
401.7 | 訪問被 Web 伺服器上的 URL 授權策略拒絕。這個錯誤代碼為 IIS 6.0 所專用。 |
402 Payment Required | 此代碼尚無法使用。 |
403 Forbidden | 對被請求頁面的訪問被禁止。 |
403.1 | 執行訪問被禁止。 |
403.2 | 讀訪問被禁止。 |
403.3 | 寫訪問被禁止。 |
403.4 | 要求 SSL。 |
403.5 | 要求 SSL 128。 |
403.6 | IP 地址被拒絕。 |
403.7 | 要求客戶端證書。 |
403.8 | 站點訪問被拒絕。 |
403.9 | 用戶數過多。 |
403.10 | 配置無效。 |
403.11 | 密碼更改。 |
403.12 | 拒絕訪問映射表。 |
403.13 | 客戶端證書被吊銷。 |
403.14 | 拒絕目錄列表。 |
403.15 | 超出客戶端訪問許可。 |
403.16 | 客戶端證書不受信任或無效。 |
403.17 | 客戶端證書已過期或尚未生效。 |
403.18 | 在當前的應用程式池中不能執行所請求的 URL。這個錯誤代碼為 IIS 6.0 所專用。 |
403.19 | 不能為這個應用程式池中的客戶端執行 CGI。這個錯誤代碼為 IIS 6.0 所專用。 |
403.20 | Passport 登錄失敗。這個錯誤代碼為 IIS 6.0 所專用。 |
404 Not Found | 伺服器無法找到被請求的頁面。 |
404.0 | (無)–沒有找到文件或目錄。 |
404.1 | 無法在所請求的埠上訪問 Web 站點。 |
404.2 | Web 服務擴展鎖定策略阻止本請求。 |
404.3 | MIME 映射策略阻止本請求。 |
405 Method Not Allowed | 請求中指定的方法不被允許。 |
406 Not Acceptable | 伺服器生成的響應無法被客戶端所接受。 |
407 Proxy Authentication Required | 用戶必須首先使用代理伺服器進行驗證,這樣請求才會被處理。 |
408 Request Timeout | 請求超出了伺服器的等待時間。 |
409 Conflict | 由於衝突,請求無法被完成。 |
410 Gone | 被請求的頁面不可用。 |
411 Length Required | "Content-Length" 未被定義。如果無此內容,伺服器不會接受請求。 |
412 Precondition Failed | 請求中的前提條件被伺服器評估為失敗。 |
413 Request Entity Too Large | 由於所請求的實體的太大,伺服器不會接受請求。 |
414 Request-url Too Long | 由於url太長,伺服器不會接受請求。當post請求被轉換為帶有很長的查詢信息的get請求時,就會發生這種情況。 |
415 Unsupported Media Type | 由於媒介類型不被支持,伺服器不會接受請求。 |
416 Requested Range Not Satisfiable | 伺服器不能滿足客戶在請求中指定的Range頭。 |
417 Expectation Failed | 執行失敗。 |
423 | 鎖定的錯誤。 |
消息 | 描述 |
---|---|
500 Internal Server Error | 請求未完成。伺服器遇到不可預知的情況。 |
500.12 | 應用程式正忙於在 Web 伺服器上重新啟動。 |
500.13 | Web 伺服器太忙。 |
500.15 | 不允許直接請求 Global.asa。 |
500.16 | UNC 授權憑據不正確。這個錯誤代碼為 IIS 6.0 所專用。 |
500.18 | URL 授權存儲不能打開。這個錯誤代碼為 IIS 6.0 所專用。 |
500.100 | 內部 ASP 錯誤。 |
501 Not Implemented | 請求未完成。伺服器不支持所請求的功能。 |
502 Bad Gateway | 請求未完成。伺服器從上游伺服器收到一個無效的響應。 |
502.1 | CGI 應用程式超時。 · |
502.2 | CGI 應用程式出錯。 |
503 Service Unavailable | 請求未完成。伺服器臨時過載或當機。 |
504 Gateway Timeout | 網關超時。 |
505 HTTP Version Not Supported | 伺服器不支持請求中指明的HTTP協議版本。 |
2.3 HTML中指定響應頭
在HTMl頁面中可以使用<meta http-equiv="" content="">來指定響應頭,例如在index.html頁面中給出<meta http-equiv="Refresh" content="3;url=http://www.baidu.com">,表示瀏覽器只會顯示index.html頁面3秒,
然後自動跳轉到http://www.baidu.com.
參考資料:
2. http://www.cnblogs.com/yuanchenqi/articles/6000358.html