title: Large PUT requests from Go to CouchDB
body: <p>I've been having a vexing problem with CouchDB and Golang.  When sending POST/PUT requests to CouchDB with relatively large Body sizes (the threshold seems to be ~8000 bytes or so), the connection times out and I get a "tcp: use of closed network connection" error from Go.</p>
  
  <p>Eventually (a second or two later), CouchDB sends a 500 Response along with a:</p>
  
  <pre><code>{"error":"unknown_error", "reason": "noproc"}
  </code></pre>
  
  <p>in the body.  The couchdb log also has a stack trace written to it:</p>
  
  <pre><code>Stacktrace: [{couch_db,collect_results,3,
                  [{file,"couch_db.erl"},{line,833}]},
               {couch_db,write_and_commit,4,
                  [{file,"couch_db.erl"},{line,845}]},
               {couch_db,update_docs,4,
                  [{file,"couch_db.erl"},{line,782}]},
               {couch_db,update_doc,4,
                  [{file,"couch_db.erl"},{line,426}]},
               {couch_httpd_db,update_doc,6,
                  [{file,"couch_httpd_db.erl"},{line,753}]},
               {couch_httpd_db,do_db_req,2,
                  [{file,"couch_httpd_db.erl"},{line,234}]},
               {couch_httpd,handle_request_int,5,
                  [{file,"couch_httpd.erl"},{line,318}]},
               {mochiweb_http,headers,5,
                  [{file,"mochiweb_http.erl"},{line,94}]}]
  </code></pre>
  
  <p>So I wrote up a quick unit test to replicate the issue (and to make sure it's not my wrapper causing the problem).  I'm making the request like so:</p>
  
  <pre><code>client := &amp;http.Client{}
  req, err := http.NewRequest(
      "PUT",
      "http://localhost:5984/unittestdb/testdocid1",
      bytes.NewReader(testBody1), //testBody1 is 10000 bytes of json object
  )
  req.Header.Set("Content-Type", "application/json")
  req.Header.Set("Accept", "application/json")
  resp, err := client.Do(req)
  </code></pre>
  
  <p>This replicated the issue... so I tried curling a large json document to couchdb.  <em>That</em> worked.  </p>
  
  <p>So, I fired up wireshark and examined the request made by my code to CouchDB and compared it to a request sent from curl.  I noticed one additional header in the Curl Request:</p>
  
  <pre><code>Expect: 100-continue
  </code></pre>
  
  <p>I had to look that one up, as I couldn't recall having seen (or maybe I just hadn't had to deal with) that header before.  So then I did a google search to see if the Golang http client supported the Expect/Continue functionality, and found this: <a href="https://github.com/golang/go/issues/3665" rel="nofollow">https://github.com/golang/go/issues/3665</a></p>
  
  <p>So Go doesn't support it and won't at least until 1.6.  So I assumed it must be an obscure thing and wasn't the source of my problem.  I spent a couple of hours randomly trying other stuff with the http.Client, Transport, etc.  </p>
  
  <p>Eventually, I manually set the "Expect: 100-continue" header in my http request in Go (if the body size is over a certain size), and ... it worked.  No timeout, no error, no couchdb barfing stack traces into the logs.  </p>
  
  <p>Now I am confused, if Go doesn't support this, how is it working?  Am I just masking the problem by doing this?  Or can I just shrug my shoulders and move on?</p>
  
  <p>I suspect there is an issue on the CouchDB side, perhaps there's a configuration setting I'm missing?</p>