字节赫兹 框架教程 一请求上下文之请求(二)https://developer.aliyun.com/article/1391803
FormValue
按照以下顺序获取 key 的值。
从 QueryArgs 中获取值。
从 PostArgs 中获取值。
从 MultipartForm 中获取值。
函数签名:
func (ctx *RequestContext) FormValue(key string) []byte
示例:
// POST http://example.com/user?name=tom // Content-Type: application/x-www-form-urlencoded // age=10 h.POST("/user", func(c context.Context, ctx *app.RequestContext) { name := ctx.FormValue("name") // name == []byte("tom"), get by QueryArgs age := ctx.FormValue("age") // age == []byte("10"), get by PostArgs }) // POST http://example.com/user // Content-Type: multipart/form-data; // Content-Disposition: form-data; name="name" // tom h.POST("/user", func(c context.Context, ctx *app.RequestContext) { name := ctx.FormValue("name") // name == []byte("tom"), get by MultipartForm })
SetFormValueFunc
若 FormValue 函数提供的默认获取 key 的值的方式不满足需求,用户可以使用该函数自定义获取 key 的值的方式。
函数签名:
func (ctx *RequestContext) SetFormValueFunc(f FormValueFunc)
示例:
// POST http://example.com/user?name=tom // Content-Type: multipart/form-data; // Content-Disposition: form-data; name="age" // 10 h.POST("/user", func(c context.Context, ctx *app.RequestContext) { // only return multipart form value ctx.SetFormValueFunc(func(rc *app.RequestContext, s string) []byte { mf, err := rc.MultipartForm() if err == nil && mf.Value != nil { vv := mf.Value[s] if len(vv) > 0 { return []byte(vv[0]) } } return nil }) name := ctx.FormValue("name") // name == nil age := ctx.FormValue("age") // age == []byte("10") })
文件操作
func (ctx *RequestContext) MultipartForm() (*multipart.Form, error) func (ctx *RequestContext) FormFile(name string) (*multipart.FileHeader, error) func (ctx *RequestContext) SaveUploadedFile(file *multipart.FileHeader, dst string) error
MultipartForm
获取 multipart.Form 对象。(详情请参考 multipart#Form)
注意:此函数既可以获取普通值也可以获取文件,此处给出了获取文件值的示例代码,获取普通值的示例代码可参考 MultipartForm。
函数签名:
func (ctx *RequestContext) MultipartForm() (*multipart.Form, error)
示例:
// POST http://example.com/user // Content-Type: multipart/form-data; // Content-Disposition: form-data; name="avatar"; filename="abc.jpg" h.POST("/user", func(c context.Context, ctx *app.RequestContext) { form, err := ctx.MultipartForm() avatarFile := form.File["avatar"][0] // avatarFile.Filename == "abc.jpg" })
FormFile
按名称检索 multipart.Form.File,返回给定 name 的第一个 multipart.FileHeader。(详情请参考 multipart#FileHeader)
函数签名:
func (ctx *RequestContext) FormFile(name string) (*multipart.FileHeader, error)
示例:
// POST http://example.com/user // Content-Type: multipart/form-data; // Content-Disposition: form-data; name="avatar"; filename="abc.jpg" h.Post("/user", func(c context.Context, ctx *app.RequestContext) { avatarFile, err := ctx.FormFile("avatar") // avatarFile.Filename == "abc.jpg", err == nil })
SaveUploadedFile
保存 multipart 文件到磁盘。
函数签名:
func (ctx *RequestContext) SaveUploadedFile(file *multipart.FileHeader, dst string) error
示例:
// POST http://example.com/user // Content-Type: multipart/form-data; // Content-Disposition: form-data; name="avatar"; filename="abc.jpg" h.Post("/user", func(c context.Context, ctx *app.RequestContext) { avatarFile, err := ctx.FormFile("avatar") // avatarFile.Filename == "abc.jpg", err == nil // save file ctx.SaveUploadedFile(avatarFile, avatarFile.Filename) // save file "abc.jpg" })
Handler
func (ctx *RequestContext) Next(c context.Context) func (ctx *RequestContext) Handlers() HandlersChain func (ctx *RequestContext) Handler() HandlerFunc func (ctx *RequestContext) SetHandlers(hc HandlersChain) func (ctx *RequestContext) HandlerName() string func (ctx *RequestContext) GetIndex() int8 func (ctx *RequestContext) Abort() func (ctx *RequestContext) IsAborted() bool
Next
执行下一个 handler,该函数通常用于中间件 handler 中。
函数签名:
func (ctx *RequestContext) Next(c context.Context)
示例:
h.POST("/user", func(c context.Context, ctx *app.RequestContext) { ctx.Next(c) v := ctx.GetString("version") // v == "v1" }, func(c context.Context, ctx *app.RequestContext) { ctx.Set("version", "v1") })
Handlers
获取 handlers chain。
函数签名:
func (ctx *RequestContext) Handlers() HandlersChain
示例:
middleware1 := func(c context.Context, ctx *app.RequestContext) { } handler1 := func(c context.Context, ctx *app.RequestContext) { handlers := ctx.Handlers() // []Handler{middleware1, handler1} } h.POST("/user", middleware1, handler1)
Handler
获取 handlers chain 的最后一个 handler,一般来说,最后一个 handler 是 main handler。
函数签名:
func (ctx *RequestContext) Handler() HandlerFunc
示例:
middleware1 := func(c context.Context, ctx *app.RequestContext) { lastHandler := ctx.Handler() // lastHandler == handler1 } handler1 := func(c context.Context, ctx *app.RequestContext) { } h.POST("/user", middleware1, handler1)
SetHandlers
设置 handlers chain。
函数签名:
func (ctx *RequestContext) SetHandlers(hc HandlersChain)
示例:
handler1 := func(c context.Context, ctx *app.RequestContext) { ctx.Set("current", "handler1") } handler := func(c context.Context, ctx *app.RequestContext) { hc := app.HandlersChain{ctx.Handlers()[0], handler1} // append handler1 into handlers chain ctx.SetHandlers(hc) ctx.Next(c) current := ctx.GetString("current") // current == "handler1" ctx.String(consts.StatusOK, current) } h.POST("/user", handler)
HandlerName
获取最后一个 handler 的函数名称。
函数签名:
func (ctx *RequestContext) HandlerName() string
示例:
package main func main() { h := server.New() h.POST("/user", func(c context.Context, ctx *app.RequestContext) { hn := ctx.HandlerName() // hn == "main.main.func1" }) }
GetIndex
获取当前执行的 handler 在 handlers chain 中的 index。
函数签名:
func (ctx *RequestContext) GetIndex() int8
示例:
h.POST("/user", func(c context.Context, ctx *app.RequestContext) { index := ctx.GetIndex() // index == 0 }, func(c context.Context, ctx *app.RequestContext) { index := ctx.GetIndex() // index == 1 })
Abort
终止后续的 handler 执行。
函数签名:
func (ctx *RequestContext) Abort()
示例:
h.POST("/user", func(c context.Context, ctx *app.RequestContext) { ctx.Abort() }, func(c context.Context, ctx *app.RequestContext) { // will not execute })
IsAborted
获取后续的 handler 执行状态是否被终止。
函数签名:
func (ctx *RequestContext) IsAborted() bool
示例:
h.POST("/user", func(c context.Context, ctx *app.RequestContext) { ctx.Abort() isAborted := ctx.IsAborted() // isAborted == true }, func(c context.Context, ctx *app.RequestContext) { // will not execute })
参数绑定与校验
func (ctx *RequestContext) Bind(obj interface{}) error func (ctx *RequestContext) Validate(obj interface{}) error func (ctx *RequestContext) BindAndValidate(obj interface{}) error
获取 ClientIP
func (ctx *RequestContext) ClientIP() string func (ctx *RequestContext) SetClientIPFunc(f ClientIP)
ClientIP
获取客户端 IP 的地址。
该函数的默认行为:若 X-Forwarded-For 或 X-Real-IP Header 中存在 ip,则从这两个 Header 中读 ip 并返回(优先级 X-Forwarded-For 大于 X-Real-IP),否则返回 remote address。
函数签名:
func (ctx *RequestContext) ClientIP() string
示例:
// X-Forwarded-For: 20.20.20.20, 30.30.30.30 // X-Real-IP: 10.10.10.10 h.Use(func(c context.Context, ctx *app.RequestContext) { ip := ctx.ClientIP() // 20.20.20.20 })
SetClientIPFunc
若 ClientIP 函数提供的默认方式不满足需求,用户可以使用该函数自定义获取客户端 ip 的方式。
用户可以自己实现自定义函数,也可以通过设置 app.ClientIPOptions 实现。
注意:在设置 app.ClientIPOptions 时,TrustedCIDRs 需用户自定义(若不设置则固定返回 remote address),代表可信任的路由。若 remote address 位于可信任的路由范围内,则会选择从 RemoteIPHeaders 中获取 ip,否则返回 remote address。
函数签名:
func (ctx *RequestContext) SetClientIPFunc(f ClientIP)
示例:
// POST http://example.com/user // X-Forwarded-For: 30.30.30.30 h.POST("/user", func(c context.Context, ctx *app.RequestContext) { // method 1 customClientIPFunc := func(ctx *app.RequestContext) string { return "127.0.0.1" } ctx.SetClientIPFunc(customClientIPFunc) ip := ctx.ClientIP() // ip == "127.0.0.1" // method 2 _, cidr, _ := net.ParseCIDR("127.0.0.1/32") opts := app.ClientIPOptions{ RemoteIPHeaders: []string{"X-Forwarded-For", "X-Real-IP"}, TrustedCIDRs: []*net.IPNet{cidr}, } ctx.SetClientIPFunc(app.ClientIPWithOption(opts)) ip = ctx.ClientIP() // ip == "30.30.30.30" })
并发安全
func (ctx *RequestContext) Copy() *RequestContext
Copy
拷贝 RequestContext 副本,提供协程安全的访问方式。
函数签名:
func (ctx *RequestContext) Copy() *RequestContext 示例: h.POST("/user", func(c context.Context, ctx *app.RequestContext) { ctx1 := ctx.Copy() go func(context *app.RequestContext) { // safely }(ctx1) })