通过标头错误代码返回或JSON响应终止http请求

时间:2015-08-16 19:57:51

标签: json http go error-handling

如何从Handlefunc调用多个错误返回函数?

我在这个链接中找到了类似于我需要的东西: Golang: terminating or aborting an HTTP request

因此,在某些情况下,我需要使用HTTP错误代码返回错误响应,如下所示(代码来自上面的链接):

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
   // examine incoming params
   if !ok {
   http.Error(w, `Invalid input params!`, http.StatusBadRequest) 
   return
          }

   // Do normal API serving
})

但是,在某些情况下,我需要向Web客户端返回JSON响应:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    // examine incoming params
    if !ok {
        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusBadRequest)
        str := `{"Result":"","Error":"No valide Var"}`
        fmt.Fprint(w, str)
        return
    }

    // Do normal API serving
})

问题是:我想将错误处理部分放在一个单独的错误函数中,并将我想要呈现的错误类型作为函数参数/方法传递。但是,我不知道如何在语义上做到这一点。

所以,在要点:

 if isJsonError {
    //call HTTP function to serve JSON error
   }
 if isHTTPError {
   //call HTTP function to serve an HTTP error
}

我怎样才能在语义上做到这一点?如果我不清楚,请提前抱歉。谢谢!

P.S。:我还阅读了以下博文: http://blog.golang.org/error-handling-and-go

有一个部分称为"简化重复性错误处理" - 它很酷但我需要简化多个重复的错误处理,我无法弄清楚如何。

2 个答案:

答案 0 :(得分:14)

这样的事情:

func badReq(w http.ResponseWriter, isJson bool, err string) {
    if !isJson {
        http.Error(w, err, http.StatusBadRequest)
        return
    }
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusBadRequest)
    fmt.Fprintf(w, `{"result":"","error":%q}`, err)
}



http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    if !ok {
        badReq(w, true, "no valid var")
        return
    }
})

答案 1 :(得分:6)

自定义处理程序方法(根据博客文章) - 带有func(w http.ResponseWriter, r *http.Request) error签名肯定是一个很好的方法。您可以返回&HTTPError{err, code}&JSONError{err, code}ServeHTTP检查并正确渲染。 e.g。

type Handler struct {
    h func(http.ResponseWriter, *http.Request) error
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // Execute the handler function
    err := h.h(w, r)
    if err != nil {
        switch e := err.(type) {
        case *HTMLError:
             // Render a HTML response, calling e.Err and e.Code
        case *JSONError:
             // Render a JSON response
        default:
             // Handle all other 'generic' errors you don't inspect
        }
    }
}

type HTMLError struct {
    Err error
    Code int
}

func (e *HTMLError) Error() string {
    return e.Err.Error()
}

type JSONError struct {
    Err error
    Code int
}

func (e *JSONError) Error() string {
    return e.Err.Error()
}

func SomeHandler(w http.ResponseWriter, r *http.Request) error {
    // examine incoming params
    if !ok {
        // Your returns are also enforced here - avoiding subtle bugs
        return &HTTPError{errors.New("No good!"), http.StatusBadRequest}
    }
}

小插件:我wrote a blog post关于使用与上述示例类似的处理程序集中错误处理的方法。