02-1. HTTP 基礎概念

⏱️ 閱讀時間: 10 分鐘 🎯 難度: ⭐⭐ (簡單)


🎯 本篇重點

理解 HTTP 協定的基本概念、運作原理、版本演進,以及為什麼 HTTP 是網路世界最重要的協定。


🤔 什麼是 HTTP?

HTTP (HyperText Transfer Protocol) = 超文本傳輸協定

一句話解釋: HTTP 就像是瀏覽器和網站伺服器之間的「對話語言」,規定了雙方如何請求和傳送網頁資料。


📖 用圖書館借書來比喻 HTTP

借書流程 = HTTP 請求流程

你(瀏覽器) → 圖書館(伺服器)

步驟 1:你走進圖書館(建立 TCP 連線)
步驟 2:你填寫借書單(HTTP 請求)
        - 書名:《三國演義》(URL)
        - 借書方式:借閱(GET 方法)

步驟 3:館員處理(伺服器處理請求)
        - 檢查有沒有這本書
        - 檢查你有沒有借書資格

步驟 4:館員回應(HTTP 回應)
        - 成功:給你書 + 借書證明(200 OK + 內容)
        - 失敗:書不存在(404 Not Found)
        - 失敗:沒有權限(403 Forbidden)

步驟 5:你離開圖書館(關閉 TCP 連線)

🏗️ HTTP 在網路模型中的位置

OSI 7 層模型

┌──────────────────────────────┬─────────────────┐
│ 7. Application Layer (應用層) │  HTTP, HTTPS    │ ← HTTP 在這裡
├──────────────────────────────┼─────────────────┤
│ 6. Presentation Layer (表示層)│  加密、壓縮      │
├──────────────────────────────┼─────────────────┤
│ 5. Session Layer (會話層)     │  建立、維護會話  │
├──────────────────────────────┼─────────────────┤
│ 4. Transport Layer (傳輸層)   │  TCP            │
├──────────────────────────────┼─────────────────┤
│ 3. Network Layer (網路層)     │  IP             │
├──────────────────────────────┼─────────────────┤
│ 2. Data Link Layer (資料鏈結層)│  Ethernet       │
├──────────────────────────────┼─────────────────┤
│ 1. Physical Layer (實體層)    │  網路線、光纖    │
└──────────────────────────────┴─────────────────┘

HTTP 位於第 7 層(應用層)

  • HTTP 是應用層協定
  • 提供網頁資料傳輸服務
  • 使用者透過瀏覽器與 Web 伺服器互動

TCP/IP 4 層模型

┌─────────────────────────────┬─────────────────┐
│ 4. Application Layer (應用層) │  HTTP, HTTPS    │ ← HTTP 在這裡
├─────────────────────────────┼─────────────────┤
│ 3. Transport Layer (傳輸層)  │  TCP            │
├─────────────────────────────┼─────────────────┤
│ 2. Internet Layer (網際網路層)│  IP             │
├─────────────────────────────┼─────────────────┤
│ 1. Network Access (網路存取層)│  Ethernet       │
└─────────────────────────────┴─────────────────┘

HTTP 位於第 4 層(應用層)

  • 在 TCP/IP 模型中,HTTP 同樣是應用層協定
  • 使用 TCP 作為傳輸層協定(Port 80)
  • TCP 提供可靠的連線導向傳輸

對比表:

模型HTTP 所在層級層級編號底層協定Port
OSI 7 層Application LayerLayer 7TCP (Layer 4)80
TCP/IP 4 層Application LayerLayer 4TCP (Layer 3)80

重點:

  • HTTP 是應用層協定(兩種模型都是)
  • 使用 TCP 作為傳輸層(Port 80,HTTPS 用 Port 443)
  • TCP 提供可靠傳輸,HTTP 提供網頁內容傳輸

🌐 HTTP 的基本運作原理

請求-回應模型(Request-Response Model)

【客戶端(瀏覽器)】           【伺服器】

        請求(Request)
    ────────────────────→
    GET /index.html HTTP/1.1
    Host: www.example.com

                            處理請求...

        回應(Response)
    ←────────────────────
    HTTP/1.1 200 OK
    Content-Type: text/html

    <html>...</html>

HTTP 的特性

1. 無狀態(Stateless)
   ├─ 每個請求都是獨立的
   ├─ 伺服器不記得你是誰
   └─ 需要 Cookie/Session 來記住用戶

2. 無連線(Connectionless)
   ├─ 每次請求都建立新連線(HTTP/1.0)
   ├─ 請求完畢就關閉連線
   └─ HTTP/1.1 支援持久連線

3. 基於 TCP
   ├─ 使用 TCP 作為傳輸層協定
   ├─ 保證資料可靠傳輸
   └─ 預設使用 Port 80(HTTP)、443(HTTPS)

4. 文字協定(Text Protocol)
   ├─ 請求和回應都是可讀的文字格式
   ├─ 方便除錯
   └─ HTTP/2 改用二進位格式

🔍 HTTP 的組成部分

HTTP 請求(Request)

GET /index.html HTTP/1.1              ← 請求行(Request Line)
Host: www.example.com                 ← 標頭(Headers)
User-Agent: Mozilla/5.0
Accept: text/html
Connection: keep-alive
                                      ← 空行
[可選的請求內容]                        ← 主體(Body)

HTTP 回應(Response)

HTTP/1.1 200 OK                       ← 狀態行(Status Line)
Content-Type: text/html               ← 標頭(Headers)
Content-Length: 1234
Server: Apache/2.4
Date: Mon, 06 Jan 2025 12:00:00 GMT
                                      ← 空行
<html>                                ← 主體(Body)
<head><title>首頁</title></head>
<body>Hello World!</body>
</html>

📝 HTTP 請求方法

常用方法一覽

GET     - 取得資源(讀取)
POST    - 新增資源(建立)
PUT     - 更新資源(完整更新)
PATCH   - 部分更新資源
DELETE  - 刪除資源
HEAD    - 只取得標頭(不取內容)
OPTIONS - 查詢伺服器支援的方法

實際例子

【讀取文章】
GET /articles/123 HTTP/1.1
→ 取得編號 123 的文章

【發表文章】
POST /articles HTTP/1.1
Content-Type: application/json

{"title": "新文章", "content": "內容"}
→ 建立新文章

【更新文章】
PUT /articles/123 HTTP/1.1
Content-Type: application/json

{"title": "修改後的標題", "content": "修改後的內容"}
→ 完整更新編號 123 的文章

【刪除文章】
DELETE /articles/123 HTTP/1.1
→ 刪除編號 123 的文章

📊 HTTP 狀態碼

五大類狀態碼

1xx - 資訊性回應(Informational)
├─ 100 Continue
└─ 101 Switching Protocols

2xx - 成功(Success)
├─ 200 OK                   ← 最常見
├─ 201 Created              ← POST 成功建立資源
└─ 204 No Content           ← 成功但無內容

3xx - 重新導向(Redirection)
├─ 301 Moved Permanently    ← 永久重新導向
├─ 302 Found                ← 暫時重新導向
└─ 304 Not Modified         ← 使用快取

4xx - 客戶端錯誤(Client Error)
├─ 400 Bad Request          ← 請求格式錯誤
├─ 401 Unauthorized         ← 需要登入
├─ 403 Forbidden            ← 沒有權限
├─ 404 Not Found            ← 找不到資源
└─ 429 Too Many Requests    ← 請求太頻繁

5xx - 伺服器錯誤(Server Error)
├─ 500 Internal Server Error ← 伺服器內部錯誤
├─ 502 Bad Gateway          ← 閘道錯誤
└─ 503 Service Unavailable  ← 服務暫時無法使用

🚀 HTTP 版本演進

HTTP/0.9(1991 年)

特性:
- 超級簡單,只有 GET 方法
- 沒有標頭(Headers)
- 只能傳輸 HTML

範例:
GET /index.html

(沒有版本號,沒有標頭)

HTTP/1.0(1996 年)

新增功能:
✅ 加入版本號(HTTP/1.0)
✅ 加入標頭(Headers)
✅ 加入狀態碼(200, 404, 500...)
✅ 支援多種內容類型(圖片、影片等)
✅ 支援 POST、HEAD 等方法

缺點:
❌ 每個請求都要建立新連線(效率差)

範例:
GET /index.html HTTP/1.0
Host: www.example.com

HTTP/1.0 200 OK
Content-Type: text/html

<html>...</html>

HTTP/1.1(1997 年 - 現在最常用)

改進:
✅ 持久連線(Keep-Alive)
   - 一個 TCP 連線可以發送多個請求
   - 不用每次都重新建立連線

✅ 管線化(Pipelining)
   - 可以同時發送多個請求
   - 不用等第一個回應回來

✅ 分塊傳輸(Chunked Transfer)
   - 可以一邊產生一邊傳送
   - 不用等全部內容都產生完

✅ Host 標頭
   - 支援虛擬主機
   - 一個 IP 可以架多個網站

✅ 快取控制
   - Cache-Control 標頭
   - 減少重複請求

範例:
GET /index.html HTTP/1.1
Host: www.example.com
Connection: keep-alive      ← 持久連線

HTTP/1.1 200 OK
Content-Type: text/html
Connection: keep-alive

HTTP/2(2015 年)

革命性改進:
✅ 二進位格式
   - 不再是文字協定
   - 效率更高

✅ 多工(Multiplexing)
   - 一個連線同時處理多個請求/回應
   - 不會互相阻塞

✅ 標頭壓縮(Header Compression)
   - 使用 HPACK 演算法
   - 減少重複的標頭傳輸

✅ 伺服器推送(Server Push)
   - 伺服器主動推送資源
   - 不用等客戶端請求

✅ 優先順序(Stream Priority)
   - 重要的資源先傳

效能提升:
- 網頁載入速度提升 20-50%

HTTP/3(2022 年)

最新版本:
✅ 基於 QUIC 協定
   - 不再使用 TCP,改用 UDP
   - 更快的連線建立

✅ 改善隊頭阻塞(Head-of-Line Blocking)
   - TCP 層的阻塞問題
   - 一個封包遺失不影響其他資料流

✅ 更好的行動網路支援
   - 切換 Wi-Fi/4G 不斷線

✅ 內建加密
   - 強制 TLS 1.3

使用情況:
- Google、Facebook、Cloudflare 已支援
- Chrome、Firefox、Safari 已支援

💻 實戰範例:用 Python 發送 HTTP 請求

使用 requests 套件

import requests

# GET 請求
response = requests.get('https://api.github.com/users/octocat')

print(f"狀態碼:{response.status_code}")        # 200
print(f"標頭:{response.headers}")              # 回應標頭
print(f"內容:{response.text}")                 # 回應內容
print(f"JSON:{response.json()}")               # 解析 JSON

# POST 請求
data = {
    'title': '新文章',
    'content': '文章內容'
}
response = requests.post(
    'https://api.example.com/articles',
    json=data,
    headers={'Authorization': 'Bearer TOKEN'}
)

print(f"狀態碼:{response.status_code}")        # 201 Created
print(f"回應內容:{response.json()}")

# PUT 請求(更新)
update_data = {
    'title': '修改後的標題'
}
response = requests.put(
    'https://api.example.com/articles/123',
    json=update_data
)

# DELETE 請求
response = requests.delete('https://api.example.com/articles/123')
print(f"狀態碼:{response.status_code}")        # 204 No Content

使用原始的 HTTP 請求(socket)

import socket

# 建立 TCP 連線
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('www.example.com', 80))

# 發送 HTTP 請求
request = """GET / HTTP/1.1
Host: www.example.com
User-Agent: Python/3.9
Accept: text/html
Connection: close

"""

sock.send(request.encode())

# 接收回應
response = b''
while True:
    data = sock.recv(4096)
    if not data:
        break
    response += data

sock.close()

# 解析回應
response_text = response.decode()
print(response_text)

# 輸出:
# HTTP/1.1 200 OK
# Content-Type: text/html
# ...
# <html>...</html>

🌐 實際應用場景

1. 瀏覽網頁

你在瀏覽器輸入 www.google.com

步驟 1:DNS 解析
www.google.com → 142.250.185.46(IP)

步驟 2:建立 TCP 連線
三次握手 → 連線建立

步驟 3:發送 HTTP 請求
GET / HTTP/1.1
Host: www.google.com
User-Agent: Chrome/120.0
Accept: text/html

步驟 4:接收 HTTP 回應
HTTP/1.1 200 OK
Content-Type: text/html

<html>...</html>

步驟 5:渲染網頁
瀏覽器解析 HTML、CSS、JavaScript → 顯示網頁

2. API 呼叫

# 前端 JavaScript 呼叫後端 API

// 取得用戶資料
fetch('https://api.example.com/users/123')
  .then(response => response.json())
  .then(data => {
    console.log(data);  // { id: 123, name: "John" }
  });

// 更新用戶資料
fetch('https://api.example.com/users/123', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer TOKEN'
  },
  body: JSON.stringify({
    name: 'John Doe',
    email: 'john@example.com'
  })
})
  .then(response => response.json())
  .then(data => console.log('更新成功', data));

3. 檔案上傳

import requests

# 上傳圖片
files = {'file': open('photo.jpg', 'rb')}
response = requests.post(
    'https://api.example.com/upload',
    files=files
)

print(response.json())  # { "url": "https://cdn.../photo.jpg" }

🤔 為什麼 HTTP 這麼重要?

1. 無所不在

HTTP 無處不在:
├─ 網頁瀏覽(Chrome、Firefox、Safari)
├─ API 呼叫(RESTful API、GraphQL)
├─ 行動應用(App 與後端通訊)
├─ 物聯網(IoT 設備)
├─ 微服務(Service-to-Service)
└─ 雲端服務(AWS、Azure、GCP)

估計:
- 全球每天超過 1000 億次 HTTP 請求
- 99% 的網路流量使用 HTTP/HTTPS

2. 簡單易用

優點:
✅ 文字協定(易讀、易除錯)
✅ 無狀態(簡化伺服器設計)
✅ 擴展性強(可以加新的標頭)
✅ 跨平台(任何語言都能實作)
✅ 生態系統完整(大量工具支援)

3. 標準化

標準制定:
├─ IETF(Internet Engineering Task Force)
├─ RFC 文件(Request for Comments)
└─ W3C(World Wide Web Consortium)

主要 RFC:
- RFC 7230-7235(HTTP/1.1)
- RFC 7540(HTTP/2)
- RFC 9114(HTTP/3)

好處:
- 所有瀏覽器、伺服器遵循同一標準
- 跨平台互通

🎓 面試常見問題

Q1:HTTP 是無狀態的,那怎麼保持登入狀態?

A:使用 Cookie 和 Session

方法 1:Session + Cookie
1. 用戶登入成功
2. 伺服器建立 Session(儲存在伺服器)
3. 伺服器回傳 Session ID(透過 Cookie)
4. 客戶端每次請求都帶上 Cookie
5. 伺服器透過 Session ID 識別用戶

範例:
// 登入請求
POST /login HTTP/1.1
Content-Type: application/json

{"username": "john", "password": "123456"}

// 伺服器回應
HTTP/1.1 200 OK
Set-Cookie: sessionid=abc123; HttpOnly; Secure

// 後續請求自動帶上 Cookie
GET /profile HTTP/1.1
Cookie: sessionid=abc123

方法 2:Token(JWT)
1. 用戶登入成功
2. 伺服器產生 Token(JWT)
3. 客戶端儲存 Token(localStorage)
4. 每次請求在 Authorization 標頭帶上 Token
5. 伺服器驗證 Token

範例:
// 登入請求
POST /login HTTP/1.1

// 伺服器回應
{"token": "eyJhbGci..."}

// 後續請求
GET /profile HTTP/1.1
Authorization: Bearer eyJhbGci...

Q2:HTTP/1.1 和 HTTP/2 的最大差異?

A:HTTP/2 使用多工(Multiplexing)

HTTP/1.1 的問題:
- 隊頭阻塞(Head-of-Line Blocking)
- 一個連線一次只能處理一個請求
- 即使使用持久連線,也要等前一個回應完成

範例:
請求 1:GET /style.css    → 等待...
請求 2:GET /script.js    → 等請求 1 完成
請求 3:GET /image.png    → 等請求 2 完成

HTTP/2 的解決:
- 多工:一個連線同時處理多個請求
- 不會互相阻塞

範例:
請求 1:GET /style.css    ↓
請求 2:GET /script.js    ↓  同時進行
請求 3:GET /image.png    ↓

結果:
- 網頁載入速度提升 20-50%
- 不需要域名分片(Domain Sharding)

Q3:為什麼需要 HTTPS?HTTP 有什麼問題?

A:HTTP 是明文傳輸,不安全

HTTP 的三大問題:

1. 竊聽(Eavesdropping)
   - 資料以明文傳輸
   - 任何人都可以攔截並讀取
   - 例:帳號密碼、信用卡資訊

2. 篡改(Tampering)
   - 中間人可以修改資料
   - 例:植入惡意腳本、修改網頁內容

3. 偽裝(Impersonation)
   - 無法驗證伺服器身份
   - 例:釣魚網站

HTTPS 的解決:
✅ 加密(Encryption)→ 防止竊聽
✅ 完整性(Integrity)→ 防止篡改
✅ 驗證(Authentication)→ 防止偽裝

使用 SSL/TLS 加密:
- 所有資料加密傳輸
- 使用數位憑證驗證身份
- 確保資料完整性

Q4:GET 和 POST 有什麼差異?

A:主要差異在語義、安全性、快取

語義差異:
GET  - 取得資源(讀取)
POST - 新增資源(建立)

安全性:
GET:
- 參數在 URL 中(可見)
- 會被記錄在瀏覽器歷史
- 可能洩露敏感資訊
- 例:/login?username=john&password=123

POST:
- 參數在 Body 中(不可見)
- 不會被記錄在瀏覽器歷史
- 相對安全

快取:
GET:
- 可以被快取
- 可以加入書籤
- 適合查詢

POST:
- 通常不被快取
- 不能加入書籤
- 適合修改資料

長度限制:
GET:
- URL 長度有限制(約 2048 字元)
- 大量資料無法傳送

POST:
- 無長度限制
- 可以傳送大量資料

冪等性(Idempotence):
GET  - 冪等(多次請求結果相同)
POST - 非冪等(多次請求可能產生多個資源)

Q5:HTTP 的 Keep-Alive 是什麼?

A:Keep-Alive = 持久連線(Persistent Connection)

HTTP/1.0:
- 每個請求建立新連線
- 請求完畢就關閉連線
- 效率差

HTTP/1.1:
- 預設使用 Keep-Alive
- 一個 TCP 連線可以發送多個請求
- 不用每次都重新建立連線

範例:
// HTTP/1.0(每次都重新連線)
請求 1 → 建立連線 → GET /page1 → 關閉連線
請求 2 → 建立連線 → GET /page2 → 關閉連線
請求 3 → 建立連線 → GET /page3 → 關閉連線

// HTTP/1.1(Keep-Alive)
建立連線 → GET /page1 → GET /page2 → GET /page3 → 關閉連線

優點:
✅ 減少 TCP 連線建立的開銷(三次握手)
✅ 減少 TCP 連線關閉的開銷(四次揮手)
✅ 提升效能(減少延遲)

設定:
// 伺服器回應
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=100

timeout=5:連線閒置 5 秒後關閉
max=100:最多處理 100 個請求

✅ 重點回顧

HTTP 定義:

  • 超文本傳輸協定
  • 瀏覽器和伺服器之間的對話語言

HTTP 特性:

  • ✅ 無狀態(每個請求獨立)
  • ✅ 基於 TCP(可靠傳輸)
  • ✅ 請求-回應模型
  • ✅ 文字協定(HTTP/1.x)

HTTP 組成:

  • 請求:請求行 + 標頭 + 主體
  • 回應:狀態行 + 標頭 + 主體

HTTP 方法:

  • GET(讀取)、POST(新增)、PUT(更新)、DELETE(刪除)

HTTP 狀態碼:

  • 2xx(成功)、3xx(重新導向)、4xx(客戶端錯誤)、5xx(伺服器錯誤)

HTTP 版本:

  • HTTP/1.1 - 最常用、持久連線
  • HTTP/2 - 多工、二進位、標頭壓縮
  • HTTP/3 - 基於 QUIC(UDP)、更快

面試重點:

  • ✅ HTTP 無狀態 → 用 Cookie/Session/Token 保持狀態
  • ✅ HTTP/2 多工 → 解決隊頭阻塞
  • ✅ HTTP 不安全 → 用 HTTPS 加密
  • ✅ GET vs POST → 語義、安全性、快取
  • ✅ Keep-Alive → 持久連線,提升效能

上一篇: 01-4. TCP vs UDP 下一篇: 02-2. HTTP 請求與回應


最後更新:2025-01-06

0%