HTTP1.1 基礎: 請求和響應的消息交互細節

HTTP1.1 基礎概念

HTTP/2在2015年已推出,本文主要介紹的是HTTP1.1。下面是RFC2616對HTTP1.1的描述:

The Hypertext Transfer Protocol (HTTP) is an application-level protocol for distributed, collaborative, hypermedia information systems. It is a generic, stateless, protocol which can be used for many tasks beyond its use for hypertext, such as name servers and distributed object management systems, through extension of its request methods, error codes and headers.

HTTP1.1 作爲一個應用層協議,有如下的一些特點:

  • 報文頭是約定格式的純文本,報文頭指定了方法、內容格式、緩存等meta信息;
  • 無狀態的請求響應,即當前的請求跟之前的請求無聯繫;
  • 承載在傳輸層TCP之上,HTTPS又在TCP之上增加了TLS安全層;

當前大部分網站都已經切換到HTTPS, 並且Chrome 68正式版會把所有潛在不安全的HTTP網站標記爲不安全。HTTPS是在HTTP下加入SSL/TLS安全層,增強了網絡訪問的安全性。TLS(Transport Layer Security)是SSL的v3.0升級版,已經是HTTPS的標準。HTTP和HTTPS有如下的區別:

  • HTTPS協議需要到ca申請證書,需要一定費用;
  • HTTP信息是明文傳輸,HTTPS則是具有安全性的TLS加密傳輸;
  • HTTP默認使用80端口,HTTPS默認使用是443端口;

一個典型交互場景如下:
這裏寫圖片描述

HTTP1.1 報文格式

學習網絡協議細節時,一個很重要的手段就是看RFC(Request For Comments),基本的互聯網通信協議都有在RFC裏詳細說明。下面是HTTP的RFC:

HTTP訪問從URL開始,Uniform Resource Locator (URL)的格式爲:

protocol://hostname:port/path-and-file-name
# port: server監聽的TCP port,http缺省是80
# path-and-file-name: server的文件路徑

在瀏覽器輸入URL,瀏覽器會發起一個http request,使用Chrome或者Firefox開發者工具的Network選項可以查看HTTP請求與響應頭內容。

HTTP的報文結構如下圖,左右分別是請求和響應報文的結構:
這裏寫圖片描述
詳細說明可以看RFC的對應章節。

http request

這裏寫圖片描述
上面 Request Line 的標準格式爲:

# request line
request-method-name request-URI HTTP-version
#  method舉例: GET, POST
#  request-URI: 指定請求的資源
#  HTTP-version: HTTP/1.0 or HTTP/1.1

當request消息到達server時,服務器會做以下處理中的一項:

  1. server解析request消息,映射request到對應文件目錄,返回請求的文件給client;
  2. server解析request消息,映射request到server的一個程序,執行程序,把程序輸出返回給client;
  3. server發現request無法被完成,返回攜帶錯誤碼的error msg給client;

http response

這裏寫圖片描述
上面 Status Line 的標準格式爲:

# Status Line
HTTP-version status-code reason-phrase
# HTTP-version: HTTP/1.0 or HTTP/1.1
# status-code: 三位數字的返回碼, 如: 200 ok, 403 Forbidden, 404 Not Found
# reason-phrase: 返回碼的簡短解釋

然後client(通常就是瀏覽器)收到server的response消息,會把內容顯示在頁面,瀏覽器會渲染HTML並執行JS.

HTTP 方法:GET和POST

每個 http request 請求都可以攜帶一個方法,最常見的就是 GET 和 POST,還有其他方法這裏不做介紹,可以看RFC。

GET method

GET request-URI HTTP-version
(optional request headers)

(optional request body)
  • GET 必須大寫
  • request-URI:resource路徑,必須以root “/" 開始,server指定的,非OS文件系統的根目錄;
  • client使用request headers 裏的Accept, Accept-Language等協商交互內容;
  • GET請求消息有一個可選的 request body,攜帶查詢字符串

Request Header 裏的host字段

請求header裏如果攜帶了 Connection: Keep-Alive,那麼要求server不要馬上關閉TCP連接。HTTP/1.1 默認指定 keep-alive,可以提高網絡效率。並且 HTTP/1.1 server支持虛擬主機,即同一個host有不同的hostname,不同host有各自指定的不同的根目錄,因此 HTTP/1.1 默認要求request header指定host字段。

URL Encoded 編碼特殊字符

URL無法攜帶特殊字符,遇到特殊字符用%xx編碼,xx是ASCII hex coe,如空格可被編碼爲 %20+.

GET 攜帶查詢參數, 是在URL裏傳參的,比如如下form制定GET方法提交

<html>
<body>
<form method="get" action="/bin/login">
    Username: <input type="text" name="user" size="25" /><br/>
    Password: <input type="password" name="pw" size="10" /><br/>
    <input type="hidden" name="action" value="login" />
    <input type="submit" value="SEND" />
</form>
</body>
</html>

點擊提交,瀏覽器生成的request消息如下:

GET /bin/login?user=Peter+Lee&pw=123456&action=login HTTP/1.1
Accept: image/gif, image/jpeg, */*
Referer: http://127.0.0.1:8000/login.html
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: 127.0.0.1:8000
Connection: Keep-Alive

上面request line的URI傳參:?user=Peter+Lee&pw=123456&action=login ,然後server可以解析這個字符串獲取對應的參數。

POST method

POST方法可以post額外的數據到server,如提交表單或上傳文件,一個POST請求如下:

POST request-URI HTTP-version
Content-Type: mime-type
Content-Length: number-of-bytes
(other optional request headers)

(URL-encoded query string)

對於POST, request header 裏的Content-TypeContent-Length is necessary是必選字段,指定post數據的類型和長度。

<html>
<body>
<form method="post" action="/bin/login">
    Username: <input type="text" name="user" size="25" /><br/>
    Password: <input type="password" name="pw" size="10" /><br/>
    <input type="hidden" name="action" value="login" />
    <input type="submit" value="SEND" />
</form>
</body>
</html>

提交表單,產生如下的http request請求

POST /bin/login HTTP/1.1
Host: 127.0.0.1:8000
Accept: image/gif, image/jpeg, */*
Referer: http://127.0.0.1:8000/login.html
Accept-Language: en-us
Content-Type: application/x-www-form-urlencoded  # type, post必選字段
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Content-Length: 37  # length, post必選字段, 下面post數據37個字符
Connection: Keep-Alive
Cache-Control: no-cache

User=Peter+Lee&pw=123456&action=login

POST request提交的數據沒有大小限制,並且不會再瀏覽器地址欄顯示,適合敏感或大量數據提交。對於上面裏子,post攜帶的參數就是最後的 User=Peter+Lee&pw=123456&action=login , server 解析這個字符串即可獲取對應數據。

HTTP 常用工具

  • chrome: chrome瀏覽器的開發者工具,調試前端DOM/JS,查看報文都很方便;
  • wget: 非交互式的web文件下載工具,支持HTTP, HTTPS和FTP等協議;
  • netcat: 網絡安全界的瑞士軍刀, 可以建立TCP或UDP連接來收發報文;
  • curl: 利用URL語法在命令行方式下工作的開源文件傳輸工具;

如使用curl查看一次http的請求響應,內容如下:

root@ubuntu:~# curl -v www.baidu.com
* Rebuilt URL to: www.baidu.com/
* Hostname was NOT found in DNS cache
*   Trying 115.239.211.112...
* Connected to www.baidu.com (115.239.211.112) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: www.baidu.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Connection: Keep-Alive
< Content-Length: 2381
< Content-Type: text/html
< Date: Sun, 26 Aug 2018 05:40:50 GMT
< Etag: "58860504-94d"
< Last-Modified: Mon, 23 Jan 2017 13:28:36 GMT
< Pragma: no-cache
* Server bfe/1.0.8.18 is not blacklisted
< Server: bfe/1.0.8.18
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
<
<!DOCTYPE html><head>...</head><body>...</body></html>

極簡HTTP1.1 Server的C實現

可以看這篇:HTTP1.1 基礎: 用C語言實現200行內的極簡http server

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章