go HTTP客户端正在向我的客户端请求添加“chunked”传输编码字段。不幸的是,我所连接的服务不支持这种情况,并且它返回时出现错误。
有没有办法禁用它?
这是我的请求代码:
// DoHTTPRequest Do a full HTTP Client Request, with timeout
func DoHTTPRequest(method, url string, body io.Reader, headers map[string]string, timeout time.Duration) (*http.Response, error) {
// Create the request
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
}
// Add headers
for k, v := range headers {
req.Header.Set(k, v)
}
client := &http.Client{
Timeout: timeout,
}
return client.Do(req)
}
基本上我希望这个标题丢弃。这个客户端正在与S3交谈,这对于它发送的标头非常敏感。
我收到此错误:
A header you provided implies functionality that is not implemented
答案 0 :(得分:2)
TransferEncoding
是直接在Request结构上的字段。如果你明确地设置它,它将不会被覆盖。
req.TransferEncoding = []string{"identity"}
答案 1 :(得分:2)
像这样设置Transfer Encoding标头不会使用chunked:
req.TransferEncoding = []string{"identity"}
然而,http客户端来源给出了在我的情况下选择chunked的原因。具体来说,我使用“PUT”作为方法,没有指定内容长度。所以我需要的是设置req.ContentLength。
但是,您可以看到我的DoHTTPRequest
包装函数不知道设置它有多大。我曾假设设置标题会使其最初工作。好吧,它通过设置标题不起作用。你可以在决定是否使用分块编码的来源中看到原因。
// shouldSendChunkedRequestBody reports whether we should try to send a
// chunked request body to the server. In particular, the case we really
// want to prevent is sending a GET or other typically-bodyless request to a
// server with a chunked body when the body has zero bytes, since GETs with
// bodies (while acceptable according to specs), even zero-byte chunked
// bodies, are approximately never seen in the wild and confuse most
// servers. See Issue 18257, as one example.
//
// The only reason we'd send such a request is if the user set the Body to a
// non-nil value (say, ioutil.NopCloser(bytes.NewReader(nil))) and didn't
// set ContentLength, or NewRequest set it to -1 (unknown), so then we assume
// there's bytes to send.
//
// This code tries to read a byte from the Request.Body in such cases to see
// whether the body actually has content (super rare) or is actually just
// a non-nil content-less ReadCloser (the more common case). In that more
// common case, we act as if their Body were nil instead, and don't send
// a body.
func (t *transferWriter) shouldSendChunkedRequestBody() bool {
// Note that t.ContentLength is the corrected content length
// from rr.outgoingLength, so 0 actually means zero, not unknown.
if t.ContentLength >= 0 || t.Body == nil { // redundant checks; caller did them
return false
}
if requestMethodUsuallyLacksBody(t.Method) {
// Only probe the Request.Body for GET/HEAD/DELETE/etc
// requests, because it's only those types of requests
// that confuse servers.
t.probeRequestBody() // adjusts t.Body, t.ContentLength
return t.Body != nil
}
// For all other request types (PUT, POST, PATCH, or anything
// made-up we've never heard of), assume it's normal and the server
// can deal with a chunked request body. Maybe we'll adjust this
// later.
return true
}
所以我的解决方案很简单:
// DoHTTPRequest Do a full HTTP Client Request, with timeout
func DoHTTPRequest(method, url string, body io.Reader, headers map[string]string, timeout time.Duration) (*http.Response, error) {
// Create the request
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
}
// Add headers
for k, v := range headers {
req.Header.Set(k, v)
// Set the Content Length correctly if specified.
if strings.EqualFold(k, "Content-Length") {
length, err := strconv.Atoi(v)
if err != nil {
return nil, fmt.Errorf("Bad Content-Length header")
}
req.ContentLength = int64(length)
}
}
client := &http.Client{
Timeout: timeout,
Transport: &loghttp.Transport{},
}
return client.Do(req)
}
只要内容长度正确,就满足S3。我不需要将TransferEncoding设置为identity。