0Pricing
Go Academy · 课时

CORS 与 panic 恢复中间件

跨源策略与从 panic 中恢复

CORS 与 panic 恢复中间件 是 CoddyKit 上的免费 Go Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。

什么是 CORS

跨源资源共享(CORS)是一种浏览器安全机制,用于限制哪些源可以向您的 API 发出 HTTP 请求。服务器通过设置响应标头选择启用该机制。

CORS 预检

在带有自定义标头或非简单方法的跨源请求之前,浏览器会发送 OPTIONS 预检请求。您的中间件必须处理 OPTIONS,并返回包含 CORS 标头的 200 响应。

CORS 中间件

用于开发环境的简单 CORS 中间件:

func CORS(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "https://myapp.com")
        w.Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
        w.Header().Set("Access-Control-Allow-Headers", "Authorization,Content-Type")
        if r.Method == http.MethodOptions {
            w.WriteHeader(http.StatusOK); return
        }
        next.ServeHTTP(w, r)
    })
}

允许的源

涉及凭据(Cookie、Authorization 标头)时,不要使用 Access-Control-Allow-Origin: *,而应使用明确的源。对于多个源,请与白名单进行匹配。

allowedOrigins := map[string]bool{
    "https://app.example.com": true,
    "https://dev.example.com": true,
}

if allowedOrigins[r.Header.Get("Origin")] {
    w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
}

Access-Control-Allow-Credentials

允许跨源发送 Cookie 和授权标头:

w.Header().Set("Access-Control-Allow-Credentials", "true")

rs/cors 库

在生产环境中,请使用 github.com/rs/cors 库,以获得功能完善的 CORS 支持,包括灵活的源匹配、凭据支持和预检缓存。

c := cors.New(cors.Options{
    AllowedOrigins: []string{"https://example.com"},
    AllowedMethods: []string{"GET","POST","PUT","DELETE"},
    AllowedHeaders: []string{"Authorization","Content-Type"},
    AllowCredentials: true,
})
handler := c.Handler(mux)

恐慌恢复中间件

从恐慌中恢复,防止服务器崩溃并丢失所有活动连接:

func Recovery(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        defer func() {
            if rec := recover(); rec != nil {
                log.Printf("panic: %v\n%s", rec, debug.Stack())
                http.Error(w, "Internal Server Error", 500)
            }
        }()
        next.ServeHTTP(w, r)
    })
}

runtime/debug.Stack

发生恐慌时打印完整的 goroutine 堆栈跟踪,以帮助诊断根本原因:

import "runtime/debug"
log.Printf("panic: %v\n%s", rec, debug.Stack())

Sentry 集成

在恢复中间件中,将恐慌发送到 Sentry 或类似的错误跟踪服务,然后再向客户端返回 500。

顺序:Recovery 位于最外层

请始终将 Recovery 注册为最外层(最先应用的)中间件,以便它捕获其他所有中间件和处理程序产生的恐慌。

handler := Recovery(RequestID(Logger(Auth(mux))))

测试恐慌恢复

编写一个会故意引发恐慌的处理程序,通过 httptest 经由中间件调用它,并断言响应为 500。

panicHandler := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { panic("test") })
w := httptest.NewRecorder()
Recovery(panicHandler).ServeHTTP(w, httptest.NewRequest("GET", "/", nil))
assert.Equal(t, 500, w.Code)

快速检查

为什么恐慌恢复中间件必须位于最外层?

回顾:CORS 与恐慌恢复

要点:

  • CORS:设置 Access-Control-Allow-* 标头;处理 OPTIONS 预检请求
  • 涉及凭据时,Allow-Origin 使用明确的源,而不是 *
  • 恢复:defer recover() + 记录堆栈跟踪 + 返回 500
  • Recovery 必须是最外层的中间件

常见问题解答

「CORS 与 panic 恢复中间件」课时是免费的吗?

是的 — 「CORS 与 panic 恢复中间件」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。

「CORS 与 panic 恢复中间件」这节课中我会学到什么?

跨源策略与从 panic 中恢复 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「CORS 与 panic 恢复中间件」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Go Academy 课中编写并运行代码吗?

能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. HTTP 中间件链基础
  2. 日志记录与请求 ID 中间件
  3. 身份验证与速率限制中间件
  4. CORS 与 panic 恢复中间件
← 返回 Go Academy