httptest WriteHeader无效问题

uuid · · 549 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

## 背景 测试一个调用http接口时,使用了httptest.NewServer来mock一个http服务端,在验证响应异常状态码时发现奇怪问题,明明设置了异常状态码,但是http.Get始终返回的状态码都是正常的200: ``` mockHttpSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello world")) w.WriteHeader(http.StatusBadRequest) })) resp , err:= http.Get(mockHttpSrv.URL) if err != nil { return } defer resp.Body.Close() fmt.Println(resp.StatusCode) // 输出200 ``` ## 分析 查阅WriteHeader的文档时才发现原来当w.WriteHeader没明确调用时,默认第一次调用Write方法时,会隐式的触发WriteHeader(http.StatusOK): ``` // WriteHeader sends an HTTP response header with the provided // status code. // // If WriteHeader is not called explicitly, the first call to Write // will trigger an implicit WriteHeader(http.StatusOK). // Thus explicit calls to WriteHeader are mainly used to // send error codes. // // The provided code must be a valid HTTP 1xx-5xx status code. // Only one header may be written. Go does not currently // support sending user-defined 1xx informational headers, // with the exception of 100-continue response header that the // Server sends automatically when the Request.Body is read. WriteHeader(statusCode int) ``` 我的单测代码将WriteHeader写在了Write方法之后,所以默认会先触发了WriteHeader(http.StatusOK)。 但是,为什么后来我调用WriteHeader(http.StatusBadRequest)会无效呢,正常不是应该覆盖前面的方法才对?! 认真阅读了 WriteHeader源码,原来WriteHeader只允许写入一次Header(通过一个布尔变量:wroteHeader,写入后被标志为true,再次调用就直接return): ``` // WriteHeader implements http.ResponseWriter. func (rw *ResponseRecorder) WriteHeader(code int) { if rw.wroteHeader { return } rw.Code = code rw.wroteHeader = true if rw.HeaderMap == nil { rw.HeaderMap = make(http.Header) } rw.snapHeader = rw.HeaderMap.Clone() } ``` 这样问题就清晰了,是我WriteHeader顺序写错了,应该放在Write方法之前。 ## 总结 WriteHeader只能调用一次,如果一开始先调用Write,默认会触发WriteHeader(http.StatusOK),后续再调用WriteHeader就无效。 所以在开发中如果要测试非200的状态时,需要先设置响应状态码WriteHeader(http.StatusBadRequest),然后再调用Write方法。 **我的博客**: [httptest WriteHeader无效问题 | 艺术码农的小栈](https://itart.cn/blogs/2021/practice/httptest-writeheader-invalid.html)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

549 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传