When doing a POST of a zero length file, or any file when using digest authentication curl will issue an "Expect: 100-continue" header as well as a "Content-Length: 0". This violates RFC-2616 and earns a 400 error code from servers written in Go 1.2.
Section 8.2.3 includes:
A client MUST NOT send an Expect request-header field (Expect) with the "100-continue" expectation if it does not intend to send a request body.
Once the problem is understood, using "-H Expect:" suppresses the header and allows the command to function normally.
If a Content-Length: 0 for a zero length POST constitutes not sending a body is debatable. Omitting the body when digest authentication probes to get a nonce is clearly against the RFC.
Maximum compatibility would be achieved by omitting the "Expect" header in both of these cases, the queries would save a turnaround, and there is no performance downside, since the bodies are empty anyway. There is probably an applicable code path, since doing a POST of /dev/null does not send the Expect header.
$ curl --version curl 7.26.0 (x86_64-pc-linux-gnu) libcurl/7.26.0 OpenSSL/1.0.1e zlib/1.2.7 libidn/1.25 libssh2/1.4.2 librtmp/2.3 Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtmp rtsp scp sftp smtp smtps telnet tftp Features: Debug GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP
I've confused this bug report by typing POST instead of PUT, so just continue as if I said PUT the first time.
To replicate the problem with a recent curl I moved a machine to Debian jessie, same problem...
jim@future:~$ curl -v -T empty.txt http://127.0.0.1:8080/images/ -H Content-Type:image/png
Hostname was NOT found in DNS cache
Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
The crux of the problem having both a Content-Length:0 and an Expect: 100-continue. This will happen communicating with any server written using the standard Go http packages. They interpret a Content-Length of 0 as "no body" and in violating section 8.2.3 of RFC-2616. I would say they are wrong. I think section 4.3 is clear that messages can be of zero length. The fact remains that curl will fail on Go servers for no benefit. Expanding the header to explicitly wait for a network turnaround before transferring zero bytes is nonsensical.
Moving on to the htdigest, zero length body optimization to get a nonce, this is dangerous, non compliant default behavior. It fails with Go because it trips the same Content-Length: 0, Expect conflict, again the Expect gains nothing with a zero length body. The dangerous part comes because a PUT of a fictitious zero length body might succeed and overwrite an existing resource leaving an erroneous state available in the server. In the best case when the eventual PUT of the data arrives it will be accepted, but if the server does validation of the body and rejects the operation you will have effectively destroyed the previous contents.
On Mar 25, 2014, at 2:20 AM, Daniel Stenberg bagder@users.sf.net wrote:
Related
Bugs:
#1349I agree that "Content-Length: 0" together with "Expect: 100-continue" is plain nonsense and that's the main bug I take from this bug report.
"Content-Length: 0" in a request without the Expect: header is perfectly fine. It is a signal that there's 0 bytes sent in a request, which for PUT or POST is not the norm. If you want to persue to somehow limit the use of that, I suggest we do that as a separate bug report to not confuse matters too much here.
Can you show us a command line to get zero content-length? I'm not sure I can repeat it with a recent curl version.
"If a Content-Length: 0 for a zero length POST constitutes not sending a body is debatable. " What else would it mean?
"Omitting the body when digest authentication probes to get a nonce is clearly against the RFC." Which RFC are you talking about here? I know it is far from ideal to do it like that, but it is a shortcut that is wildly supported and you can tell curl to not do it so we've opted to keep the shortcut for the faster operation for those who can use it.
https://github.com/bagder/curl/commit/42937f87 addresses this.