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

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

字节赫兹 框架教程 一请求上下文之请求(二)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)
})
目录
打赏
0
0
0
0
5
分享
相关文章
|
10月前
字节赫兹 框架教程 一请求上下文之请求(二)
字节赫兹 框架教程 一请求上下文之请求
74 0
字节赫兹 框架教程 一请求上下文之请求(一)
字节赫兹 框架教程 一请求上下文之请求
86 0
IOS网络请求(可变请求和不可变的区别)
有些方法在可变请求的时候是不能用的。有些刚开始不一定指定它的url那么可以在后面进行变动。那么就用可变请求。 通常我们的URL请求可能是一组,并不是一个,而且我们的URL请求也是会不停的根据流程在变化的,所以我们要仍然使用NSURLRequest这个对象是不能随时的进行一个URL的变化的,因此我们的NSMUtableURLRequest这个对象,可以用来解决我们的。
514 0
【芯片前端】延迟一拍出数的握手型ram结构的一次探索
【芯片前端】延迟一拍出数的握手型ram结构的一次探索
153 0
H264(NAL简介与I帧判断)
1、NAL全称Network Abstract Layer, 即网络抽象层。         在H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL)和网络抽象层面(NAL)。
1895 0
FPGA设计8位十进制计数器异步/同步模块以及m序列码产生器模块
本文主要介绍了FPGA设计8位十进制计数器异步/同步模块以及m序列码产生器模块
1344 0
FPGA设计8位十进制计数器异步/同步模块以及m序列码产生器模块
【实测】大白话讲requests发送请求的不同参数类型(上)
【实测】大白话讲requests发送请求的不同参数类型(上)
【实测】大白话讲requests发送请求的不同参数类型(下)
【实测】大白话讲requests发送请求的不同参数类型(下)
HID 入门学习:标准请求和类请求
HID 入门学习:标准请求和类请求
542 0
cheerp 减小调用转换类型的开销的方式
这个文章主要描述在cheerp环境下, c++和javascript代码减小类型转换开销 在cheerp,基本数据类型的C ++阵列如char,unsigned char,short,unsigned short,int,unsigned int,float和double由JavaScript键入相应类型的阵列的支持。
2119 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等