4

I'm using Golang 1.4.2 (built from source) and when I try to make an HTTP PUT request via http.Client.Do() the Content-Length header is missing from the request. All my other headers are sent... Am I doing something wrong? When I make the same request via CURL the content-length header is sent. My requests are being made to etcd server, which is setting all my keys to empty values. While this is somewhat novel, it is hardly useful. :)

http://play.golang.org/p/pIoB--bXUT

package main

import (
    "bytes"
    "fmt"
    "net/http"
    "net/http/httputil"
    "net/url"
    "strconv"
)

func main() {
    put := url.Values{}
    put.Set("value", "WHOAH here is my stuff")
    put.Add("ttl","")
    encode := put.Encode()
    req, _ := http.NewRequest("PUT", "http://localhost:2379/v2/keys/somekey", bytes.NewBufferString(encode))
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    req.Header.Add("Content-Length", strconv.Itoa(len(encode)))
    req.Header.Add("X-Content-Length", strconv.Itoa(len(encode)))
    dump, _ := httputil.DumpRequest(req, true)
    fmt.Println(string(dump))
}

yields

PUT /v2/keys/somekey HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
X-Content-Length: 33

ttl=&value=WHOAH+here+is+my+stuff
Austen Hoogen
  • 2,726
  • 3
  • 18
  • 12

2 Answers2

4

If you are saying header Content-Length is not set (actually it is set automatically just not showed up when dumping it), it works as designed because the following headers are excluded in httputil.DumpRequest() even you set them explicitly:

  • Host
  • Content-Length
  • Transfer-Encoding
  • Trailer

see line 317 of go/src/net/http/httputil/dump.go.

If you do send the request instead dumping it, you will see the header Content-Length sent along with User-Agent and Accept-Encoding.

shawnzhu
  • 7,233
  • 4
  • 35
  • 51
  • yes, so it is unnecessary to set the content-length header in above code. it just strips those headers out of dumped result from `httputil.DumpRequest()` afterwards, although, this header is still there – shawnzhu Aug 06 '15 at 14:33
4

I was incorrect about Content-Length not being sent, I just wasn't seeing it when using httputil.DumpRequest.

Solution here was to use httputil.DumpRequestOut which properly shows the Content-Length header (and others). It means there is something else going on with my program that is causing etcd to set empty values. If I figure that out I'll update with that solution as well.

Austen Hoogen
  • 2,726
  • 3
  • 18
  • 12
  • The overall problem had nothing to do with the HTTP request but instead were the json tags I was using for the etcd response. I was storing json in an etcd key/value, and passing that into json.RawMessage type, which I assumed would be better for subsequent json.Unmarshal calls on that data. The issue, however, is that the json.RawMessage []bytes was being quoted, so I needed to unquote before unmarshaling. I decided to just use a string type on this instead and convert to []byte when passing into json.Unmarshal. – Austen Hoogen Aug 10 '15 at 18:40