golang处理HTTP问题详情(Problem Details)的插件库go-problemdetails的使用
Golang处理HTTP问题详情(Problem Details)的插件库go-problemdetails的使用
简介
go-problemdetails
是一个实现了RFC 7807标准(Problem Details for HTTP APIs)的Golang包。它可以帮助开发者以标准化的方式返回HTTP API错误信息。
安装
go get github.com/mvmaasakkers/go-problemdetails
基本用法
ProblemDetails
结构体实现了error
接口,可以作为错误使用。ProblemType
接口可以用来创建预定义的ProblemDetails
扩展,同样实现了error
接口。
简单创建
根据HTTP状态码创建ProblemDetails
:
problemDetails := problemdetails.NewHTTP(http.StatusNotFound)
这将生成一个JSON格式的响应:
{
"type": "about:blank",
"title": "Not Found",
"status": 404
}
或XML格式:
<problem xmlns="urn:ietf:rfc:7807">
<type>about:blank</type>
<title>Not Found</title>
<status>404</status>
</problem>
详细创建
使用更详细的构造函数:
problemDetails := problemdetails.New(
http.StatusNotFound,
"https://example.net/problem/object_not_found",
"Object not found",
"Object with id 1234 was not found, another id should be given.",
"https://api.example.net/objects/1234"
)
这将生成:
{
"type": "https://example.net/problem/object_not_found",
"title": "Object not found",
"status": 404,
"detail": "Object with id 1234 was not found, another id should be given.",
"instance": "https://api.example.net/objects/1234"
}
或XML格式:
<problem xmlns="urn:ietf:rfc:7807">
<type>https://example.net/problem/object_not_found</type>
<title>Object not found</title>
<status>404</status>
<detail>Object with id 1234 was not found, another id should be given.</detail>
<instance>https://api.example.net/objects/1234</instance>
</problem>
HTTP辅助函数
为方便使用,提供了两个输出处理器:
ProblemDetails.ServeJSON
用于JSON格式ProblemDetails.ServeXML
用于XML格式
示例:
problemdetails.NewHTTP(http.StatusNotFound).ServeJSON(w, r)
完整示例
下面是一个完整的HTTP服务器示例:
package main
import (
"net/http"
"github.com/mvmaasakkers/go-problemdetails"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// 返回404错误
problemdetails.NewHTTP(http.StatusNotFound).ServeJSON(w, r)
})
http.HandleFunc("/object", func(w http.ResponseWriter, r *http.Request) {
// 返回自定义错误
pd := problemdetails.New(
http.StatusNotFound,
"https://example.net/problem/object_not_found",
"Object not found",
"Object with id 1234 was not found, another id should be given.",
"https://api.example.net/objects/1234",
)
pd.ServeJSON(w, r)
})
http.ListenAndServe(":8080", nil)
}
这个示例展示了如何使用go-problemdetails
库来返回标准化的HTTP错误响应。
更多关于golang处理HTTP问题详情(Problem Details)的插件库go-problemdetails的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang处理HTTP问题详情(Problem Details)的插件库go-problemdetails的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用go-problemdetails处理HTTP问题详情
go-problemdetails是一个用于处理HTTP问题详情(RFC 7807)的Golang库,它提供了一种标准化的方式来表示HTTP API中的错误信息。下面我将详细介绍如何使用这个库。
安装
首先安装go-problemdetails库:
go get github.com/StevenACoffman/go-problemdetails
基本用法
1. 创建问题详情响应
package main
import (
"net/http"
"github.com/StevenACoffman/go-problemdetails"
)
func main() {
http.HandleFunc("/example", func(w http.ResponseWriter, r *http.Request) {
// 创建一个问题详情响应
detail := problemdetails.NewProblem(
"https://example.com/probs/out-of-credit",
"You do not have enough credit.",
"Your current balance is 30, but that costs 50.",
http.StatusForbidden,
)
// 可选:添加自定义字段
detail.With("balance", 30).
With("accounts", []string{"/account/12345", "/account/67890"})
// 发送响应
problemdetails.ServeProblem(w, r, detail)
})
http.ListenAndServe(":8080", nil)
}
2. 使用预定义的问题类型
func handler(w http.ResponseWriter, r *http.Request) {
// 使用预定义的问题类型
detail := problemdetails.NewStatusProblem(http.StatusNotFound)
problemdetails.ServeProblem(w, r, detail)
}
3. 自定义中间件处理错误
func ProblemDetailsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
var detail *problemdetails.Problem
switch e := err.(type) {
case *problemdetails.Problem:
detail = e
case error:
detail = problemdetails.NewStatusProblem(http.StatusInternalServerError).
With("error", e.Error())
default:
detail = problemdetails.NewStatusProblem(http.StatusInternalServerError)
}
problemdetails.ServeProblem(w, r, detail)
}
}()
next.ServeHTTP(w, r)
})
}
高级用法
1. 自定义问题类型
// 定义自定义问题类型
var InsufficientCreditProblem = problemdetails.NewProblemType(
"https://example.com/probs/insufficient-credit",
"Insufficient Credit",
)
func creditHandler(w http.ResponseWriter, r *http.Request) {
detail := problemdetails.NewProblemFromType(
InsufficientCreditProblem,
"Your credit balance is too low",
"Current balance: 30, required: 50",
http.StatusForbidden,
).With("balance", 30).With("required", 50)
problemdetails.ServeProblem(w, r, detail)
}
2. 与标准库错误集成
func someOperation() error {
return problemdetails.NewStatusProblem(http.StatusBadRequest).
With("details", "Invalid input parameter").
With("field", "username")
}
func handler(w http.ResponseWriter, r *http.Request) {
if err := someOperation(); err != nil {
if pd, ok := err.(*problemdetails.Problem); ok {
problemdetails.ServeProblem(w, r, pd)
return
}
// 处理其他类型的错误
}
// 正常处理
}
3. 从错误中提取问题详情
func extractProblemDetails(err error) *problemdetails.Problem {
if pd, ok := err.(*problemdetails.Problem); ok {
return pd
}
return problemdetails.NewStatusProblem(http.StatusInternalServerError).
With("error", err.Error())
}
响应示例
使用上述代码生成的响应如下:
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"status": 403,
"balance": 30,
"accounts": [
"/account/12345",
"/account/67890"
]
}
最佳实践
- 使用标准问题类型:尽可能使用预定义的标准问题类型
- 包含足够信息:提供足够的信息帮助客户端理解问题
- 保持一致性:在整个API中保持一致的错误格式
- 适当的状态码:使用正确的HTTP状态码
- 文档化:在API文档中记录可能返回的问题类型
go-problemdetails库提供了一种符合RFC 7807标准的方式来处理HTTP API中的错误,使客户端能够以一致的方式理解和处理错误情况。