2017-08-21 129 views
3

我已经编写了一个REST API服务,要求所有响应都是JSON。但是,当Go http请求解析器遇到错误时,它将以纯文本响应的形式返回400,而不会调用我的处理程序。例如:如何为解析错误定制Golang http 400响应?

> curl -i -H 'Authorization: Basic hi  
there' 'http://localhost:8080/test' -v 
* Trying ::1... 
* TCP_NODELAY set 
* Connected to localhost (::1) port 8080 (#0) 
> GET /test HTTP/1.1 
> Host: localhost:8080 
> User-Agent: curl/7.54.0 
> Accept: */* 
> Authorization: Basic hi 
> there 
> 
< HTTP/1.1 400 Bad Request 
HTTP/1.1 400 Bad Request 
< Content-Type: text/plain; charset=utf-8 
Content-Type: text/plain; charset=utf-8 
< Connection: close 
Connection: close 

< 
* Closing connection 0 

请注意无效的授权标头。当然,400是正确的回应,但它当然是文本/纯文本。有什么方法可以配置Go HTTP解析器使用自定义错误响应媒体类型和主体?

+0

你在使用某种框架吗?我从来没有见过stdlib http处理程序的这种行为。 – Adrian

+0

没有。这里有一个[愚蠢的简单例子](https://play.golang.org/p/5iOUCklUeH)。 – theory

回答

1

你不行。你可以找到这个净/ HTTP源,它只会发生,如果请求错误:

https://github.com/golang/go/blob/master/src/net/http/server.go#L1744

我认为你的问题可能是你在卷曲加入标头的新线?

401,403,404,500错误您可以使用json进行响应,但在server.go中处理错误的请求或错误的标头(太长,格式错误)。

目前没有办法拦截这样的错误,虽然它在consideration之下,所以你唯一的解决方法就是修补stdlib源代码(我不推荐这么做)。但是,由于此错误仅在客户发生错误并且请求格式错误时才会显示,所以这可能不是一个大问题。文本响应的原因是,浏览器或类似的客户端(如没有-v的curl)不会看到空的响应。你可以在你的应用程序前放置一个像nginx这样的代理,但是你永远不会看到这个请求,因为这是一个错误的请求,你的代理会处理它。

可能你可以用像前面的nginx这样的代理来完成它,但是如果你为它设置了一个特定的静态错误页面来服务400个错误并且提供你指定的400.json文件?这是我能想到的唯一解决方案。一个指令,这样的事情可能会为nginx的工作:

error_page 400 /400.json; 

如果您希望能够自定义这些错误,或许是注释添加到链接,让他们知道你有这个特定问题的问题。

+0

我担心这会是答案。是的,换行符是错误的。不,这不是一个大问题,除非我必须将API记录为“总是返回JSON,除非在我的代码发现请求之前Go https返回错误”。我很欣赏想要在回复中包含一个主体(虽然这个主题对细节不够详细,但花了我一段时间才发现错误),但理想情况下我可以控制所有回复的内容类型和内容。请对此问题发表评论,谢谢! – theory

-2

如果您使用的是标准net/http库,则可以使用以下代码。看看这个答案Showing custom 404 error page with standard http package @Mostafa我从这个例子中得到了这个例子

func homeHandler(w http.ResponseWriter, r *http.Request) { 
    if r.URL.Path != "/" { 
     errorHandler(w, r, http.StatusNotFound) 
     return 
    } 
    fmt.Fprint(w, "welcome home") 
} 

func errorHandler(w http.ResponseWriter, r *http.Request, status int) { 
    w.WriteHeader(status) 
    if status == http.StatusNotFound { 
     // JSON Out here 
    } 
} 
+0

400和404不是一回事。请阅读这个问题。 – Adrian