有时候一个服务器应用程序需要在相同的 URI 上提供资源不同表示形式。当然这也可以手动实现,检查 Accept 请求头,设置推送的请求表单的文本。然而,当你的程序管理更多的资源和不同形式的时候,这将变得非常痛苦,你需要检查 Accept-Charset,Accept-Encoding,设置一些服务器端优先级,正确处理错误等等。
有一些 Go 的 web 框架已经艰难地实现了这个特性,但是它们不能正确地做以下的事情:
- 不处理
accept-charset - 不处理
accept-encoding - 不会发送
RFC提出的一些错误状态码(406 not acceptable)。
但是我对我来说幸运的是,Iris 始终遵循最佳实践和Web标准。
基于:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiationhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accepthttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charsethttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
实现于:
https://github.com/kataras/iris/pull/1316/commits/8ee0de51c593fe0483fbea38117c3c88e065f2ef
示例
type testdata struct {
Name string `json:"name" xml:"Name"`
Age int `json:"age" xml:"Age"`
}
通过 gzip 编码算法将资源渲染为 application/json 或者 text/html 或者 application/xml。
- 当客户端的
Accept头部包含上述之一时, - 如果接收的为空就声明为
JSON(首先声明) - 当客户端的
Accpet-Encoding头包含gzip或者为空时
app.Get("/resource", func(ctx iris.Context) {
data := testdata{
Name: "test name",
Age: 26,
}
ctx.Negotiation().JSON().XML().EncodingGzip()
_, err := ctx.Negotiate(data)
if err != nil {
ctx.Writef("%v", err)
}
})
或者在一个中间件中定义他们,然后在最后的处理器中以 nil 参数调用Negotiate。
ctx.Negotiation().JSON(data).XML(data).Any("content for */*")
ctx.Negotiate(nil)
app.Get("/resource2", func(ctx iris.Context) {
jsonAndXML := testdata{
Name: "test name",
Age: 26,
}
ctx.Negotiation().
JSON(jsonAndXML).
XML(jsonAndXML).
HTML("<h1>Test Name</h1><h2>Age 26</h2>")
ctx.Negotiate(nil)
})
文献资料
Context.Negotiotion 方法创建一次,返回 “协商构造器”,以便构建适用于特定文本类型,字符和编码算法的服务器端的可用内容。
Context.Negotiation() *context.NegotiationBuilderContext.Negotiotion 方法用于服务相同 URI 的不同表现形式的资源。当无法匹配 MIME 类型它返回 context.ErrContentNotSupported 。
Context.Negotiate(v interface{}) (int, error)v接口可以是一个iris.N结构体类型值。v接口可以是任何实现了context.ContentSelector接口的值。v接口可以是任何实现了context.ContentNegotiator接口的值。v接口可以是结构体(JSON、JSONP、XML、YAML), 或者 字符串(TEXT,HTML),或者字节切片(Markdown,Binary),或者匹配的 MIME 类型的字节切片。- 如果
v接口是nil,将会使用Context.Negotitation()构造器的内容来替代,除此之外,v接口覆写了构造器的内容(服务器的 MIME 类型通过其注册的、支持的 MIME 列表进行检索) - 通过
Negotiation()返回的构造器 的MIME,Text,JSON,XML,HTML等等方法设置MIME类型优先级。 - 通过
Negotiation()返回的构造器 的Charset方法设置字符串类型优先级。 - 通过
Negotiation()返回的构造器 的Encoding方法设置编码算法优先级。 - 通过
Negotiation()返回的构造器 的Accept,Override,XML等等方法修改Accept。
文档更新时间: 2020-08-14 10:45 作者:kuteng