HTTP 協議深入理解
什麼是 HTTP?
HTTP(HyperText Transfer Protocol)是瀏覽器和伺服器之間溝通的語言。
💡 比喻:寄信 想像你去郵局寄信:
- Request(請求) = 你寫的信(告訴對方你要什麼)
- Response(回應) = 對方的回信(把結果寄回來)
- HTTP Method = 信封上的「目的」(查詢?修改?刪除?)
- Status Code = 回信的「處理結果」(成功?找不到?伺服器爆炸?)
HTTP 方法(Methods)
方法 用途 比喻
───────────────────────────────────────
GET 取得資料 去圖書館借書
POST 新增資料 交一份新的申請表
PUT 完整更新資料 整份文件重寫
PATCH 部分更新資料 只改文件中的一段
DELETE 刪除資料 撕掉一張表單
C# HttpClient 範例
// 建立 HttpClient 實例
var client = new HttpClient();
// GET:取得使用者列表
var response = await client.GetAsync("https://api.example.com/users");
// 讀取回應內容
var body = await response.Content.ReadAsStringAsync();
// POST:新增一筆使用者資料
var newUser = new StringContent(
// JSON 格式的使用者資料
"\"{ \"name\": \"小明\", \"age\": 25 }\" ",
System.Text.Encoding.UTF8,
// 指定內容類型為 JSON
"application/json"
);
// 送出 POST 請求
var postResponse = await client.PostAsync("https://api.example.com/users", newUser);
// PUT:完整更新使用者(需要傳入所有欄位)
var updatedUser = new StringContent(
// 完整的使用者資料
"\"{ \"name\": \"小明\", \"age\": 26, \"email\": \"ming@example.com\" }\" ",
System.Text.Encoding.UTF8,
"application/json"
);
// 送出 PUT 請求到指定的使用者 ID
await client.PutAsync("https://api.example.com/users/1", updatedUser);
// DELETE:刪除指定使用者
await client.DeleteAsync("https://api.example.com/users/1");
HTTP 狀態碼(Status Codes)
2xx — 成功 ✅
狀態碼 意思 什麼時候會看到
──────────────────────────────────────────
200 OK 一般請求成功
201 Created POST 新增成功
204 No Content DELETE 成功,沒有回傳內容
3xx — 重新導向 🔄
狀態碼 意思 什麼時候會看到
──────────────────────────────────────────
301 永久搬家 舊網址永久轉到新網址
302 暫時搬家 暫時轉向(例如登入後跳轉)
304 沒有修改 瀏覽器可以用快取
4xx — 客戶端錯誤 ❌
狀態碼 意思 什麼時候會看到
──────────────────────────────────────────
400 Bad Request 參數格式錯誤
401 Unauthorized 沒有登入(未驗證身份)
403 Forbidden 有登入但沒有權限
404 Not Found 網址或資源不存在
405 Method Not Allowed 用了不支援的 HTTP 方法
429 Too Many Requests 請求太頻繁被限流
5xx — 伺服器錯誤 💥
狀態碼 意思 什麼時候會看到
──────────────────────────────────────────
500 Internal Server Error 程式碼出錯(Bug)
502 Bad Gateway 反向代理連不到後端
503 Service Unavailable 伺服器維護中
504 Gateway Timeout 後端回應太慢
HTTP Headers(標頭)
Headers 就像信封上的附加資訊,告訴對方一些額外的細節。
常見 Request Headers
GET /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Accept: application/json
Cache-Control: no-cache
User-Agent: MyApp/1.0
重點 Headers 說明
Header 用途 比喻
──────────────────────────────────────────────────────
Content-Type 告訴對方資料格式 信封上寫「內含文件」
Authorization 身份驗證憑證 出示你的員工證
Cache-Control 快取策略 這封信可以影印保存嗎?
Accept 期望的回應格式 我要中文版的回覆
C# 設定 Headers
// 建立 HttpClient 並設定預設標頭
var client = new HttpClient();
// 設定 Authorization 標頭(Bearer Token)
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "your-token-here");
// 設定 Accept 標頭,告訴伺服器我們要 JSON 格式
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HTTPS 與 TLS
💡 比喻:信封加鎖
- HTTP = 明信片(任何人都能看到內容)
- HTTPS = 信封 + 掛號鎖(只有收件人能打開)
TLS 握手過程(簡化版)
瀏覽器 伺服器
| |
|--- 1. 你好,我要安全連線 ------>|
| |
|<-- 2. 這是我的證書(公鑰)-----|
| |
|--- 3. 用公鑰加密對稱金鑰 ----->|
| |
|<== 4. 之後都用對稱金鑰加密 ===>|
| (快速又安全) |
為什麼需要 HTTPS?
沒有 HTTPS 的風險:
├── 竊聽(Eavesdropping) → 駭客看到你的密碼
├── 篡改(Tampering) → 中間人修改回應內容
└── 偽裝(Impersonation) → 假的銀行網站騙你的資料
🤔 我這樣寫為什麼會錯?
❌ 錯誤 1:用 GET 傳送敏感資料
// ❌ 錯誤:密碼出現在網址列,會被瀏覽器歷史紀錄和伺服器 Log 記錄
var url = "https://api.example.com/login?username=admin&password=12345";
await client.GetAsync(url);
// ✅ 正確:用 POST 把敏感資料放在 Body 中
var loginData = new StringContent(
// 密碼放在請求主體中,不會出現在網址列
"\"{ \"username\": \"admin\", \"password\": \"12345\" }\" ",
System.Text.Encoding.UTF8,
"application/json"
);
// POST 請求會把資料放在 Body,而不是 URL
await client.PostAsync("https://api.example.com/login", loginData);
❌ 錯誤 2:忽略狀態碼,只看有沒有回應
// ❌ 錯誤:沒有檢查狀態碼,可能拿到錯誤的回應還繼續處理
var response = await client.GetAsync("https://api.example.com/users/999");
var data = await response.Content.ReadAsStringAsync();
// 如果回傳 404,data 可能是錯誤訊息而不是使用者資料
// ✅ 正確:先檢查狀態碼
var response2 = await client.GetAsync("https://api.example.com/users/999");
if (response2.IsSuccessStatusCode) // 檢查是否為 2xx 成功
{
// 只有成功時才處理資料
var userData = await response2.Content.ReadAsStringAsync();
Console.WriteLine(userData);
}
else
{
// 失敗時印出狀態碼,方便除錯
Console.WriteLine($"錯誤:{(int)response2.StatusCode} {response2.ReasonPhrase}");
}
❌ 錯誤 3:沒有正確使用 Content-Type
// ❌ 錯誤:送 JSON 但沒有指定 Content-Type,伺服器可能無法解析
var content = new StringContent("\"{ \"name\": \"test\" }\" ");
await client.PostAsync("https://api.example.com/users", content);
// ✅ 正確:明確指定 Content-Type 為 JSON
var correctContent = new StringContent(
"\"{ \"name\": \"test\" }\" ",
System.Text.Encoding.UTF8,
// 告訴伺服器這是 JSON 格式的資料
"application/json"
);
await client.PostAsync("https://api.example.com/users", correctContent);
💡 重點整理
| 概念 | 說明 |
|---|---|
| HTTP Method | 告訴伺服器你要做什麼(GET/POST/PUT/DELETE) |
| Status Code | 伺服器的處理結果(2xx 成功 / 4xx 你的錯 / 5xx 伺服器的錯) |
| Headers | 請求和回應的附加資訊(Content-Type、Authorization) |
| HTTPS | 加密版的 HTTP,保護傳輸安全 |
| TLS | HTTPS 底層的加密協議 |