为了账号安全,请及时绑定邮箱和手机立即绑定

在 REST API 上进行错误处理

在 REST API 上进行错误处理

Go
蝴蝶不菲 2021-12-20 19:04:51
我很陌生,已经部署了一个带有 API 端点的小型服务。我听说/读到 go 不使用,try/catch所以我想弄清楚如何从我的 API 的服务调用中“捕获”发生的任何问题,并确保资源服务器不会停机。我的 API 代码如下所示..我有一个routes.go包含以下内容的文件package mainimport (    "net/http"    "github.com/gorilla/mux")type Route struct {    Name        string    Method      string    Pattern     string    HandlerFunc http.HandlerFunc}type Routes []Routefunc NewRouter() *mux.Router {    router := mux.NewRouter().StrictSlash(true)    for _, route := range routes {        router.            Methods(route.Method).            Path(route.Pattern).            Name(route.Name).            Handler(route.HandlerFunc)    }    return router}var routes = Routes{    Route{        "CustomerLocationCreate",        "POST",        "/tracking/customer",        CustomerLocationCreate,    },}我有一个 handlers.gopackage mainimport (    "encoding/json"    "net/http"    "io"    "io/ioutil")//curl -H "Content-Type: application/json" -d '{"userId":"1234"}' http://localhost:8181/tracking/customerfunc CustomerLocationCreate(w http.ResponseWriter, r *http.Request) {    var location CustomerLocation    body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))    if err != nil {        panic(err)    }    if err := r.Body.Close(); err != nil {        panic(err)    }    if err := json.Unmarshal(body, &location); err != nil {        w.Header().Set("Content-Type", "application/json; charset=UTF-8")        w.WriteHeader(422) // unprocessable entity        if err := json.NewEncoder(w).Encode(err); err != nil {            panic(err)        }    }    c := RepoCreateCustomerLocation(location)    w.Header().Set("Content-Type", "application/json; charset=UTF-8")    w.WriteHeader(http.StatusCreated)    if err := json.NewEncoder(w).Encode(c); err != nil {        panic(err)    }    HandleCustomerLocationChange(c);}我的问题是我应该如何修改HandleCustomerLocationChange(...) function and if necessaryCustomerLocationChange(..)` 处理程序以正确处理错误,以便在发生错误时,我的整个 API 不会出现故障?
查看完整描述

1 回答

?
饮歌长啸

TA贡献1951条经验 获得超3个赞

Go 提出了一种不同的方法,错误不是例外,它们是正常事件,只是不太常见。


以上面的代码为例:


body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))

if err != nil {

    panic(err)

}

在这里,恐慌(没有恢复)终止了进程,关闭了 Web 服务器。似乎对没有完全阅读请求的反应过于严厉。


你想让我做什么?告诉提出请求的客户可能是合适的:


body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))

if err != nil {

    http.Error(w, err.Error(), http.StatusBadRequest)

    return

}

您可能希望返回一个 json 编码的响应,或者向客户端提供通用消息以避免暴露太多,并记录特定的错误详细信息。


对于一般函数,将错误作为最后一个返回参数返回是惯用的。在你提到的具体例子中:


func HandleCustomerLocationChange(custLoc CustomerLocation) 

...

    conn, err := amqp.Dial(...)

    failOnError(err, "Failed to connect to RabbitMQ")

相反,检查连接是否失败,并将错误返回给调用者。在调用函数中处理它,或添加信息并将其向上传播到调用堆栈。


func HandleCustomerLocationChange(custLoc CustomerLocation) error

...

    conn, err := amqp.Dial(...)

    if err != nil {

        return fmt.Errorf("failed to connect to RabbitMQ: %s", err)

    }

以这种方式传播错误给出了根本原因的简明解释,例如5 个为什么技术,例如:


“没有更新客户端位置:没有连接到rabbitmq:网络地址1.2.3无法访问”


另一个约定是先处理错误并尽早返回。这有助于减少嵌套。


查看完整回答
反对 回复 2021-12-20
  • 1 回答
  • 0 关注
  • 164 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号