[英]How to simulate 504 timeout error for http request inside a test in Go?
我试图在Go中的库中添加一个timeout
选项,并编写了以下测试来模拟该行为。
func TestClientTimeout(t *testing.T) {
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
d := map[string]interface{}{
"id": "12",
"scope": "test-scope",
}
time.Sleep(100 * time.Millisecond)
e := json.NewEncoder(w)
err := e.Encode(&d)
if err != nil {
t.Error(err)
}
w.WriteHeader(http.StatusOK)
}))
url := backend.URL
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
defer cancel()
req, err := http.NewRequest("GET", url, nil)
if err != nil {
t.Error("Request error", err)
}
resp, err := http.DefaultClient.Do(req.WithContext(ctx))
if err != nil {
t.Error("Response error", err)
}
defer resp.Body.Close()
t.Log(">>>>>>>Response is: ", resp)
}
但是我总是得到以下错误,而不是http.StatusGatewayTimeout
===运行TestClientTimeout
---失败:TestClientTimeout(0.05秒)
client_test.go:37: Timestamp before req 2018-07-13 09:10:14.936898 +0200 CEST m=+0.002048937 client_test.go:40: Response error Get http://127.0.0.1:49597: context deadline exceeded
紧急:运行时错误:无效的内存地址或nil指针取消引用[已恢复]
紧急:运行时错误:无效的内存地址或nil指针取消引用
如何修复此测试,以返回带有http.StatusGatewayTimeout
(504)状态代码的响应?
错误您得到的原因context deadline exceeded
是因为在超时context.Context
请求的客户端是不是在服务器端处理程序的超时时间。 这意味着在写入任何响应之前, context.Context
以及客户端http.DefaultClient
都会放弃。
panic: runtime error: invalid memory address...
是因为您推迟在响应上关闭主体,但是如果客户端返回错误,则响应为nil
。
此处的响应为nil,如果错误为非nil, t.Error
t.Fatal
更改为t.Fatal
resp, err := http.DefaultClient.Do(req.WithContext(ctx))
if err != nil {
// this should be t.Fatal, or don't do the body close if there's an error
t.Error("Response error", err)
}
defer resp.Body.Close()
http.StatusGatewayTimeout
问题的真正根源, http.StatusGatewayTimeout
是服务器端超时,这意味着创建的任何超时都必须在服务器端。 客户端http.DefaultClient
将永远不会创建自己的服务器错误响应代码。
要创建服务器端超时,可以将处理程序函数包装在http.TimeoutHandler
:
handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
d := map[string]interface{}{
"id": "12",
"scope": "test-scope",
}
time.Sleep(100 * time.Millisecond)
e := json.NewEncoder(w)
err := e.Encode(&d)
if err != nil {
t.Error(err)
}
w.WriteHeader(http.StatusOK)
})
backend := httptest.NewServer(http.TimeoutHandler(handlerFunc, 20*time.Millisecond, "server timeout"))
但是,这将创建503 - Service Unavailable
错误响应代码。
有关504的重要信息是这是“网关”或“代理”错误响应代码。 这意味着此代码不太可能从实际处理请求的服务器中发出。 从负载均衡器和代理中经常可以看到此代码。
504网关超时服务器充当网关或代理时,未收到其为完成请求而需要访问的上游服务器的及时响应。
您已经使用httptest.NewServer(...)
在测试方法中httptest.NewServer(...)
了http.Server
,因此可以在处理函数中手动返回http.StatusGatewayTimeout
响应状态。
handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusGatewayTimeout)
})
backend := httptest.NewServer(handlerFunc)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.