昨天已經成功讓瀏覽器連線到自己建立的 Server,也能看到瀏覽器傳來的 HTTP Request。
今天進一步想了解:
瀏覽器傳來的 GET /hello HTTP/1.1 只是一串文字,Framework 是怎麼知道哪一部分代表請求方法、網址路徑和 HTTP 版本? 因此今天的目標是嘗試解析 HTTP Request 的第一行,也就是 Request Line。


瀏覽器傳來的 HTTP Request 會包含許多內容,例如:
GET /hello HTTP/1.1
Host: 127.0.0.1:5000
Connection: keep-alive
...
其中第一行:
GET /hello HTTP/1.1
就是 Request Line。
因此先利用:
string firstLine = request.Split("\r\n")[0];
將收到的 Request 按照換行切開,再取出第一行。
這時程式就能從整份 HTTP Request 中取得:
GET /hello HTTP/1.1
接著使用:
string[] parts = firstLine.Split(' ');
按照空白將 Request Line 拆開。
原本的:
GET /hello HTTP/1.1
就會變成:
parts[0] → GET
parts[1] → /hello
parts[2] → HTTP/1.1
因此可以分別取得:
string method = parts[0];
string path = parts[1];
string version = parts[2];
三個資料分別代表:
-Method:瀏覽器要進行的動作,例如 GET
-Path:瀏覽器要求的資源路徑,例如 /hello
-Version:使用的 HTTP 版本,例如 HTTP/1.1
在瀏覽器輸入:
Server 收到:
GET /hello HTTP/1.1
程式解析後得到:
Method : GET
Path : /hello
Version : HTTP/1.1
這代表程式已經能把原本的一整行 HTTP 文字拆成個別資訊。

接著將瀏覽器網址改成:
http://127.0.0.1:5000/products
這次收到的 Request Line 變成:
GET /products HTTP/1.1
解析結果也跟著變成:
Method : GET
Path : /products
Version : HTTP/1.1

這個測試證明 Path 並不是程式中固定寫好的 /hello,而是會根據瀏覽器實際要求的網址取得不同結果。
今天第一次實際解析 HTTP Request,發現瀏覽器傳送過來的資料其實具有固定的格式。程式可以先從完整 Request 中取得第一行,再利用空白將它拆成 Method、Path 和 Version。
原本看到 GET /products HTTP/1.1 時,只知道這是瀏覽器傳來的一串文字;但經過今天的實作後,可以進一步把它轉換成程式能分別處理的資訊。
完成實驗後,我再回頭查 Microsoft 官方資料確認自己的理解。
Microsoft 的 HTTP Request 格式說明中,Request 的第一行會包含三個主要部分:
HTTP Method + Request Target + HTTP Version
也就是今天實際看到的:
GET /products HTTP/1.1
可以拆成:
GET
↓
Method
/products
↓
Request Target
HTTP/1.1
↓
HTTP Version
這和今天自己透過 Split() 解析出的結果一致。Microsoft 的 ASP.NET Core Request 相關結構中,也會將 Method、Path、Protocol 等資訊分開保存,代表 Framework 最後確實需要把原始 HTTP 資料整理成可以個別使用的資訊。
還有前幾天使用的 TcpListener、TcpClient 與 NetworkStream 也符合 Microsoft 官方對 TCP 通訊流程的說明:Server 接受連線後,可以取得 NetworkStream,再透過資料流讀取 Client 傳來的內容。
所以今天的實驗不是單純把字串切一切而已,它其實是在模擬一個 Framework 收到 HTTP Request 後,最前面的解析工作。
昨天的我:
Browser 傳來一份 HTTP Request,Server 把它收進來。
今天的我:
Server 收到 HTTP Request 後,還必須解析它,才能知道 Client 到底想做什麼。
原本:
GET /products HTTP/1.1
對程式而言只是:
一串 string
今天我們把它拆成:
-Method = GET
-Path = /products
-Version = HTTP/1.1
這讓我第一次真正感受到,Framework 的工作,就是把底層看起來很難直接使用的資料,整理成開發者容易理解的形式。
今天最大的發現,不是學會:
Split()
而是我第一次自己完成了一小部分:
HTTP Parsing
以前使用 ASP.NET Core 時,我可以直接取得:
Request.Method
Request.Path
看起來好像這些資訊本來就存在。
但今天才知道,它們一開始其實只是藏在:
GET /products HTTP/1.1
這一串原始資料裡。
Framework 必須先:
收到 bytes
↓
轉成可解析的資料
↓
找到 Request Line
↓
解析 Method
↓
解析 Path
↓
解析 Version
最後才有我們平常熟悉的 Request 資訊。
也就是說ASP.NET Core 平常替我省略掉的,其實是一整段解析流程。
今天,我的 Framework 已經開始不只是「收到資料」,而是開始:
理解資料。
目前雖然還只有三個變數:
method
path
version
但這三個值之後會非常重要。
尤其是:
path
因為未來 Framework 必須根據:
/
/hello
/products
決定要執行哪一段程式。
這也代表我們已經非常接近下一個 Framework 核心能力:
Routing。
現在我們已經可以取得:
Path = /hello
或:
Path = /products
但目前不管 Path 是什麼,Server 做的事情都一樣:
解析
↓
印出來
真正的 Web Framework 顯然不能這樣。
它應該要能做到:
/hello
↓
執行 Hello Handler
/products
↓
執行 Products Handler
所以新的問題來了:
Framework 到底怎麼根據 Path 找到正確的程式?
這就是下一篇要開始研究的: Routing。