字节赫兹 框架教程 一请求上下文之请求(三)

简介: 字节赫兹 框架教程 一请求上下文之请求

字节赫兹 框架教程 一请求上下文之请求(二)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)
})
相关文章
|
8月前
|
监控 前端开发 网络协议
GB/T 28181-2016多响应消息传输探究
我们在实现Android平台GB28181设备接入模块的时候,有遇到发送多条记录的情况,本文主要探讨下GB28181多响应传输。
|
3天前
|
数据采集 搜索推荐 API
python爬虫如何处理请求频率限制?
【2月更文挑战第21天】【2月更文挑战第64篇】python爬虫如何处理请求频率限制?
|
4天前
字节赫兹 框架教程 一请求上下文之请求(二)
字节赫兹 框架教程 一请求上下文之请求
44 0
|
4天前
|
存储 安全 中间件
字节赫兹 框架教程 一请求上下文之请求(一)
字节赫兹 框架教程 一请求上下文之请求
25 0
|
6月前
|
监控 流计算
Flink 指标参数源码解读(读取数量、发送数量、发送字节数、接收字节数等)(上)
Flink 指标参数源码解读(读取数量、发送数量、发送字节数、接收字节数等)(上)
60 1
|
存储 算法
【实测】大白话讲requests发送请求的不同参数类型(上)
【实测】大白话讲requests发送请求的不同参数类型(上)
|
XML JSON 前端开发
【实测】大白话讲requests发送请求的不同参数类型(下)
【实测】大白话讲requests发送请求的不同参数类型(下)
|
BI 索引
HID 入门学习:标准请求和类请求
HID 入门学习:标准请求和类请求
198 0
|
传感器
十四、差错控制(检错编码)
十四、差错控制(检错编码)
十四、差错控制(检错编码)
|
应用服务中间件
设置请求编码
设置编码,改成我们习惯的中文输出