PUT and content-length with tamino webdav

I’ve been playing around today with the new delta-v enabled version of the webdav server, and found one major problem with one of the clients I use.

When I do a PUT to the server with the content-length header set, it works fine. If I do a PUT without a content-length header, however (my client does this under some circumstances), the file is created with 0 length on the server.

In order to test this independently of my client, I sent the following request (manually, using ‘nc’) to the server, and confirmed the problem. Sending the same request with a content-length header (set to 52 in this case, as I recall) worked correctly, resulting in the file being stored and retrievable from the server.

PUT /taminowebdavserver/testcoll/test.xml HTTP/1.1
Content-Type: text/xml
Host: 192.168.1.107:4000

<?xml version="1.0"?>

contents

Hello Michael,

reading the HTTP 1.1 spec (I include section 4.4 here) I get the impression, that a request with no Content-Length: header should include something like a Transfer-Encoding: chunked header. What do you think?

Regards,
Peter

From RFC 2616:

4.4 Message Length

The transfer-length of a message is the length of the message-body as it appears in the message; that is, after any transfer-codings have been applied. When a message-body is included with a message, the transfer-length of that body is determined by one of the following (in order of precedence):

1. Any response message which “MUST NOT” include a message-body (such as the 1xx, 204, and 304 responses and any response to a HEAD request) is always terminated by the first empty line after the header fields, regardless of the entity-header fields present in the message.

2. If a Transfer-Encoding header field (section 14.41) is present and has any value other than “identity”, then the transfer-length is defined by use of the “chunked” transfer-coding (section 3.6), unless the message is terminated by closing the connection.

3. If a Content-Length header field (section 14.13) is present, its decimal value in OCTETs represents both the entity-length and the transfer-length. The Content-Length header field MUST NOT be sent if these two lengths are different (i.e., if a Transfer-Encoding header field is present). If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.

4. If the message uses the media type “multipart/byteranges”, and the ransfer-length is not otherwise specified, then this self- elimiting media type defines the transfer-length. This media type UST NOT be used unless the sender knows that the recipient can arse it; the presence in a request of a Range header with ultiple byte- range specifiers from a 1.1 client implies that the lient can parse multipart/byteranges responses.

A range header might be forwarded by a 1.0 proxy that does not understand multipart/byteranges; in this case the server MUST delimit the message using methods defined in items 1,3 or 5 of this section.

5. By the server closing the connection. (Closing the connection cannot be used to indicate the end of a request body, since that would leave no possibility for the server to send back a response.)

For compatibility with HTTP/1.0 applications, HTTP/1.1 requests containing a message-body MUST include a valid Content-Length header field unless the server is known to be HTTP/1.1 compliant. If a request contains a message-body and a Content-Length is not given, the server SHOULD respond with 400 (bad request) if it cannot determine the length of the message, or with 411 (length required) if it wishes to insist on receiving a valid Content-Length.

All HTTP/1.1 applications that receive entities MUST accept the “chunked” transfer-coding (section 3.6), thus allowing this mechanism to be used for messages when the message length cannot be determined in advance.

Messages MUST NOT include both a Content-Length header field and a non-identity transfer-coding. If the message does include a non- identity transfer-coding, the Content-Length MUST be ignored.

When a Content-Length is given in a message where a message-body is allowed, its field value MUST exactly match the number of OCTETs in the message-body. HTTP/1.1 user agents MUST notify the user when an invalid length is received and detected.

Peter,

You’re correct that the spec says that an HTTP/1.1 request (and a PUT presumably has to be HTTP/1.1, since 1.0 doesn’t define PUT except to note it as an extension method available in some implementations) should either give a Content-Length, or use the chunked transfer-encoding, but this doesn’t seem to be required (it’s a little ambiguous. Refusing to accept the request is possibly an acceptable thing to do).

Certainly, returning 201 (Created) in this case is completely wrong - it tells the client that the request succeeded, though in this case the server was unwilling to process the request. As the text you quoted from the spec says:

“If a request contains a message-body and a Content-Length is not given, the server SHOULD respond with 400 (bad request) if it cannot determine the length of the message, or with 411 (length required) if it wishes to insist on receiving a valid Content-Length.”

It’s worth noting that ‘normal’ slide and tomcat cope fine with this case, creating the file correctly. Given that the spec does not require the request to be dropped, that there is sufficient information available to deal with it correctly, that most other implementations accept it, and that the software underlying tamino’s webdav server can cope fine, it would seem reasonable to fix this bug by making it accept the request. Of course, merely correctly rejecting the request would also be acceptable.

Michael

Michael,

sorry for late reply! Thank you for the hints. I will take them into account for our next release.

Regards,
Peter