This repository has been archived on 2026-05-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
obsidian/BACKEND/HTTP 协议.md
T

153 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [后端, HTTP, 协议, 基础]
create time: 2026-04-24 18:41
---
# HTTP 协议
## 概述
HTTP(HyperText Transfer Protocol)是浏览器和服务器之间通信的"语言"。理解 HTTP 是理解 Web 工作原理的第一步。
思考题:你在浏览器地址栏输入 `https://www.google.com` 后按下回车,HTTP 协议在这个过程中扮演了什么角色?
## 正文
### 1. HTTP 请求结构
```
请求行 → 方法 + URL + 协议版本
请求头 → Key-Value 对,携带元信息
空行
请求体 → GET 请求通常为空,POST/PUT 有数据
```
```
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Length: 42
{"name": "Alice", "age": 25}
```
### 2. HTTP 方法(动词)
| 方法 | 语义 | 幂等性 | 典型场景 |
|------|------|--------|----------|
| `GET` | 读取数据 | ✅ 是 | 获取列表、详情 |
| `POST` | 创建资源 | ❌ 否 | 提交表单、创建用户 |
| `PUT` | 全量更新 | ✅ 是 | 完整替换一个资源 |
| `PATCH` | 部分更新 | ❌ 否 | 修改用户某个字段 |
| `DELETE` | 删除资源 | ✅ 是 | 删除用户、删除文章 |
```mermaid
graph LR
A[CRUD] -->|Create| B[POST]
A -->|Read| C[GET]
A -->|Update| D[PUT / PATCH]
A -->|Delete| E[DELETE]
```
> **提问:** 为什么 `GET` 请求要求"幂等"和"安全"(不修改服务器状态)?如果 `GET` 请求能删除数据,会发生什么安全问题?
### 3. 状态码分类
```
1xx → 信息性(处理中)
2xx → 成功(200 OK, 201 Created)
3xx → 重定向(301 永久, 302 临时)
4xx → 客户端错误(400 参数错误, 401 未认证, 403 无权限, 404 不存在)
5xx → 服务端错误(500 服务器内部错误, 502 网关错误, 503 服务不可用)
```
> **实战要点:** 前端开发最常遇到的是 401(Token 过期)和 403(权限不足),理解它们的区别很重要:401 是"你是谁?",403 是"你是谁,但你不能做这件事。"
### 4. 常用请求头
| Header | 说明 |
|--------|------|
| `Content-Type` | 请求体格式(`application/json` / `application/x-www-form-urlencoded`) |
| `Authorization` | 认证信息(`Bearer <token>`) |
| `Accept` | 期望的响应格式 |
| `Cookie` | 客户端存储的会话数据 |
| `Referer` | 来源页面(用于防盗链) |
| `User-Agent` | 客户端信息(浏览器/设备) |
### 5. RESTful 设计原则
RESTful 不是严格的规范,而是一组设计哲学:
```
资源命名用名词复数,动词用 HTTP 方法:
GET /api/users → 获取所有用户
GET /api/users/:id → 获取单个用户
POST /api/users → 创建用户
PUT /api/users/:id → 更新用户(全量)
PATCH /api/users/:id → 更新用户(部分)
DELETE /api/users/:id → 删除用户
```
```mermaid
graph TD
A[RESTful 核心原则] --> B["资源用 URL 表示<br/>(名词复数)"]
A --> C["操作用 HTTP 方法表示<br/>(GET/POST/PUT/DELETE)"]
A --> D["状态码表示结果<br/>(200/201/404/500)"]
A --> E["无状态<br/>(每次请求独立)"]
A --> F["JSON 作为数据交换格式"]
```
> **思考:** 为什么 RESTful 要求 URL 中用名词而不是动词?`GET /api/deleteUser/5` 和 `DELETE /api/users/5` 哪个更符合 RESTful 原则?为什么?
### 6. Go 后端处理 HTTP 请求示例
```go
package main
import (
"encoding/json"
"net/http"
)
// 定义请求结构体
type CreateUserRequest struct {
Name string `json:"name"`
Age int `json:"age"`
}
func handleCreateUser(w http.ResponseWriter, r *http.Request) {
// 只接受 POST 方法
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 解析请求体
var req CreateUserRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
// 处理业务逻辑...
// 创建用户
// 返回 201 Created
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]interface{}{
"id": 1,
"name": req.Name,
"age": req.Age,
})
}
```
## 关联笔记
- [[API 设计]] — 基于 HTTP 协议的 API 设计方法
- [[数据库基础]] — HTTP 请求最终需要操作数据库
- [[30.areas/finance/Investment lessons/2024.Current trading lessons.md]]