Hertz的RequestContext 中与响应相关的功能解析
Header
// 设置响应的 Content-Type 头,告诉客户端返回的数据类型(如 "application/json")。
func (ctx *RequestContext) SetContentType(contentType string)
// 设置响应的 Content-Type 头,参数是字节形式(性能更高,避免字符串转换)。
func (ctx *RequestContext) SetContentTypeBytes(contentType []byte)
// 设置响应头 Connection: close,告诉客户端在处理完当前请求后关闭连接。
func (ctx *RequestContext) SetConnectionClose()
// 设置 HTTP 响应的状态码(如 200、404 等)。
func (ctx *RequestContext) SetStatusCode(statusCode int)
// 设置 HTTP 响应的状态码(是 SetStatusCode 的简化版)。
func (ctx *RequestContext) Status(code int)
// 返回 404 状态码,表示请求的资源未找到。
func (ctx *RequestContext) NotFound()
// 返回 304 状态码,表示资源未修改(通常用于缓存控制)。
func (ctx *RequestContext) NotModified()
// 重定向客户端到指定的 URI,并设置状态码(如 302 临时重定向)。
func (ctx *RequestContext) Redirect(statusCode int, uri []byte)
// 设置响应头的键值对(如 "Cache-Control": "no-cache")。
func (ctx *RequestContext) Header(key, value string)
// 设置一个 Cookie,可以指定名称、值、过期时间、路径、域名等属性。
func (ctx *RequestContext) SetCookie(name, value string, maxAge int, path, domain string, sameSite protocol.CookieSameSite, secure, httpOnly bool)
// 终止请求处理并返回指定的状态码(如 401 表示未授权)。
func (ctx *RequestContext) AbortWithStatus(code int)
// 终止请求处理并返回指定的状态码和错误信息(通常用于错误处理)。
func (ctx *RequestContext) AbortWithError(code int, err error) *errors.Error
用法
c.SetContentType("application/json; charset=utf-8")
// Content-Type: application/json; charset=utf-8
c.SetContentType("application/json; charset=utf-8")
// Content-Type: application/json; charset=utf-8
c.SetConnectionClose()
// 直接返回相应的状态码
c.SetStatusCode(consts.StatusOK)
// Status Code: 200
c.Status(consts.StatusOK)
// Status Code: 200
c.NotFound()
// Status Code: 404
c.NotModified()
// Status Code: 304
// 跳转
c.Redirect(consts.StatusFound, []byte("/pet"))
c.Redirect(consts.StatusFound, []byte("http://www.example1.com:8888/pet"))
// 设置header值
c.Header("My-Name", "tom")
c.Header("My-Name", "")
c.Header("My-Name-Not-Exists", "yes")
// cookie
c.SetCookie("user", "hertz", 1, "/", "localhost", protocol.CookieSameSiteLaxMode, true, true)
cookie := c.Response.Header.Get("Set-Cookie")
// cookie == "user=hertz; max-age=1; domain=localhost; path=/; HttpOnly; secure; SameSite=Lax"
// 设置 Status Code 并终止后续的 Handler
c.AbortWithStatus(consts.StatusOK)
// 设置 Status Code 收集 Error 并终止后续的 Handler,返回 Error
c.AbortWithError(consts.StatusOK, errors.New("hertz error"))
err := c.Errors.String()
// err == "Error #01: hertz error"
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 等的渲染。
// 使用自定义的渲染器(render.Render)生成响应,适合需要高度定制化响应的场景。
func (ctx *RequestContext) Render(code int, r render.Render)
// 返回一个纯文本响应,支持格式化字符串(如 "Hello, %s!")。
func (ctx *RequestContext) String(code int, format string, values ...interface{})
// 返回一个 Protocol Buffers(Protobuf)格式的响应,适合高性能数据传输。
func (ctx *RequestContext) ProtoBuf(code int, obj interface{})
// 返回一个 JSON 格式的响应,自动将对象序列化为 JSON 字符串。
func (ctx *RequestContext) JSON(code int, obj interface{})
// 返回一个 JSON 格式的响应,但不转义 HTML 字符(如 <、> 等),适合返回原始 JSON 数据。
func (ctx *RequestContext) PureJSON(code int, obj interface{})
// 返回一个格式化后的 JSON 响应(带缩进和换行),适合调试或人类阅读。
func (ctx *RequestContext) IndentedJSON(code int, obj interface{})
// 返回一个 HTML 格式的响应,通常用于渲染模板文件。
func (ctx *RequestContext) HTML(code int, name string, obj interface{})
// 返回一个自定义 Content-Type 的二进制数据响应,适合返回文件或原始字节数据。
func (ctx *RequestContext) Data(code int, contentType string, data []byte)
// 返回一个 XML 格式的响应,自动将对象序列化为 XML 字符串。
func (ctx *RequestContext) XML(code int, obj interface{})
JSON
JSON
Hertz 支持渲染 JSON
。
示例代码:
func main() {
h := server.Default(server.WithHostPorts("127.0.0.1:8080"))
// utils.H is a shortcut for map[string]interface{}
h.GET("/someJSON", func(ctx context.Context, c *app.RequestContext) {
c.JSON(consts.StatusOK, utils.H{"message": "hey", "status": consts.StatusOK})
})
h.Spin()
}
你也可以使用一个结构体。
示例代码:
func main() {
h := server.Default(server.WithHostPorts("127.0.0.1:8080"))
h.GET("/moreJSON", func(ctx context.Context, c *app.RequestContext) {
var msg struct {
Company string `json:"company"`
Location string
Number int
}
msg.Company = "company"
msg.Location = "location"
msg.Number = 123
// Note that msg.Company becomes "company" in the JSON
// Will output : {"company": "company", "Location": "location", "Number": 123}
c.JSON(consts.StatusOK, msg)
})
h.Spin()
}
PureJSON
JSON
使用 Unicode 替换特殊的 HTML 字符,如果你想要按照字面意义编码这些字符,你可以使用 PureJSON
。
示例代码:
func main() {
h := server.Default(server.WithHostPorts("127.0.0.1:8080"))
h.GET("/pureJson", func(ctx context.Context, c *app.RequestContext) {
c.PureJSON(consts.StatusOK, utils.H{
"html": "<p> Hello World </p>",
})
})
h.Spin()
}
IndentedJSON
IndentedJSON
将给定的结构序列化为优雅的 JSON (通过缩进 + 换行)。
示例代码:
func main() {
h := server.Default(server.WithHostPorts("127.0.0.1:8080"))
h.GET("/indentedJSON", func(ctx context.Context, c *app.RequestContext) {
var msg struct {
Company string
Location string
Number int
}
msg.Company = "company"
msg.Location = "location"
msg.Number = 123
c.IndentedJSON(consts.StatusOK, msg)
/*
will output : {
"Company": "company",
"Location": "location",
"Number": 123
}
*/
})
h.Spin()
}
配置其他 json marshal 库
hertz 默认使用开源 json 库 sonic,你也可以通过 ResetJSONMarshal
指定自己的 json 序列化库。
示例代码:
import (
"encoding/json"
"github.com/cloudwego/hertz/pkg/app/server/render"
)
func main() {
render.ResetJSONMarshal(json.Marshal)
}
完整代码
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main() {
h := server.Default(server.WithHostPorts("127.0.0.1:8080"))
// utils.H 是 map[string]interface{} 的快捷方式
h.GET(
"/someJSON", func(ctx context.Context, c *app.RequestContext) {
c.JSON(consts.StatusOK, utils.H{"message": "hey", "status": consts.StatusOK})
},
)
h.GET(
"/moreJSON", func(ctx context.Context, c *app.RequestContext) {
// 你也可以使用struct
var msg struct {
Company string `json:"company"`
Location string
Number int
}
msg.Company = "company"
msg.Location = "location"
msg.Number = 123
// Note that msg.Company becomes "company" in the JSON
// Will output : {"company": "company", "Location": "location", "Number": 123}
c.JSON(consts.StatusOK, msg)
},
)
h.GET(
"/pureJson", func(ctx context.Context, c *app.RequestContext) {
c.PureJSON(
consts.StatusOK, utils.H{
"html": "<p> Hello World </p>",
},
)
},
)
h.GET(
"/someData", func(ctx context.Context, c *app.RequestContext) {
c.Data(consts.StatusOK, "text/plain; charset=utf-8", []byte("hello"))
},
)
h.Spin()
}
Data
Data
需要你自行设置 Content-Type
,而且 Data
只接收 []byte。
示例代码:
func main() {
h := server.Default(server.WithHostPorts("127.0.0.1:8080"))
h.GET("/someData", func(ctx context.Context, c *app.RequestContext) {
c.Data(consts.StatusOK, "text/plain; charset=utf-8", []byte("hello"))
})
h.Spin()
}
HTML
加载模板文件
Hertz 提供 LoadHTMLGlob
和 LoadHTMLFiles
来加载模板文件。
示例代码:
func main(){
h := server.Default(server.WithHostPorts(":8080"))
h.LoadHTMLGlob("render/html/*")
//h.LoadHTMLFiles("render/html/index.tmpl")
h.GET("/index", func(ctx context.Context, c *app.RequestContext) {
c.HTML(http.StatusOK, "index.tmpl", utils.H{
"title": "Main website",
})
})
}
自定义分隔符
Hertz 支持自定义分隔符。
示例代码:
h := server.Default(server.WithHostPorts(":8080"))
h.Delims("{[{", "}]}")
//Left delimiter, defaults to {{.
//Right delimiter, defaults to }}.
自定义模板功能
Hertz 支持自定义模板功能,示例代码如下。
main.go:
package main
import (
"context"
"fmt"
"html/template"
"net/http"
"time"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
)
func formatAsDate(t time.Time) string {
year, month, day := t.Date()
return fmt.Sprintf("%d/%02d/%02d", year, month, day)
}
func main() {
h := server.Default(server.WithHostPorts(":8080"))
h.Delims("{[{", "}]}")
h.SetFuncMap(template.FuncMap{
"formatAsDate": formatAsDate,
})
h.LoadHTMLGlob("render/html/*")
h.GET("/raw", func(ctx context.Context, c *app.RequestContext) {
c.HTML(http.StatusOK, "template1.html", map[string]interface{}{
"now": time.Date(2017, 0o7, 0o1, 0, 0, 0, 0, time.UTC),
})
})
h.Spin()
}
template1.html:
<h1>Date: {[{.now | formatAsDate}]}</h1>
查看详细 [示例代码](hertz-examples/render/html at main · cloudwego/hertz-examples · GitHub)。
Protobuf
Hertz 支持渲染 Protobuf
。
示例代码:
package main
import (
"context"
"github.com/cloudwego/hertz-examples/render/protobuf/body"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
)
func main() {
h := server.Default(server.WithHostPorts(":8080"))
h.GET("/somePb", func(ctx context.Context, c *app.RequestContext) {
//The specific definition of protobuf is written in the "protobuf/body" file.
body := body.BodyStruct{
Body: []byte("Hello World"),
}
c.ProtoBuf(200, &body)
})
h.Spin()
}
示例代码中的 body.bodyStruct
具体定义如下。
type BodyStruct struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Body []byte `protobuf:"bytes,1,opt,name=body" json:"body,omitempty"`
}
Text
Hertz 支持渲染 string
,它需要你自行设置 format
。
示例代码:
func main() {
h := server.Default(server.WithHostPorts(":8080"))
h.GET("someText", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "message", "hello,world")
})
h.Spin()
}
XML
Hertz 支持渲染 XML
。
示例代码:
func main() {
h := server.Default(server.WithHostPorts(":8080"))
h.GET("/someXML", func(ctx context.Context, c *app.RequestContext) {
c.XML(consts.StatusOK, "hello world")
})
h.Spin()
}
自定义渲染
Hertz 在 app 包内提供了 Render
方法。
函数签名:
func (ctx *RequestContext) Render(code int, r render.Render)
如果你想要进行自定义渲染,首先要自行实现 render 包内的 Render
接口。
type Render interface {
// Render writes data with custom ContentType.
// Do not panic inside, RequestContext will handle it.
Render(resp *protocol.Response) error
// WriteContentType writes custom ContentType.
WriteContentType(resp *protocol.Response)
}
以实现 YAML
渲染为例。
示例代码:
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/protocol"
"github.com/cloudwego/hertz/pkg/protocol/consts"
"gopkg.in/yaml.v3"
)
func main() {
h := server.Default(server.WithHostPorts(":8080"))
h.GET("/someXML", func(ctx context.Context, c *app.RequestContext) {
c.Render(consts.StatusOK, YAML{Data: "hello,world"})
})
h.Spin()
}
type YAML struct {
Data interface{}
}
var yamlContentType = "application/yaml; charset=utf-8"
func (r YAML) Render(resp *protocol.Response) error {
writeContentType(resp, yamlContentType)
yamlBytes, err := yaml.Marshal(r.Data)
if err != nil {
return err
}
resp.AppendBody(yamlBytes)
return nil
}
func (r YAML) WriteContentType(w *protocol.Response) {
writeContentType(w, yamlContentType)
}
func writeContentType(resp *protocol.Response, value string) {
resp.Header.SetContentType(value)
}
本文来自博客园,作者:厚礼蝎,转载请注明原文链接:https://www.cnblogs.com/guangdelw/p/18741242
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现