英文:
Terminate http request via header error code return or JSON response
问题
我可以通过Handlefunc调用多个错误返回函数吗?
我在这个链接中找到了类似我所需的内容:
https://stackoverflow.com/questions/31293314/golang-terminating-or-aborting-an-http-request。
所以,在某些情况下,我需要返回带有HTTP错误代码的错误响应,如下所示(代码取自上述链接):
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// 检查传入的参数
if !ok {
http.Error(w, "无效的输入参数!", http.StatusBadRequest)
return
}
// 执行正常的API服务
})
然而,在某些情况下,我需要向Web客户端返回JSON响应:
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// 检查传入的参数
if !ok {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
str := `{"Result":"","Error":"无效的变量"}`
fmt.Fprint(w, str)
return
}
// 执行正常的API服务
})
问题是:我想将错误处理部分放在一个单独的错误函数中,并将要呈现的错误类型作为函数参数/方法传递。然而,我不知道如何在语义上实现这一点。
所以,在代码片段中:
if isJsonError {
// 调用用于提供JSON错误的HTTP函数
}
if isHTTPError {
// 调用用于提供HTTP错误的HTTP函数
}
我该如何在语义上实现这一点?如果我表达不清楚,我提前道歉。谢谢!
附注:我还阅读了以下博文:
http://blog.golang.org/error-handling-and-go
其中有一个名为"Simplifying repetitive error handling"的部分,很酷,但我需要简化多个重复的错误处理,而我无法弄清楚如何做到。
英文:
How can I call multiple error return functions from a Handlefunc?
I have found something similar to what I need in this link:
https://stackoverflow.com/questions/31293314/golang-terminating-or-aborting-an-http-request.
So, in some cases, I need to return error response with HTTP error code, like below (code taken from link above):
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
})
However, in some cases I need to return a JSON response to the web client:
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
})
Question is: I want to place the error handling part in a seperate error function and passing what type of error I want to present as a function parameter/method. However I don't know, how to do it semantically.
So, in the gist:
if isJsonError {
//call HTTP function to serve JSON error
}
if isHTTPError {
//call HTTP function to serve an HTTP error
}
How can I do that semantically? Sorry in advance, if I'm not being clear. Thank you!
P.S.: I've also read the following blogpost :
http://blog.golang.org/error-handling-and-go
There is a section there called "Simplifying repetitive error handling" - and it's cool but I need to simplify multiple repetitive error handling and I can't figure out how to.
答案1
得分: 16
类似这样:
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
}
})
英文:
Something like this:
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
}
})
答案2
得分: 6
自定义处理程序方法(根据博客文章)——使用func(w http.ResponseWriter, r *http.Request) error
签名的方式确实是一个不错的选择。你可以返回&HTTPError{err, code}
或&JSONError{err, code}
,然后让ServeHTTP
进行检查和适当的渲染。例如:
type Handler struct {
h func(http.ResponseWriter, *http.Request) error
}
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 执行处理程序函数
err := h.h(w, r)
if err != nil {
switch e := err.(type) {
case *HTMLError:
// 渲染HTML响应,调用e.Err和e.Code
case *JSONError:
// 渲染JSON响应
default:
// 处理其他不需要检查的“通用”错误
}
}
}
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 {
// 检查传入的参数
if !ok {
// 这里也强制执行了你的返回值,避免了潜在的错误
return &HTTPError{errors.New("不好!"), http.StatusBadRequest}
}
}
小插曲:我写了一篇关于如何集中处理处理程序错误的博客文章,与上面的示例类似。你可以在这里阅读:http://elithrar.github.io/article/http-handler-error-handling-revisited/。
英文:
The custom handler approach (as per that blog post)—with a func(w http.ResponseWriter, r *http.Request) error
signature is certainly a good way to go. You could return &HTTPError{err, code}
or a &JSONError{err, code}
and have ServeHTTP
inspect and render appropriately. 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}
}
}
Small plug: I wrote a blog post about ways to centralise error handling with handlers that is similar to the example above.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论