有什么方法可以自定义Golang中的HTTP响应状态?

时间:2019-06-19 01:32:37

标签: http go web

我需要在Web服务器的处理程序中自定义HTTP状态,但是我发现golang似乎不支持完全自定义的HTTP响应。 例如:

w.WriteHeader(999)

这是curl的结果:

$ curl -vk -i localhost:9898/hello

*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9898 (#0)
> GET /hello HTTP/1.1
> Host: localhost:9898
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 999 status code 999
HTTP/1.1 999 status code 999
< Date: Wed, 19 Jun 2019 02:01:09 GMT
Date: Wed, 19 Jun 2019 02:01:09 GMT
< Content-Length: 0
Content-Length: 0

结果中的status code似乎无法修改..但是,我想定义自己的状态,例如Bad Request: xxx

有什么好主意吗?非常感谢!

2 个答案:

答案 0 :(得分:6)

我不认为您正在尝试的内容目前不受支持。

根据the official documentation of net/http.ResponseWriter.WriteHeader

  

提供的代码必须是有效的HTTP 1xx-5xx状态代码。只能写入一个标题。 Go目前不支持发送用户定义的1xx信息性标头,但100连续响应标头是服务器在读取Request.Body时自动发送的。

答案 1 :(得分:3)

此功能在net/http/server.go中处理:

func writeStatusLine(bw *bufio.Writer, is11 bool, code int, scratch []byte) {
    if is11 {
        bw.WriteString("HTTP/1.1 ")
    } else {
        bw.WriteString("HTTP/1.0 ")
    }
    if text, ok := statusText[code]; ok {
        bw.Write(strconv.AppendInt(scratch[:0], int64(code), 10))
        bw.WriteByte(' ')
        bw.WriteString(text)
        bw.WriteString("\r\n")
    } else {
        // don't worry about performance
        fmt.Fprintf(bw, "%03d status code %d\r\n", code, code)
    }
}

由此您可以看到,描述性文本来自标准库的内部状态码列表,这些内容由StatusText函数公开。

如果没有已知的文本,则使用占位符“状态代码”,没有任何选项可以更改此行为。

因此,使用标准库http程序包,您无法做您想要的事情。您可以选择在您自己的程序包中分叉和/或重新实现此功能,或者(可能是长期的)向上游提交功能请求以更改此功能。

如果出于某种原因确实需要此功能,那么最后一种绝望的方法可能是编写某种代理,该代理可以拦截HTTP输出并为您转换“状态代码”文本。您可以通过编写自己的net.Listener实现/包装器来实现此目的,然后将其传递给http.Serve。除非您绝对没有其他选择,否则这将不会非常有效,并且不建议这样做。