2017-08-21 115 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