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

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

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错误代码的错误响应,如下所示(代码取自上述链接):

  1. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  2. // 检查传入的参数
  3. if !ok {
  4. http.Error(w, "无效的输入参数!", http.StatusBadRequest)
  5. return
  6. }
  7. // 执行正常的API服务
  8. })

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

  1. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  2. // 检查传入的参数
  3. if !ok {
  4. w.Header().Set("Content-Type", "application/json")
  5. w.WriteHeader(http.StatusBadRequest)
  6. str := `{"Result":"","Error":"无效的变量"}`
  7. fmt.Fprint(w, str)
  8. return
  9. }
  10. // 执行正常的API服务
  11. })

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

所以,在代码片段中:

  1. if isJsonError {
  2. // 调用用于提供JSON错误的HTTP函数
  3. }
  4. if isHTTPError {
  5. // 调用用于提供HTTP错误的HTTP函数
  6. }

我该如何在语义上实现这一点?如果我表达不清楚,我提前道歉。谢谢!

附注:我还阅读了以下博文:
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):

  1. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  2. // examine incoming params
  3. if !ok {
  4. http.Error(w, `Invalid input params!`, http.StatusBadRequest)
  5. return
  6. }
  7. // Do normal API serving
  8. })

However, in some cases I need to return a JSON response to the web client:

  1. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  2. // examine incoming params
  3. if !ok {
  4. w.Header().Set("Content-Type", "application/json")
  5. w.WriteHeader(http.StatusBadRequest)
  6. str := `{"Result":"","Error":"No valide Var"}`
  7. fmt.Fprint(w, str)
  8. return
  9. }
  10. // Do normal API serving
  11. })

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:

  1. if isJsonError {
  2. //call HTTP function to serve JSON error
  3. }
  4. if isHTTPError {
  5. //call HTTP function to serve an HTTP error
  6. }

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

类似这样:

  1. func badReq(w http.ResponseWriter, isJson bool, err string) {
  2. if !isJson {
  3. http.Error(w, err, http.StatusBadRequest)
  4. return
  5. }
  6. w.Header().Set("Content-Type", "application/json")
  7. w.WriteHeader(http.StatusBadRequest)
  8. fmt.Fprintf(w, `{"result":"","error":%q}`, err)
  9. }
  10. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  11. if !ok {
  12. badReq(w, true, "no valid var")
  13. return
  14. }
  15. })
英文:

Something like this:

  1. func badReq(w http.ResponseWriter, isJson bool, err string) {
  2. if !isJson {
  3. http.Error(w, err, http.StatusBadRequest)
  4. return
  5. }
  6. w.Header().Set("Content-Type", "application/json")
  7. w.WriteHeader(http.StatusBadRequest)
  8. fmt.Fprintf(w, `{"result":"","error":%q}`, err)
  9. }
  10. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  11. if !ok {
  12. badReq(w, true, "no valid var")
  13. return
  14. }
  15. })

答案2

得分: 6

自定义处理程序方法(根据博客文章)——使用func(w http.ResponseWriter, r *http.Request) error签名的方式确实是一个不错的选择。你可以返回&HTTPError{err, code}&JSONError{err, code},然后让ServeHTTP进行检查和适当的渲染。例如:

  1. type Handler struct {
  2. h func(http.ResponseWriter, *http.Request) error
  3. }
  4. func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  5. // 执行处理程序函数
  6. err := h.h(w, r)
  7. if err != nil {
  8. switch e := err.(type) {
  9. case *HTMLError:
  10. // 渲染HTML响应,调用e.Err和e.Code
  11. case *JSONError:
  12. // 渲染JSON响应
  13. default:
  14. // 处理其他不需要检查的“通用”错误
  15. }
  16. }
  17. }
  18. type HTMLError struct {
  19. Err error
  20. Code int
  21. }
  22. func (e *HTMLError) Error() string {
  23. return e.Err.Error()
  24. }
  25. type JSONError struct {
  26. Err error
  27. Code int
  28. }
  29. func (e *JSONError) Error() string {
  30. return e.Err.Error()
  31. }
  32. func SomeHandler(w http.ResponseWriter, r *http.Request) error {
  33. // 检查传入的参数
  34. if !ok {
  35. // 这里也强制执行了你的返回值,避免了潜在的错误
  36. return &HTTPError{errors.New("不好!"), http.StatusBadRequest}
  37. }
  38. }

小插曲:我写了一篇关于如何集中处理处理程序错误的博客文章,与上面的示例类似。你可以在这里阅读: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.

  1. type Handler struct {
  2. h func(http.ResponseWriter, *http.Request) error
  3. }
  4. func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  5. // Execute the handler function
  6. err := h.h(w, r)
  7. if err != nil {
  8. switch e := err.(type) {
  9. case *HTMLError:
  10. // Render a HTML response, calling e.Err and e.Code
  11. case *JSONError:
  12. // Render a JSON response
  13. default:
  14. // Handle all other 'generic' errors you don't inspect
  15. }
  16. }
  17. }
  18. type HTMLError struct {
  19. Err error
  20. Code int
  21. }
  22. func (e *HTMLError) Error() string {
  23. return e.Err.Error()
  24. }
  25. type JSONError struct {
  26. Err error
  27. Code int
  28. }
  29. func (e *JSONError) Error() string {
  30. return e.Err.Error()
  31. }
  32. func SomeHandler(w http.ResponseWriter, r *http.Request) error {
  33. // examine incoming params
  34. if !ok {
  35. // Your returns are also enforced here - avoiding subtle bugs
  36. return &HTTPError{errors.New("No good!"), http.StatusBadRequest}
  37. }
  38. }

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:

确定