如何在Go语言中进行HTTP错误处理

8
我在go语言中关于错误处理的方法有些困惑。我已经阅读了很多文章,但仍然无法将它们应用于我的代码结构中。由于我是go的新手,请帮忙解决。

主函数处理两个api:api1和api2。

func main() {
    http.HandleFunc("/offers", api1)
    http.HandleFunc("/getOffersList", api2)
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}


func api1(w http.ResponseWriter, req *http.Request) {
    validateRequestHeader(w, req, "GET")
    // code here....
}

func api2(w http.ResponseWriter, req *http.Request) {
    validateRequestHeader(w, req, "POST")
    //code here....
}

func validateRequestHeader(w http.ResponseWriter, req *http.Request, allowedMethod string) {
    // allow cross domain AJAX requests
    w.Header().Set("Content-Type", "application/json")
    if origin := req.Header.Get("Origin"); origin != "" {
        w.Header().Set("Access-Control-Allow-Origin", origin)
        w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers",
            "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
    }
    // Stop here if its Preflighted OPTIONS request
    if req.Method == "OPTIONS" {
        return
    }
    if req.Method != allowedMethod {
        response := "Only " + allowedMethod + " requests are allowed"
        http.Error(w, response, http.StatusMethodNotAllowed)
        return
    }
}

api1api2 中,都会调用函数 validateRequestHeader。如果这个函数返回 true,那么在 api1/api2 中将继续执行进一步的代码,而我不希望它这样执行。应该如何处理?

if req.Method != allowedMethod {
        response := "Only " + allowedMethod + " requests are allowed"
        http.Error(w, response, http.StatusMethodNotAllowed)
        return
    }

1
如果不通过验证,则返回。 - Warrior
@Warrior validateRequestHeader(w, req, "POST") 作为值使用。 - Jagrati
问题是我应该在这里返回什么:http.Error(w, response, http.StatusMethodNotAllowed) return - Jagrati
1
任何用于表示验证结果的信号。 - Warrior
1
惯用的 Go 语言方式是使用 validateRequestHeader 方法返回一个错误类型,并在方法调用时检查 err != nil。只有在这种情况下才能继续执行。 - Endre Simo
没有一种“正确”的方法,要学习背后的逻辑。 - Warrior
1个回答

14

这篇博客文章详细介绍了如何链接多个处理程序函数,这正是您应该做的。通过这种方式,您可以拥有验证处理程序、记录处理程序、授权处理程序等等,并将它们链接在一起。

基本上

func validator(next http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, req *http.Request) {
            if isRequestValid(req) {
                // a valid request is passed on to next handler
                next.ServeHTTP(w, req)
            } else {
                // otherwise, respond with an error
                http.Error(w, "Bad request - Go away!", 400)
            }
    }
    return http.HandlerFunc(fn)
}

func api1() http.Handler {
    fn := func(w http.ResponseWriter, req *http.Request) {
            // api 1 code
    }
    return http.HandlerFunc(fn)
}

func api2() http.Handler {
    fn := func(w http.ResponseWriter, req *http.Request) {
            // api 2 code
    }
    return http.HandlerFunc(fn)
}

然后在你的main函数中将它们串起来。

func main() {
    http.Handler("/offers", validate(api1()))
    http.Handler("/getOffersList", validate(api2()))
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

2
这个回复很好,但我会更清楚地指出验证器代码在错误时会阻塞链。 - Gianfranco Reppucci
1
@GianfrancoReppucci 我在验证器逻辑上进行了一些扩展。现在是否更清晰,它是首先执行并确定是否使用“next”处理程序? - Emil L

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接