[Go Web Development]管理错误请求
浏览:1036 次

内容继续。当请求处理函数createMovieHandler接收到客户端发送的JSON请求体时,它可以正常工作。但此时你可能会想:
如果客户端不发送JSON,例如XML或一些随机字节,该怎么办?
如果JSON格式不正确或包含错误,会发生什么?
如果JSON类型与我们试图解码的类型不匹配怎么办?
如果请求中甚至不包含身体怎么办?
现在让我们来看看!
#将XML内容作为请求正文发送
$curl-d'<?xml版本=“1.0”编码=“UTF-8”?>;&书信电报;注意><;收件人>Alice收件人><;/注意>'本地主机:4000/v1/movies
{
“错误”:“查找值开头的字符'\u003c'无效”
}
#发送一些格式错误的JSON(注意结尾的逗号)
$curl-d'{“title”:“Moana”,}'本地主机:4000/v1/movies
{
“错误”:“查找对象键字符串开头的字符“}”无效”
}
#发送JSON数组而不是对象
$curl-d'[“foo”,“bar”]'本地主机:4000/v1/movies
{
“错误”:“json:无法将数组解组为结构{Title-string\”json:\\“Title\\”\“;年份int32\”json:\\“年\\”;运行时int32\“json:\ \\”运行时\\“\”;流派[]string\”jsson:\\”流派\\“”}“
}
#发送数字“title”值(不是字符串)
$curl-d“{”title“:123}”本地主机:4000/v1/movies
{
“error”:“json:无法将数字解组到Go结构字段中。string类型的title”
}

#发送空请求正文
$curl-X POST本地主机:4000/v1/movies
{
“错误”:“EOF”
}
在所有这些情况下,我们都可以看到createMovieHandler正在根据正确的请求进行处理。当它接收到无法解码到输入结构中的无效请求时,它将不会进行任何进一步的处理。客户端将收到一个JSON响应,其中包含Decode()方法返回的错误消息。
对于私有API服务,如果它对公众不可用,则返回不会产生影响。你不需要做任何其他事情。
但对于面向公共的API服务,错误消息本身并不理想。有些过于详细,显示了有关底层API实现的信息。其他错误消息不够描述性(如“EOF”),并且存在一些难以理解的错误。使用的格式或语言也不一致。
为了改进这一点,我们将解释如何对Decode()返回的错误进行分类,并将其替换为更清晰、更易于操作的错误消息,以帮助客户端准确地调试JSON错误。
对解码错误进行分类
此时,在我们的app构造中,Decode()方法可能会返回以下五种类型的错误:
错误类型
原因
json.Syntax错误
正在解码的JSON存在语法问题。
io.Err意外EOF
正在解码的JSON存在语法问题。
json.InvalidUnmarshalError错误
解码目标无效(通常是因为它不是指针)。这实际上是我们的app代码的问题,而不是JSON本身。
io.EOF
正在解码的JSON为空。
对这些潜在的错误进行分类(我们可以使用Go的errors.is()和error。as()函数将使createMovieHandler中的代码更长、更复杂。这个逻辑也需要在整个项目的其他处理程序中重复。
因此,在cmd/api/helpersGo中创建一个新的readJSON()helper函数。JSON将从请求正文中正常解码,然后错误将被分类,并在必要时用我们自己的自定义消息替换。
如果您关注这一系列文章,请继续并将以下代码添加到cmd/api/helper。go文件:
文件:cmd/api/helpers.go
成套设备总管

导入(
“编码/json”
“错误”
“fmt”
“io”
“net/http”
“strconv”
“github.com/julienschmidt/httprouter”
)
func(app*application)readJSON(w http.ResponseWriter,r*http.Request,dst接口{})错误{
//将请求正文解析为dst
错误:=json.NewDecoder(r.Body).Decode(dst)
如果出错!=无{
//如果分析过程中出现错误,请开始分类
var语法错误*json.syntaxError
var unmarshalTypeError*json.UnmarshalType错误
var invalidUnmarshalError*json.InvalidUnmashalError
开关{
//使用错误。As()函数检查错误类型是否为*json.SyntaxError。如果是,则返回错误
案例错误。作为(错误,语法错误(&S)):
返回fmt。错误(“正文包含格式错误的JSON(在字符%d处)”,语法错误偏移量)
//在某些情况下,Decode()函数可能会返回io。错误由于语法错误导致意外的EOF错误。
案例错误。是(err,io.ErrUnexpectedEOF):
返回错误。新建(“正文包含格式错误的JSON”)
//同时捕获*json UnmarshalTypeError错误。这些错误是由JSON值和接收对象之间的不匹配引起的。如果错误对应于特定的to字段,
//我们可以指出哪个字段是错误的,以方便客户d