通过返回头部错误代码或JSON响应终止HTTP请求。

huangapple go评论91阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2015年8月17日 03:57:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/32039334.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定