Golang中gin.Negotiate的示例代码
Golang中gin.Negotiate的示例代码 如果有人能发布一个示例,解释如何根据请求的 Accept 头部返回不同格式的响应,那将非常有帮助。
我搜索了很长时间,找不到任何关于如何根据 Accept 头部实际渲染响应的示例。 而且肯定没有关于如何根据包含 API 版本号的自定义媒体类型(如 “application/vnd.health.json;version=1.0.0” 或 “application/vnd.kliket.health+v1.json”)进行渲染的示例。
以下是我目前所了解到的内容:
func Health(c *gin.Context) {
startupTime := c.MustGet("startupTime").(time.Time)
status := models.NewHealth(startupTime)
c.Negotiate(http.StatusOK, gin.Negotiate{
Offered: []string{"application/vnd.health.json;version=1.0.0", gin.MIMEJSON, gin.MIMEYAML, gin.MIMEXML, gin.MIMEHTML},
HTMLName: "",
HTMLData: status,
JSONData: status,
XMLData: status,
YAMLData: status,
Data: status,
})
}
我可以获取除 HTML 和我自定义的版本化媒体类型(这是首选类型)之外的所有格式。
我找不到任何关于 HTMLName 应该填入什么内容,或者如何为我的自定义媒体类型注册 Render 的示例。
更多关于Golang中gin.Negotiate的示例代码的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中gin.Negotiate的示例代码的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
以下是使用 gin.Negotiate 根据 Accept 头部返回不同格式响应的完整示例,包括自定义媒体类型的处理:
package main
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
)
type Health struct {
Status string `json:"status" xml:"status" yaml:"status"`
Startup time.Time `json:"startup" xml:"startup" yaml:"startup"`
Timestamp time.Time `json:"timestamp" xml:"timestamp" yaml:"timestamp"`
}
// 自定义渲染器
type CustomRenderer struct {
Version string
Data interface{}
}
func (r CustomRenderer) Render(w http.ResponseWriter) error {
// 这里实现自定义格式的渲染逻辑
// 例如:根据版本号返回不同的JSON结构
return nil
}
func (r CustomRenderer) WriteContentType(w http.ResponseWriter) {
w.Header().Set("Content-Type", "application/vnd.health.json;version="+r.Version)
}
func main() {
r := gin.Default()
// 注册自定义渲染器
gin.MIME("application/vnd.health.json;version=1.0.0", []string{".v1json"})
gin.MIME("application/vnd.health.json;version=2.0.0", []string{".v2json"})
r.GET("/health", func(c *gin.Context) {
startupTime := time.Now().Add(-1 * time.Hour) // 示例启动时间
status := Health{
Status: "healthy",
Startup: startupTime,
Timestamp: time.Now(),
}
c.Negotiate(http.StatusOK, gin.Negotiate{
Offered: []string{
"application/vnd.health.json;version=1.0.0",
"application/vnd.health.json;version=2.0.0",
gin.MIMEJSON,
gin.MIMEYAML,
gin.MIMEXML,
gin.MIMEHTML,
},
HTMLName: "health.html", // HTML模板名称
HTMLData: gin.H{
"status": status.Status,
"startup": startupTime.Format(time.RFC3339),
"timestamp": time.Now().Format(time.RFC3339),
},
JSONData: status,
XMLData: status,
YAMLData: status,
Data: status,
})
})
// 自定义媒体类型处理器
r.GET("/health-custom", func(c *gin.Context) {
startupTime := time.Now().Add(-1 * time.Hour)
status := Health{
Status: "healthy",
Startup: startupTime,
Timestamp: time.Now(),
}
accept := c.Request.Header.Get("Accept")
switch accept {
case "application/vnd.health.json;version=1.0.0":
c.Render(http.StatusOK, CustomRenderer{
Version: "1.0.0",
Data: status,
})
case "application/vnd.health.json;version=2.0.0":
// 版本2.0.0的响应结构
v2Response := map[string]interface{}{
"health": map[string]interface{}{
"status": status.Status,
"uptime": time.Since(startupTime).String(),
"timestamp": status.Timestamp,
},
"version": "2.0.0",
}
c.JSON(http.StatusOK, v2Response)
default:
c.JSON(http.StatusOK, status)
}
})
// 使用NegotiateFormat的另一种方式
r.GET("/health-negotiate", func(c *gin.Context) {
startupTime := time.Now().Add(-1 * time.Hour)
status := Health{
Status: "healthy",
Startup: startupTime,
Timestamp: time.Now(),
}
switch c.NegotiateFormat(
"application/vnd.health.json;version=1.0.0",
"application/vnd.health.json;version=2.0.0",
gin.MIMEJSON,
gin.MIMEYAML,
gin.MIMEXML,
) {
case "application/vnd.health.json;version=1.0.0":
c.Header("Content-Type", "application/vnd.health.json;version=1.0.0")
c.JSON(http.StatusOK, gin.H{
"data": status,
"version": "1.0.0",
})
case "application/vnd.health.json;version=2.0.0":
c.Header("Content-Type", "application/vnd.health.json;version=2.0.0")
c.JSON(http.StatusOK, gin.H{
"health": gin.H{
"status": status.Status,
"details": status,
},
"api_version": "2.0.0",
})
case gin.MIMEYAML:
c.YAML(http.StatusOK, status)
case gin.MIMEXML:
c.XML(http.StatusOK, status)
default:
c.JSON(http.StatusOK, status)
}
})
// 设置HTML模板
r.LoadHTMLGlob("templates/*")
r.Run(":8080")
}
对于HTML模板(templates/health.html):
<!DOCTYPE html>
<html>
<head>
<title>Health Status</title>
</head>
<body>
<h1>Health Status: {{.status}}</h1>
<p>Startup Time: {{.startup}}</p>
<p>Current Time: {{.timestamp}}</p>
</body>
</html>
要测试不同格式的响应,可以使用curl命令:
# 请求JSON格式
curl -H "Accept: application/json" http://localhost:8080/health
# 请求XML格式
curl -H "Accept: application/xml" http://localhost:8080/health
# 请求YAML格式
curl -H "Accept: application/x-yaml" http://localhost:8080/health
# 请求自定义版本1.0.0
curl -H "Accept: application/vnd.health.json;version=1.0.0" http://localhost:8080/health
# 请求自定义版本2.0.0
curl -H "Accept: application/vnd.health.json;version=2.0.0" http://localhost:8080/health
# 请求HTML格式
curl -H "Accept: text/html" http://localhost:8080/health
这个示例展示了:
- 使用
gin.Negotiate处理多种格式 HTMLName指定HTML模板文件名称- 自定义媒体类型的注册和处理
- 通过
NegotiateFormat手动处理内容协商 - 不同版本API响应的实现方式

