十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

beego Controller与Context

beego Controller与Context 学习目标:ControllerInterface 契约、Controller 结构、Context/Input/Output 实现、Abort 的 panic 机制、SecureCookie 签名。1. ControllerInterface(controller.go:137-154)type ControllerInterface interface { Init(ctx *context.Context, controllerName, actionName string, app interface{}) Prepare() Get() / Post() / Delete() / Put() / Head() / Patch() / Options() / Trace() Finish() Render() error XSRFToken() string CheckXSRFCookie() bool HandlerFunc(fn string) bool URLMapping() }契约即生命周期:serveHttp 只依赖此接口,任何实现该接口的类型都能当控制器(不必嵌入 Controller)。方法名 switch(S05 步骤 13)正是对着这份接口。2. Controller 结构(controller.go:107-134)字段用途Ctx *context.Context请求上下文Data map[interface{}]interface{}与 ctx.Input.Data 共享同一 map(Init:167)——控制器与过滤器天然互通controllerName/actionName私有,Init 填充methodMapping map[string]func()Mapping() 注册的自定义方法TplName/ViewPath/Layout/LayoutSections/TplPrefix/TplExt模板六件套EnableRender bool渲染开关(粒度控制)EnableXSRF/_xsrfToken/XSRFExpireXSRFCruSession session.Store会话快捷方式基类默认实现:Get/Post/… 全部ctx.Abort(405,…)(178-210);Trace 按 RFC 回显(220-232);Render 走renderTemplate(339,空 TplName 时默认controller/action.tpl)。3. Context 家族(context/context.go)3.1 Context(72-78)type Context struct { Input *BeegoInput Output *BeegoOutput Request *http.Request ResponseWriter *Response _xsrfToken string }方法群:Bind*(按 Content-Type 分派 80-103)、Resp/JSONResp/XMLResp/YamlResp/ProtoResp(107-135,按 Accept)、Redirect、Abort(201-204)、Get/SetCookie、GetSecureCookie/SetSecureCookie(224-262)、XSRFToken/CheckXSRFCookie(265-298)、RenderMethodResult(301-314,方法返回值渲染,配合 CtrlXxx 路由)、Session(317-330)。3.2 Abort 的实现(201-204)func (ctx *Context) Abort(status int, body string) { ctx.Output.SetStatus(status) panic(body) // !! }Abort SetStatus panic。panic 沿调用栈冒泡到 serveHttp 的defer RecoverFunc(S05 步骤 1),RecoverFunc 检查 Output.Status 决定渲染什么。这就是:为什么 Abort 后 Finish 不再执行(panic 跳过了)为什么过滤器里 Abort 能短路一切为什么自定义 RecoverFunc 必须理解这套约定Controller.Abort(389 起)同理;CustomAbort支持自定义 body 渲染开关。3.3 Response(334-397)——响应包装type Response struct { http.ResponseWriter Started bool Status int Elapsed time.Duration }Write/WriteHeader置 StartedWriteHeader 幂等:Status0 直接 return(357-365)——防输出后又 500Hijack/Flush/CloseNotify/Pusher 透传(类型断言标准库可选接口)StatusCode类型(context/response.go)实现error与Renderer:直接把状态码当返回值 return的新式控制器写法靠它3.4 BeegoInput(input.go:46-56)type BeegoInput struct { Context *Context CruSession session.Store pnames/pvalues []string // 路由参数(树匹配时 SetParam 写入) data map[string]interface{} // 与 Controller.Data 共享 RequestBody []byte RunMethod/RunController // 过滤器改写路由的接口 }要点方法:Scheme(X-Forwarded-Proto 优先)、IP(X-Forwarded-For 首个)、IsAjax、CopyBody、ParseFormOrMultiForm、Param(:id)、ResetParams、Reset(池复用清场,68-77——字段清单就是泄漏风险清单)。3.5 BeegoOutput(output.go)Body/JSON/YAML/Proto/JSONP/XML/ServeFormatted(按 Accept)/Download(支持中文文件名 RFC 5987)/Cookie(sanitize)/SetStatus/IsCachable/IsOk/… 状态判断族。4. SecureCookie 签名机制(context.go:224-262)value base64(HMAC-SHA256(key, name date value_b64) 格式拼装) Set: {name}{date}{value}{MAC} 各段 base64 后以 | 连接 Get: 逐段拆开,重算 MAC 比对 → 校验 date 有效期 → 返回 value与 session cookie 引擎(sess_utils.go)同一套思路:gob 序列化 → AES-CTR 加密 → base64 → HMAC 签名。密钥必须固定且保密;理解这套编码加密签名三层结构是做安全审计的基础。5. XSRF 实现(265-298)func (ctx *Context) XSRFToken() string { // 读 cookie(XSRFName),没有则生成随机 token 写 cookie(HttpOnlyfalse,给 JS 读) } func (ctx *Context) CheckXSRFCookie() bool { // POST/PUT/DELETE:form._xsrf 或 header X-Xsrftoken 与 cookie 比对 }serveHttp 在 Prepare 后、方法前调用(S05 步骤 13),失败 Abort 403。6. 设计赏析Data map 共享:Init 里c.Data ctx.Input.Data——一次赋值打通控制器↔过滤器↔模板三个世界,代价是 map 的 key 变成 interface{}(弱类型)。panic 做控制流:Abort 的选择激进但统一;Go 官方不推荐 panic 跨层,但在请求处理这个天然有边界的场景(顶部必有 recover)是干净的。对比:gin 用显式 returnctx 标志位,代码更啰嗦但更 orthodox。接口最小化:serveHttp 只认 ControllerInterface 十几个方法,Controller 基类 30 方法都是可选便利——组合优于继承的实践。Response 包装不吞接口:透传 Flusher/Hijacker,兼容 SSE/WebSocket。
返回列表