响应

RequestContext 中与响应相关的功能。
func (ctx *RequestContext) SetContentType(contentType string)
func (ctx *RequestContext) SetContentTypeBytes(contentType []byte)
func (ctx *RequestContext) SetConnectionClose()
func (ctx *RequestContext) SetStatusCode(statusCode int)
func (ctx *RequestContext) Status(code int)
func (ctx *RequestContext) NotFound()
func (ctx *RequestContext) NotModified()
func (ctx *RequestContext) Redirect(statusCode int, uri []byte)
func (ctx *RequestContext) Header(key, value string)
func (ctx *RequestContext) SetCookie(name, value string, maxAge int, path, domain string, sameSite protocol.CookieSameSite, secure, httpOnly bool)
func (ctx *RequestContext) AbortWithStatus(code int)
func (ctx *RequestContext) AbortWithError(code int, err error) *errors.Error 

SetContentType

设置 Content-Type。

函数签名:

func (ctx *RequestContext) SetContentType(contentType string)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.Write([]byte(`{"foo":"bar"}`))
    ctx.SetContentType("application/json; charset=utf-8")
    // Content-Type: application/json; charset=utf-8
})

SetContentTypeBytes

[]byte 方式设置 Content-Type。

函数签名:

func (ctx *RequestContext) SetContentTypeBytes(contentType []byte)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.Write([]byte(`{"foo":"bar"}`))
    ctx.SetContentType([]byte("application/json; charset=utf-8"))
    // Content-Type: application/json; charset=utf-8
})

SetConnectionClose

设置 Connection: close,告知客户端服务器想关闭连接。

函数签名:

func (ctx *RequestContext) SetConnectionClose()

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.SetConnectionClose()
})

SetStatusCode

设置 Status Code。

函数签名:

func (ctx *RequestContext) SetStatusCode(statusCode int)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.SetStatusCode(consts.StatusOK)
    // Status Code: 200
})

Status

设置 Status Code,SetStatusCode 的别名。

函数签名:

func (ctx *RequestContext) Status(code int)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.Status(consts.StatusOK)
    // Status Code: 200
})

NotFound

设置 Status Code 代码为 404。

函数签名:

func (ctx *RequestContext) NotFound()

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.NotFound()
    // Status Code: 404
})

NotModified

设置 Status Code 代码为 304。

函数签名:

func (ctx *RequestContext) NotModified()

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.NotModified()
    // Status Code: 304
})

Redirect

设置 Status Code 代码以及要跳转的地址。

函数签名:

func (ctx *RequestContext) Redirect(statusCode int, uri []byte)

示例:

// internal redirection
// GET http://www.example.com:8888/user
h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.Redirect(consts.StatusFound, []byte("/pet"))
})
// GET http://www.example.com:8888/pet
h.GET("/pet", func(c context.Context, ctx *app.RequestContext) {
    ctx.String(consts.StatusOK, "cat")
})

// external redirection
// GET http://www.example.com:8888/user
h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.Redirect(consts.StatusFound, []byte("http://www.example1.com:8888/pet"))
})
// GET http://www.example1.com:8888/pet
h.GET("/pet", func(c context.Context, ctx *app.RequestContext) {
    ctx.String(consts.StatusOK, "cat")
})

Header

设置或删除指定 Header。

函数签名:

func (ctx *RequestContext) Header(key, value string)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.Header("My-Name", "tom")
    ctx.Header("My-Name", "")
    ctx.Header("My-Name-Not-Exists", "yes")
})

SetCookie

设置 Cookie。

函数签名:

func (ctx *RequestContext) SetCookie(name, value string, maxAge int, path, domain string, sameSite protocol.CookieSameSite, secure, httpOnly bool)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.SetCookie("user", "hertz", 1, "/", "localhost", protocol.CookieSameSiteLaxMode, true, true)
    cookie := ctx.Response.Header.Get("Set-Cookie") 
    // cookie == "user=hertz; max-age=1; domain=localhost; path=/; HttpOnly; secure; SameSite=Lax"
})

Chrome 从 2024 年第一季度开始,禁用了 1% 的用户的第三方 Cookie,拦截 SameSite 属性为 None 的第三方 Cookie。 通过引入分区 Cookie(也称为 CHIPS),允许在跨站请求中携带第三方 Cookie。

自版本 0.8.0 起,Hertz 实验性地支持了分区 Cookie。该实现遵循当前的 [RFC 草案](((https://www.ietf.org/archive/id/draft-cutler-httpbis-partitioned-cookies-01.html#name-partitioned-cookies-with-th)) 开发,并可能随着草案的迭代而调整。

示例:

func SetPartitionedCookie(ctx *app.RequestContext, name, value string, maxAge int, path, domain string, sameSite protocol.CookieSameSite, secure, httpOnly bool) {
   if path == "" {
      path = "/"
   }
   cookie := protocol.AcquireCookie()
   defer protocol.ReleaseCookie(cookie)
   // It is recommended to use the __Host prefix when setting partitioned cookies 
   // to make them bound to the hostname (and not the registrable domain).
   cookie.SetKey(name)
   cookie.SetValue(url.QueryEscape(value))
   cookie.SetMaxAge(maxAge)
   // if name has __Host prefix, Path must be set to "/”.
   cookie.SetPath(path)
   cookie.SetDomain(domain)
   // Partitioned cookies must be set with Secure.
   cookie.SetSecure(secure)
   cookie.SetHTTPOnly(httpOnly)
   cookie.SetSameSite(sameSite)
   cookie.SetPartitioned(true)
    // Set-Cookie: user=hertz; max-age=1; domain=localhost; path=/; HttpOnly; secure; SameSite=None; Partitioned

ctx.Response.Header.SetCookie(cookie)
}

func main() {
   h := server.Default()

   h.GET("/partitioned", func(ctx context.Context, c *app.RequestContext) {
      SetPartitionedCookie(c, "user", "hertz", 1, "/", "localhost", protocol.CookieSameSiteNoneMode, true, true)
      c.JSON(consts.StatusOK, utils.H{"partitioned": "yes"})
   })

   h.Spin()
}

AbortWithStatus

设置 Status Code 并终止后续的 Handler。

函数签名:

func (ctx *RequestContext) AbortWithStatus(code int)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.AbortWithStatus(consts.StatusOK)
}, func(c context.Context, ctx *app.RequestContext) {
    // will not execute
})

AbortWithError

设置 Status Code 收集 Error 并终止后续的 Handler,返回 Error。

函数签名:

func (ctx *RequestContext) AbortWithError(code int, err error) *errors.Error 

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.AbortWithError(consts.StatusOK, errors.New("hertz error"))
	err := ctx.Errors.String()
	// err == "Error #01: hertz error"
}, func(c context.Context, ctx *app.RequestContext) {
    // will not execute
})

ResponseHeader 对象

使用 RequestContext.Response.Header 获取 ResponseHeader 对象,该对象提供了以下方法获取/设置响应头部。

函数签名 说明
func (h *ResponseHeader) IsHTTP11() bool 判断是否是 HTTP/1.1 协议,true 表示是 HTTP/1.1 协议
func (h *ResponseHeader) SetHeaderLength(length int) 设置响应头的大小
func (h *ResponseHeader) GetHeaderLength() 获取响应头的大小
func (h *ResponseHeader) SetContentRange(startPos, endPos, contentLength int) 在响应头中设置 Content-Range: bytes startPos-endPos/contentLength,如 Content-Range: bytes 1-5/10
func (h *ResponseHeader) NoDefaultContentType() bool 获取未指定 Content-Type 时的默认发送行为,false 表示发送默认 Content-Type 的值,true 表示不发送,默认 Content-Type 的值为 text/plain; charset=utf-8
func (h *ResponseHeader) SetNoDefaultContentType(b bool) 设置未指定 Content-Type 时的默认发送行为,false 表示发送默认 Content-Type 的值,true 表示不发送,默认 Content-Type 的值为 text/plain; charset=utf-8
func (h *ResponseHeader) SetContentType(contentType string) 设置 Content-Type
func (h *ResponseHeader) ContentType() []byte 获取 Content-Type
func (h *ResponseHeader) SetContentTypeBytes(contentType []byte) 设置 Content-Type
func (h *ResponseHeader) ContentLength() int 获取 Content-Length,可以是负值,-1 表示 Transfer-Encoding: chunked,-2 表示 Transfer-Encoding: identity
func (h *ResponseHeader) SetContentLength(contentLength int) 设置 Content-Length,可以是负值,-1 表示 Transfer-Encoding: chunked,-2 表示 Transfer-Encoding: identity
func (h *ResponseHeader) SetContentLengthBytes(contentLength []byte) 设置 []byte 类型的 Content-Length,可以是负值,-1 表示 Transfer-Encoding: chunked,-2 表示 Transfer-Encoding: identity
func (h *ResponseHeader) CopyTo(dst *ResponseHeader) 返回响应头的副本,在对响应头存在竞争访问时可以使用
func (h *ResponseHeader) GetHeaders() []argsKV 以键值对的形式返回所有响应头
func (h *ResponseHeader) VisitAll(f func(key, value []byte)) 遍历所有 Header 的键值并执行 f 函数
func (h *ResponseHeader) Get(key string) string 获取键为 key 的值,并发安全
func (h *ResponseHeader) GetAll(key string) []string 获取 []byte 类型的键为 key 的所有值(用于获取存在相同 key 的多个值),并发安全
func (h *ResponseHeader) Peek(key string) []byte 获取 []byte 类型的键为 key 的值,并发不安全,竞争访问时使用 Get
func (h *ResponseHeader) PeekAll(key string) [][]byte 获取 []byte 类型的键为 key 的所有值(用于获取存在相同 key 的多个值),并发不安全,竞争访问时使用 GetAll
func (h *ResponseHeader) Set(key, value string) 设置 Header 键值,用于为同一个 Key 设置单个 Header
func (h *ResponseHeader) SetBytesV(key string, value []byte) 设置 []byte 类型的 Header 键值,用于为同一个 Key 设置单个 Header
func (h *ResponseHeader) Add(key, value string) 设置 Header 键值,用于为同一个 Key 设置多个 Header,但 key 会覆盖以下 Header: Content-Type, Content-Length, Connection, Cookie, Transfer-Encoding, Host, User-Agent
func (h *ResponseHeader) AddArgBytes(key, value []byte, noValue bool) 添加 Header 键值(与 Add 不同,key 一定不会被规范化且 key 为 Content-Type, Content-Length, Content-Encoding, Connection, Server, Set-Cookie, Transfer-Encoding 时不会做特殊处理)
func (h *ResponseHeader) SetArgBytes(key, value []byte, noValue bool) 设置 Header 键值(与 Set 不同,key 一定不会被规范化且 key 为 Content-Type, Content-Length, Content-Encoding, Connection, Server, Set-Cookie, Transfer-Encoding 时不会做特殊处理)
func (h *ResponseHeader) Del(key string) 删除 Header 中键为 key 的键值对
func (h *ResponseHeader) DelBytes(key []byte) 删除 Header 中键为 key 的键值对
func (h *ResponseHeader) AppendBytes(dst []byte) []byte 将完整的 Header 附加到 dst 中并返回
func (h *ResponseHeader) Header() []byte 获取 []byte 类型的完整的 Header
func (h *ResponseHeader) PeekLocation() []byte 返回 Header 中 key 为 Location 的值
func (h *ResponseHeader) Cookie(cookie *Cookie) bool 填充给定 cookie.Key 的 cookie,如果 cookie.Key 不存在则返回 false
func (h *RequestHeader) FullCookie() []byte 以字节数组形式返回完整的 cookie
func (h *ResponseHeader) SetCookie(cookie *Cookie) 设置 Cookie 的键值
func (h *ResponseHeader) VisitAllCookie(f func(key, value []byte)) 遍历所有 Cookie 的键值并执行 f 函数
func (h *ResponseHeader) DelAllCookies() 删除所有 Cookie
func (h *ResponseHeader) DelCookie(key string) 删除响应头中键为 key 的 Cookie,若要删除来自客户端的 Cookie,请使用 DelClientCookie 函数
func (h *ResponseHeader) DelCookieBytes(key []byte) 删除响应头中键为 key 的 Cookie,若要删除来自客户端的 Cookie,请使用 DelClientCookieBytes 函数
func (h *ResponseHeader) DelClientCookie(key string) 删除来自客户端键为 key 的 Cookie
func (h *ResponseHeader) DelClientCookieBytes(key []byte) 删除来自客户端键为 key 的 Cookie
func (h *ResponseHeader) SetConnectionClose(close bool) 在响应头中设置 Connection: close 标志
func (h *ResponseHeader) ConnectionClose() bool 判断是否包含 Connection: close
func (h *ResponseHeader) ContentEncoding() []byte 获取 Content-Encoding
func (h *ResponseHeader) SetContentEncoding(contentEncoding string) 设置 Content-Encoding
func (h *ResponseHeader) SetContentEncodingBytes(contentEncoding []byte) 设置 Content-Encoding
func (h *ResponseHeader) SetCanonical(key, value []byte) 设置 Header 键值,假设该键是规范形式
func (h *ResponseHeader) Server() []byte 返回 Header 中 key 为 Server 的值
func (h *ResponseHeader) SetServerBytes(server []byte) 设置 Header 中 key 为 Server 的值
func (h *ResponseHeader) MustSkipContentLength() bool 判断是否有响应 body(HTTP/1.1 协议规定,响应状态码为 1xx、204、304 时没有响应 body)
func (h *ResponseHeader) StatusCode() int 获取响应状态码
func (h *ResponseHeader) SetStatusCode(statusCode int) 设置响应状态码
func (h *ResponseHeader) Len() int 返回 Header 的数量
func (h *ResponseHeader) DisableNormalizing() 禁用 Header 名字的规范化 (首字母和破折号后第一个字母大写)
func (h *ResponseHeader) IsDisableNormalizing() bool 是否禁用 Header 名字的规范化,默认不禁用
func (h *ResponseHeader) Trailer() *Trailer 获取 Trailer
func (h *ResponseHeader) SetProtocol(p string) 设置协议名
func (h *ResponseHeader) GetProtocol() string 获取协议名
func (h *ResponseHeader) Reset() 重置响应头
func (h *ResponseHeader) ResetSkipNormalize() 重置响应头,除了 disableNormalizing 状态
func (h *ResponseHeader) ResetConnectionClose() 重置 connectionClose 标志为 false 并删除 Connection Header

渲染

支持对 JSON,HTML,Protobuf 等的渲染。(更多内容请参考 渲染)

func (ctx *RequestContext) Render(code int, r render.Render)
func (ctx *RequestContext) String(code int, format string, values ...interface{})
func (ctx *RequestContext) ProtoBuf(code int, obj interface{})
func (ctx *RequestContext) JSON(code int, obj interface{})
func (ctx *RequestContext) PureJSON(code int, obj interface{})
func (ctx *RequestContext) IndentedJSON(code int, obj interface{})
func (ctx *RequestContext) HTML(code int, name string, obj interface{})
func (ctx *RequestContext) Data(code int, contentType string, data []byte)
func (ctx *RequestContext) XML(code int, obj interface{})

Body

func (ctx *RequestContext) SetBodyStream(bodyStream io.Reader, bodySize int)
func (ctx *RequestContext) SetBodyString(body string)
func (ctx *RequestContext) Write(p []byte) (int, error)
func (ctx *RequestContext) WriteString(s string) (int, error)
func (ctx *RequestContext) AbortWithMsg(msg string, statusCode int)
func (ctx *RequestContext) AbortWithStatusJSON(code int, jsonObj interface{})

SetBodyStream

设置 Body Stream 和可选的 Body 大小。该函数用于 Hertz Server 的流式处理,详情可见 流式处理

注意:bodySize 小于 0 时数据全部写入,大于等于 0 时根据设置的 bodySize 大小写入数据。

函数签名:

func (ctx *RequestContext) SetBodyStream(bodyStream io.Reader, bodySize int)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    data := "hello world"
    r := strings.NewReader(data)
    ctx.SetBodyStream(r, -1) // Body: "hello world"
})

h.GET("/user1", func(c context.Context, ctx *app.RequestContext) {
    data := "hello world"
    r1 := strings.NewReader(data)
    ctx.SetBodyStream(r1, 5) // Body: "hello"
})

SetBodyString

设置 Body。

函数签名:

func (ctx *RequestContext) SetBodyString(body string)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.SetBodyString("hello world") // Body: "hello world"
})

Write

将字节数组 p 添加到 Body 中。

函数签名:

func (ctx *RequestContext) Write(p []byte) (int, error)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.Write([]byte("hello"))
    ctx.Write([]byte(" "))
    ctx.Write([]byte("world"))
    // Body: "hello world"
})

WriteString

设置 Body 并返回大小。

函数签名:

func (ctx *RequestContext) WriteString(s string) (int, error)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    size, _ := ctx.WriteString("hello world")// Body: "hello world", size == 11
})

AbortWithMsg

设置 Status Code 和 Body 并终止后续的 Handler。

函数签名:

func (ctx *RequestContext) AbortWithMsg(msg string, statusCode int)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.AbortWithMsg("abort", consts.StatusOK)
}, func(c context.Context, ctx *app.RequestContext) {
    // will not execute
})

AbortWithStatusJSON

设置 Status Code 和 Json 格式 Body 并终止后续的 Handler。

函数签名:

func (ctx *RequestContext) AbortWithStatusJSON(code int, jsonObj interface{})

示例:

 h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
  ctx.AbortWithStatusJSON(consts.StatusOK, utils.H{
   "foo":  "bar",
   "html": "<b>",
  })
 }, func(c context.Context, ctx *app.RequestContext) {
  // will not execute
 })

文件操作

func (ctx *RequestContext) File(filepath string)
func (ctx *RequestContext) FileAttachment(filepath, filename string)
func (ctx *RequestContext) FileFromFS(filepath string, fs *FS)

File

将指定文件写入到 Body Stream。

函数签名:

func (ctx *RequestContext) File(filepath string)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.File("./main.go")
})

FileAttachment

将指定文件写入到 Body Stream 并通过 Content-Disposition 指定为下载。

函数签名:

func (ctx *RequestContext) FileAttachment(filepath, filename string)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.FileAttachment("./main.go")
})

FileFromFS

将指定文件写入到 Body Stream。

函数签名:

func (ctx *RequestContext) FileFromFS(filepath string, fs *FS)

示例:

h.GET("/user", func(c context.Context, ctx *app.RequestContext) {
    ctx.FileFromFS("./main.go", &app.FS{
        Root:               ".",
        IndexNames:         nil,
        GenerateIndexPages: false,
        AcceptByteRange:    true,
    })
})

其他

func (ctx *RequestContext) Flush() error 
func (ctx *RequestContext) GetResponse() (dst *protocol.Response) 

Flush

把数据刷入被劫持的 Response Writer 中。(更多内容请参考 response_writer)

函数签名:

func (ctx *RequestContext) Flush() error 

GetResponse

获取 Response 对象。

函数签名:

func (ctx *RequestContext) GetResponse() (dst *protocol.Response)

最后修改 January 18, 2024 : Upload volo blog (#936) (1fc8abb)