This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
all-in-kingsoft/hzh/GIN/3-middleware/cors-registration-scope.md
T

2.8 KiB
Raw Blame History

tags, create time
tags create time
后端
Go
Gin
中间件
作用域
2026-04-27 12:55

跨分组共享中间件的作用域选择

概述

讨论当多个 RouterGroup(如 /api/v1 和 /api/v2)需要同一中间件时,是注册到全局还是各自分组的取舍。结论:同策略 → 全局;异策略 → 分组。

正文

场景还原

v1 := r.Group("/api/v1")  // 需要 CORS
v2 := r.Group("/api/v2")  // 也需要 CORS

两种方案:

方案 A — 全局注册(推荐 ✅)

r.Use(cors())  // 一次注册,所有路由自动继承

v1 := r.Group("/api/v1")
v2 := r.Group("/api/v2")

方案 B — 分组注册

v1 := r.Group("/api/v1", cors())  // 每个分组都写一遍
v2 := r.Group("/api/v2", cors())  // ← 重复代码

为什么全局更好?

1. DRY — 避免重复

分组注册需要在每个 Group 构造函数中手动传入中间件,新增版本时容易漏写。

2. 不会遗漏 — 更安全

// 假设后来加了 v3
v3 := r.Group("/api/v3")  // ← 分组注册下很容易忘记加 cors()
                            // 跨域请求静默失败,排查成本高

全局注册一劳永逸,永远不会遗漏。

3. OPTIONS 预检拦截天然正确

CORS 的核心逻辑是在最外层处理 OPTIONS 预检请求——预检触发条件、两轮对话机制、Header 语义详见 BACKEND/GIN/3-middleware/cors-registration-scope/cors-preflight。

放在全局中间件中,预检请求在最早阶段被拦截,不会消耗后续中间件的算力。

4. 性能差异可忽略

Gin 的 c.Next() 只是切片遍历,一个 CORS 中间件多走一趟链的成本微乎其微。为了省这点开销拆分到分组里,得不偿失。

什么时候按分组注册?

只有一种情况例外:不同分组需要不同的中间件配置。

// v1 宽松 — 允许所有来源
v1 := r.Group("/api/v1", corsAllowAll())

// v2 严格 — Origin 白名单校验
v2 := r.Group("/api/v2", corsStrict([]string{"https://app.example.com"}))

此时策略不同,自然不能复用同一个全局中间件。

决策对照表

条件 推荐方案
各分组使用相同中间件配置 全局 r.Use()
各分组需要不同配置 各自分组注册
某些路由明确不需要该中间件 跳过全局,按需注册到子分组
中间件本身有副作用(如限流) 评估后决定,可能需要分组隔离

关联笔记