iT邦幫忙

2026 iThome 鐵人賽

DAY 12
0

昨天已經成功讓瀏覽器連線到自己建立的 Server,也能看到瀏覽器傳來的 HTTP Request。

今天進一步想了解:

瀏覽器傳來的 GET /hello HTTP/1.1 只是一串文字,Framework 是怎麼知道哪一部分代表請求方法、網址路徑和 HTTP 版本? 因此今天的目標是嘗試解析 HTTP Request 的第一行,也就是 Request Line。

https://ithelp.ithome.com.tw/upload/images/20260813/201833956sutkTTFgo.png

https://ithelp.ithome.com.tw/upload/images/20260813/20183395S0SnK4SN5w.png

  1. 先取得 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

  1. 將 Request Line 拆成三個部分

接著使用:

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

  1. 第一次測試:/hello

在瀏覽器輸入:

http://127.0.0.1:5000/hello

Server 收到:

GET /hello HTTP/1.1

程式解析後得到:

Method  : GET
Path    : /hello
Version : HTTP/1.1

這代表程式已經能把原本的一整行 HTTP 文字拆成個別資訊。

https://ithelp.ithome.com.tw/upload/images/20260813/20183395cNUXA2BNMg.png

  1. 改變網址,確認 Path 不是寫死的

接著將瀏覽器網址改成:

http://127.0.0.1:5000/products

這次收到的 Request Line 變成:

GET /products HTTP/1.1

解析結果也跟著變成:

Method  : GET
Path    : /products
Version : HTTP/1.1

https://ithelp.ithome.com.tw/upload/images/20260813/20183395MIpIbTu0ZS.png

這個測試證明 Path 並不是程式中固定寫好的 /hello,而是會根據瀏覽器實際要求的網址取得不同結果。


今天第一次實際解析 HTTP Request,發現瀏覽器傳送過來的資料其實具有固定的格式。程式可以先從完整 Request 中取得第一行,再利用空白將它拆成 Method、Path 和 Version。

原本看到 GET /products HTTP/1.1 時,只知道這是瀏覽器傳來的一串文字;但經過今天的實作後,可以進一步把它轉換成程式能分別處理的資訊。

這也讓我開始理解,Framework 收到 Request 後,並不是直接知道使用者要前往哪個頁面,而是需要先解析 HTTP Request,再根據其中的 Path 決定後續要做什麼。

完成實驗後,我再回頭查 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。


上一篇
Browser 傳來的 Request 到底長什麼樣?
下一篇
Framework 到底怎麼根據 Path 找到正確的程式?
系列文
程式設計沒有告訴你的事:30 天破解每一個 Why16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言