请求上下文 RequestContext 是用于保存 HTTP 请求和设置 HTTP 响应的上下文,它提供了许多方便的 API 接口帮助用户开发。
Hertz 在 HandlerFunc 设计上,同时提供了一个标准 context.Context 和一个 RequestContext 作为函数的入参。 handler/middleware 函数签名为:
type HandlerFunc func(c context.Context, ctx *RequestContext)
context.Context 与 RequestContext 都有存储值的能力,具体选择使用哪一个上下文有个简单依据:所储存值的生命周期和所选择的上下文要匹配。
ctx 主要用来存储请求级别的变量,请求结束就回收了,特点是查询效率高(底层是 map),协程不安全,且未实现 context.Context 接口。
c 作为上下文在中间件 /handler 之间传递,协程安全。所有需要 context.Context 接口作为入参的地方,直接传递 c 即可。
func (ctx *RequestContext) Host() []byte
func (ctx *RequestContext) FullPath() string
func (ctx *RequestContext) SetFullPath(p string)
func (ctx *RequestContext) Path() []byte
func (ctx *RequestContext) Param(key string) string
func (ctx *RequestContext) Query(key string) string
func (ctx *RequestContext) DefaultQuery(key, defaultValue string) string
func (ctx *RequestContext) GetQuery(key string) (string, bool)
func (ctx *RequestContext) QueryArgs() *protocol.Args
func (ctx *RequestContext) URI() *protocol.URI
获取请求的主机地址。
函数签名:
func (ctx *RequestContext) Host() []byte
示例:
// GET http://example.com
h.GET("/", func(c context.Context, ctx *app.RequestContext) {
host := ctx.Host() // host == []byte("example.com")
})
获取匹配的路由完整路径,对于未匹配的路由返回空字符串。
函数签名:
func (ctx *RequestContext) FullPath() string
示例:
h := server.Default(server.WithHandleMethodNotAllowed(true))
// GET http://example.com/user/bar
h.GET("/user/:name", func(c context.Context, ctx *app.RequestContext) {
fpath := ctx.FullPath() // fpath == "/user/:name"
})
// GET http://example.com/bar
h.NoRoute(func(c context.Context, ctx *app.RequestContext) {
fpath := ctx.FullPath() // fpath == ""
})
// POST http://example.com/user/bar
h.NoMethod(func(c context.Context, ctx *app.RequestContext) {
fpath := ctx.FullPath() // fpath == ""
})
设置 FullPath 的值。
注意:FullPath 由路由查找时分配,通常你不需要使用 SetFullPath 去覆盖它。
函数签名:
func (ctx *RequestContext) SetFullPath(p string)
示例:
h.GET("/user/:name", func(c context.Context, ctx *app.RequestContext) {
ctx.SetFullPath("/v1/user/:name")
fpath := ctx.FullPath() // fpath == "/v1/user/:name"
})
获取请求的路径。
注意:出现参数路由时 Path 给出命名参数匹配后的路径,而 FullPath 给出原始路径。
函数签名:
func (ctx *RequestContext) Path() []byte
示例:
// GET http://example.com/user/bar
h.GET("/user/:name", func(c context.Context, ctx *app.RequestContext) {
path := ctx.Path() // path == []byte("/user/bar")
})
获取路由参数的值。
函数签名:
func (ctx *RequestContext) Param(key string) string
示例:
// GET http://example.com/user/bar
h.GET("/user/:name", func(c context.Context, ctx *app.RequestContext) {
name := ctx.Param("name") // name == "bar"
id := ctx.Param("id") // id == ""
})
获取路由 Query String 参数中指定属性的值,如果没有返回空字符串。
函数签名:
func (ctx *RequestContext) Query(key string) string
示例:
// GET http://example.com/user?name=bar
h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
name := ctx.Query("name") // name == "bar"
id := ctx.Query("id") // id == ""
})
获取路由 Query String 参数中指定属性的值,如果没有返回设置的默认值。
函数签名:
func (ctx *RequestContext) DefaultQuery(key, defaultValue string) string
示例:
// GET http://example.com/user?name=bar&&age=
h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
name := ctx.DefaultQuery("name", "tom") // name == "bar"
id := ctx.DefaultQuery("id", "123") // id == "123"
age := ctx.DefaultQuery("age", "45") // age == ""
})
获取路由 Query String 参数中指定属性的值以及属性是否存在。
函数签名:
func (ctx *RequestContext) GetQuery(key string) (string, bool)
示例:
// GET http://example.com/user?name=bar&&age=
h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
name, hasName := ctx.GetQuery("name") // name == "bar", hasName == true
id, hasId := ctx.GetQuery("id") // id == "", hasId == false
age, hasAge := ctx.GetQuery("age") // age == "", hasAge == true
})
获取路由 Query String 参数对象。
函数签名:
func (ctx *RequestContext) QueryArgs() *protocol.Args
Args 对象提供了以下方法获取/设置 Query String 参数。
函数签名 | 说明 |
---|---|
func (a *Args) Set(key, value string) | 设置 Args 对象 key 的值 |
func (a *Args) Reset() | 重置 Args 对象 |
func (a *Args) CopyTo(dst *Args) | 将 Args 对象拷贝到 dst |
func (a *Args) Del(key string) | 删除 Args 对象 key 的键值对 |
func (a *Args) DelBytes(key []byte) | 删除 Args 对象字节数组类型 key 的键值对 |
func (a *Args) Has(key string) bool | 获取 Args 对象是否存在 key 的键值对 |
func (a *Args) String() string | 将 Args 对象转换为字符串类型的 Query String |
func (a *Args) QueryString() []byte | 将 Args 对象转换为字节数组类型的 Query String |
func (a *Args) ParseBytes(b []byte) | 解析字节数组并将键值对存入 Args 对象 |
func (a *Args) Peek(key string) []byte | 获取 Args 对象 key 的值 |
func (a *Args) PeekExists(key string) (string, bool) | 获取 Args 对象 key 的值以及是否存在 |
func (a *Args) Len() int | 获取 Args 对象键值对数量 |
func (a *Args) AppendBytes(dst []byte) []byte | 将 Args 对象 Query String 附加到 dst 中并返回 |
func (a *Args) VisitAll(f func(key, value []byte)) | 遍历 Args 对象所有的键值对 |
func (a *Args) WriteTo(w io.Writer) (int64, error) | 将 Args 对象 Query String 写入 io.Writer 中 |
func (a *Args) Add(key, value string) | 添加 Args 对象键为 key 的值 |
示例: |
// GET http://example.com/user?name=bar&&age=&&pets=dog&&pets=cat
h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
args := ctx.QueryArgs()
// get information from args
s := args.String() // s == "name=bar&age=&pets=dog&pets=cat"
qs := args.QueryString() // qs == []byte("name=bar&age=&pets=dog&pets=cat")
cpqs := args.AppendBytes([]byte(nil)) // cpqs == []byte("name=bar&age=&pets=dog&pets=cat")
name := args.Peek("name") // name == []byte("bar")
hasName := args.Has("name") // hasName == true
age, hasAge := args.PeekExists("age") // age == "", hasAge == true
len := args.Len() // len == 4
args.VisitAll(func(key, value []byte) {
// 1. key == []byte("name"), value == []byte("bar")
// 2. key == []byte("age"), value == nil
// 3. key == []byte("pets"), value == []byte("dog")
// 4. key == []byte("pets"), value == []byte("cat")
})
// send information to io.Writer
req := protocol.AcquireRequest()
n, err := args.WriteTo(req.BodyWriter())
// n == 31 err == nil
s := req.BodyBuffer().String()
// s == "name=bar&age=&pets=dog&pets=cat"
// change args
var newArgs protocol.Args
args.CopyTo(&newArgs)
newArgs.Set("version", "v1")
version := newArgs.Peek("version") //version == []byte("v1")
newArgs.Del("age")
hasAgeAfterDel := newArgs.Has("age") // hasAgeAfterDel == false
newArgs.DelBytes([]byte("name"))
hasNameAfterDel := newArgs.Has("name") // hasNameAfterDel == false
newArgs.Add("name", "foo")
newName := newArgs.Peek("name") //newName == []byte("foo")
newArgs.Reset()
empty := newArgs.String() // empty == ""
// parse args
var newArgs2 protocol.Args
newArgs2.ParseBytes([]byte("name=bar&age=20"))
nqs2 := newArgs2.String() // nqs2 == "name=bar&age=20"
})
返回请求的 URI 对象。
函数签名:
func (ctx *RequestContext) URI() *protocol.URI
URI 对象提供了以下方法获取/设置 URI。
函数签名 | 说明 |
---|---|
func (u *URI) CopyTo(dst *URI) | 拷贝 URI 对象的副本到 dst |
func (u *URI) QueryArgs() | *Args 获取 Args 对象 |
func (u *URI) Hash() []byte | 获取 Hash 值,比如 http://example.com/user?baz=123#qwe 的 Hash 是 qwe |
func (u *URI) SetHash(hash string) | 设置 Hash |
func (u *URI) SetHashBytes(hash []byte) | 设置 []byte 类型 Hash |
func (u *URI) Username() []byte | 获取 Username |
func (u *URI) SetUsername(username string) | 设置 Username |
func (u *URI) SetUsernameBytes(username []byte) | 设置 []byte 类型 Username |
func (u *URI) Password() []byte | 获取 Password |
func (u *URI) SetPassword(password string) | 设置 Password |
func (u *URI) SetPasswordBytes(password []byte) | 设置 []byte 类型 Password |
func (u *URI) QueryString() []byte | 获取 Query String,比如 http://example.com/user?baz=123 的 Query String 是 baz=123 |
func (u *URI) SetQueryString(queryString string) | 设置 Query String |
func (u *URI) SetQueryStringBytes(queryString []byte) | 设置 []byte 类型的 Query String |
func (u *URI) Path() []byte | 获取 Path,比如 http://example.com/user/he%20rtz 的 Path 是 /user/he rtz |
func (u *URI) PathOriginal() []byte | 获取未转义的 Path,比如 http://example.com/user/he%20rtz 的 Path 是 /user/he%20rtz |
func (u *URI) SetPath(path string) | 设置 Path |
func (u *URI) SetPathBytes(path []byte) | 设置 []byte 类型 Path |
func (u *URI) String() string | 获取完整 URI 比如 http://example.com/user?baz=123 的完整 URI 是 http://example.com/user?baz=123 |
func (u *URI) FullURI() []byte | 获取 []byte 类型的完整 URI |
func (u *URI) Scheme() []byte | 获取协议,如 http |
func (u *URI) SetScheme(scheme string) | 设置协议 |
func (u *URI) SetSchemeBytes(scheme []byte) | 设置 []byte 类型的协议 |
func (u *URI) Host() []byte | 获取 Host,比如 http://example.com/user 的 Host 是 example.com |
func (u *URI) SetHost(host string) | 设置 Host |
func (u *URI) SetHostBytes(host []byte) | 设置 []byte 类型 Host |
func (u *URI) LastPathSegment() []byte | 获取 Path 的最后一部分,比如 Path /foo/bar/baz.html 的最后一部分是 baz.html |
func (u *URI) Update(newURI string) | 更新 URI |
func (u *URI) UpdateBytes(newURI []byte) | 更新 []byte 类型的 URI |
func (u *URI) Parse(host, uri []byte) | 初始化 URI |
func (u *URI) AppendBytes(dst []byte) []byte | 将完整的 URI 赋值到 dst 中并返回 dst |
func (u *URI) RequestURI() []byte | 获取 RequestURI,比如 http://example.com/user?baz=123 的 RequestURI 是 /user?baz=123 |
func (u *URI) Reset() | 重置 URI |
// RequestHeader
func (h *RequestHeader) Add(key, value string)
func (h *RequestHeader) Set(key, value string)
func (h *RequestHeader) Header() []byte
func (h *RequestHeader) String() string
func (h *RequestHeader) VisitAll(f func(key, value []byte))
// RequestContext
func (ctx *RequestContext) IsGet() bool
func (ctx *RequestContext) IsHead() bool
func (ctx *RequestContext) IsPost() bool
func (ctx *RequestContext) Method() []byte
func (ctx *RequestContext) ContentType() []byte
func (ctx *RequestContext) IfModifiedSince(lastModified time.Time) bool
func (ctx *RequestContext) Cookie(key string) []byte
func (ctx *RequestContext) UserAgent() []byte
func (ctx *RequestContext) GetHeader(key string) []byte
添加或设置键为 key 的 Header。
注意:Add 通常用于为同一个 Key 设置多个 Header,若要为同一个 Key 设置单个 Header 请使用 Set。当作用于 Content-Type, Content-Length, Connection, Cookie, Transfer-Encoding, Host, User-Agent 这些 Header 时,使用多个 Add 会覆盖掉旧值。
函数签名:
func (h *RequestHeader) Add(key, value string)
示例:
hertz.GET("/example", func(c context.Context, ctx *app.RequestContext) {
ctx.Request.Header.Add("hertz1", "value1")
ctx.Request.Header.Add("hertz1", "value2")
ctx.Request.Header.SetContentTypeBytes([]byte("application/x-www-form-urlencoded"))
contentType1 := ctx.Request.Header.ContentType()
// contentType1 == []byte("application/x-www-form-urlencoded")
ctx.Request.Header.Add("Content-Type", "application/json; charset=utf-8")
hertz1 := ctx.Request.Header.GetAll("hertz1")
// hertz1 == []string{"value1", "value2"}
contentType2 := ctx.Request.Header.ContentType()
// contentType2 == []byte("application/json; charset=utf-8")
})
设置 Header 键值。
注意:Set 通常用于为同一个 Key 设置单个 Header,若要为同一个 Key 设置多个 Header 请使用 Add。
函数签名:
func (h *RequestHeader) Set(key, value string)
示例:
hertz.GET("/example", func(c context.Context, ctx *app.RequestContext) {
ctx.Request.Header.Set("hertz1", "value1")
ctx.Request.Header.Set("hertz1", "value2")
ctx.Request.Header.SetContentTypeBytes([]byte("application/x-www-form-urlencoded"))
contentType1 := ctx.Request.Header.ContentType()
// contentType1 == []byte("application/x-www-form-urlencoded")
ctx.Request.Header.Set("Content-Type", "application/json; charset=utf-8")
hertz1 := ctx.Request.Header.GetAll("hertz1")
// hertz1 == []string{"value2"}
contentType2 := ctx.Request.Header.ContentType()
// contentType2 == []byte("application/json; charset=utf-8")
})
获取 []byte 类型的完整的 Header。
函数签名:
func (h *RequestHeader) Header() []byte
示例:
hertz.GET("/example", func(c context.Context, ctx *app.RequestContext) {
ctx.Request.Header.Set("hertz1", "value1")
ctx.Request.Header.Set("hertz1", "value2")
ctx.Request.Header.SetContentTypeBytes([]byte("application/x-www-form-urlencoded"))
contentType1 := ctx.Request.Header.ContentType()
// contentType1 == []byte("application/x-www-form-urlencoded")
ctx.Request.Header.Set("Content-Type", "application/json; charset=utf-8")
hertz1 := ctx.Request.Header.GetAll("hertz1")
// hertz1 == []string{"value2"}
contentType2 := ctx.Request.Header.ContentType()
// contentType2 == []byte("application/json; charset=utf-8")
})
获取完整的 Header。
函数签名:
func (h *RequestHeader) String() string
示例:
hertz.GET("/example", func(c context.Context, ctx *app.RequestContext) {
ctx.Request.Header.Set("hertz1", "value1")
header := ctx.Request.Header.String()
// header == "GET /example HTTP/1.1
//User-Agent: PostmanRuntime-ApipostRuntime/1.1.0
//Host: localhost:8888
//Cache-Control: no-cache
//Accept: */*
//Accept-Encoding: gzip, deflate, br
//Connection: keep-alive
//Hertz1: value1"
})
遍历所有 Header 的键值并执行 f 函数。
函数签名:
func (h *RequestHeader) VisitAll(f func(key, value []byte))
示例:
hertz.GET("/example", func(c context.Context, ctx *app.RequestContext) {
ctx.Request.Header.Add("Hertz1", "value1")
ctx.Request.Header.Add("Hertz1", "value2")
var hertzString []string
ctx.Request.Header.VisitAll(func(key, value []byte) {
if string(key) == "Hertz1" {
hertzString = append(hertzString, string(value))
}
})
// hertzString == []string{"value1", "value2"}
})
获取请求方法的类型。
函数签名:
func (ctx *RequestContext) Method() []byte
示例:
// POST http://example.com/user
h.Any("/user", func(c context.Context, ctx *app.RequestContext) {
method := ctx.Method() // method == []byte("POST")
})
获取请求头 Content-Type 的值。
函数签名:
func (ctx *RequestContext) ContentType() []byte
示例:
// POST http://example.com/user
// Content-Type: application/json
h.Post("/user", func(c context.Context, ctx *app.RequestContext) {
contentType := ctx.ContentType() // contentType == []byte("application/json")
})
判断时间是否超过请求头 If-Modified-Since 的值。
注意:如果请求头不包含 If-Modified-Since 也返回 true。
函数签名:
func (ctx *RequestContext) IfModifiedSince(lastModified time.Time) bool
示例:
// POST http://example.com/user
// If-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMT
h.Post("/user", func(c context.Context, ctx *app.RequestContext) {
t2022, _ := time.Parse(time.RFC1123, "Wed, 21 Oct 2022 07:28:00 GMT")
ifModifiedSince := ctx.IfModifiedSince(t2022) // ifModifiedSince == false
t2024, _ := time.Parse(time.RFC1123, "Wed, 21 Oct 2024 07:28:00 GMT")
ifModifiedSince = ctx.IfModifiedSince(t2024) // ifModifiedSince == true
})
获取请求头 Cookie 中 key 的值。
函数签名:
func (ctx *RequestContext) Cookie(key string) []byte
示例:
// POST http://example.com/user
// Cookie: foo_cookie=choco; bar_cookie=strawberry
h.Post("/user", func(c context.Context, ctx *app.RequestContext) {
fCookie := ctx.Cookie("foo_cookie") // fCookie == []byte("choco")
bCookie := ctx.Cookie("bar_cookie") // bCookie == []byte("strawberry")
noneCookie := ctx.Cookie("none_cookie") // noneCookie == nil
})
获取请求头 User-Agent 的值。
函数签名:
func (ctx *RequestContext) UserAgent() []byte
示例:
// POST http://example.com/user
// User-Agent: Chrome/51.0.2704.103 Safari/537.36
h.Post("/user", func(c context.Context, ctx *app.RequestContext) {
ua := ctx.UserAgent() // ua == []byte("Chrome/51.0.2704.103 Safari/537.36")
})
获取请求头中 key 的值。
函数签名:
func (ctx *RequestContext) GetHeader(key string) []byte
示例:
// POST http://example.com/user
// Say-Hello: hello
h.Post("/user", func(c context.Context, ctx *app.RequestContext) {
customHeader := ctx.GetHeader("Say-Hello") // customHeader == []byte("hello")
})
func (ctx *RequestContext) GetRawData() []byte
func (ctx *RequestContext) Body() ([]byte, error)
func (ctx *RequestContext) RequestBodyStream() io.Reader
func (ctx *RequestContext) MultipartForm() (*multipart.Form, error)
func (ctx *RequestContext) PostForm(key string) string
func (ctx *RequestContext) DefaultPostForm(key, defaultValue string) string
func (ctx *RequestContext) GetPostForm(key string) (string, bool)
func (ctx *RequestContext) PostArgs() *protocol.Args
func (ctx *RequestContext) FormValue(key string) []byte
func (ctx *RequestContext) SetFormValueFunc(f FormValueFunc)
获取请求的 body 数据,如果发生错误返回 error。
函数签名:
func (ctx *RequestContext) Body() ([]byte, error)
示例:
// POST http://example.com/pet
// Content-Type: application/json
// {"pet":"cat"}
h.Post("/pet", func(c context.Context, ctx *app.RequestContext) {
data, err := ctx.Body() // data == []byte("{\"pet\":\"cat\"}") , err == nil
})
获取请求的 BodyStream。
函数签名:
func (ctx *RequestContext) RequestBodyStream() io.Reader
示例:
// POST http://example.com/user
// Content-Type: text/plain
// abcdefg
h := server.Default(server.WithStreamBody(true))
h.Post("/user", func(c context.Context, ctx *app.RequestContext) {
sr := ctx.RequestBodyStream()
data, _ := io.ReadAll(sr) // data == []byte("abcdefg")
})
获取 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="name"
// tom
h.POST("/user", func(c context.Context, ctx *app.RequestContext) {
form, err := ctx.MultipartForm()
name := form.Value["name"][0] // name == "tom"
})
按名称检索 multipart.Form.Value,返回给定 name 的第一个值。
注意:该函数支持从 application/x-www-form-urlencoded 和 multipart/form-data 这两种类型的 content-type 中获取 value 值,且不支持获取文件值。
函数签名:
func (ctx *RequestContext) PostForm(key string) string
示例:
// 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.PostForm("name") // name == "tom"
})
按名称检索 multipart.Form.Value,返回给定 name 的第一个值,如果不存在返回 defaultValue。
注意:该函数支持从 application/x-www-form-urlencoded 和 multipart/form-data 这两种类型的 content-type 中获取 value 值,且不支持获取文件值。
函数签名:
func (ctx *RequestContext) DefaultPostForm(key, defaultValue string) string
示例:
// 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.PostForm("name", "jack") // name == "tom"
age := ctx.PostForm("age", "10") // age == "10"
})
获取 application/x-www-form-urlencoded 参数对象。(详情请参考 Args 对象)
函数签名:
func (ctx *RequestContext) PostArgs() *protocol.Args
示例:
// POST http://example.com/user
// Content-Type: application/x-www-form-urlencoded
// name=tom&pet=cat&pet=dog
h.POST("/user", func(c context.Context, ctx *app.RequestContext) {
args := ctx.PostArgs()
name := args.Peek("name") // name == "tom"
var pets []string
args.VisitAll(func(key, value []byte) {
if string(key) == "pet" {
pets = append(pets, string(value))
}
})
// pets == []string{"cat", "dog"}
})
按照以下顺序获取 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
})
若 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
获取 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"
})
按名称检索 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
})
保存 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"
})
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
执行下一个 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 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)
获取 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)
设置 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)
获取最后一个 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"
})
}
获取当前执行的 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
})
终止后续的 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
})
获取后续的 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
func (ctx *RequestContext) ClientIP() string
func (ctx *RequestContext) SetClientIPFunc(f 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
})
若 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)
})