libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 166909d2ce8c9facef9fb0574eeb9d057730c467
parent d9f458b2e6e13960809955ba99da4530f7503c08
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 18 Dec 2012 20:25:37 +0000

I was was having problems receiving data from a client using POST with chunked encoding.
It turns out this client is violating the HTTP spec by setting the "Transfer-Encoding: Chunked"
as well as "Content-Length: 0"

Here are the client headers:
  POST /ee4/live.isml/Streams(Encoder1) HTTP/1.1
  Transfer-Encoding: Chunked
  User-Agent: ExpressionEncoder
  Host: 10.11.1.29
  Content-Length: 0
  Connection: Keep-Alive
  Cache-Control: no-cache

This is what HTTP 1.1 spec says (in section 4.4):
  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.

libmicrohttpd does the opposite of what the 4.4 section says if both headers are present.  It only uses the content-length and ignores the
chunked encoding.
I patched libmicrohttpd with the attached patch that does the opposite.  It ignores the content-length if chunked encoding is also specified.
And with that patch libmicrohttpd can be a publishing point for MS Expression Encoder.

What is your take on this?

-eivind
=> answer: follow the spec ;-)


Diffstat:
MChangeLog | 4++++
Msrc/daemon/connection.c | 52++++++++++++++++++++++++----------------------------
Msrc/include/microhttpd.h | 2+-
3 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,7 @@ +Tue Dec 18 21:18:11 CET 2012 + Given both 'chunked' encoding and 'content-length', + ignore the 'content-length' header as per RFC. -ES + Thu Dec 6 10:14:44 CET 2012 Force adding "Connection: close" header to response if client asked for connection to be closed (so far, we diff --git a/src/daemon/connection.c b/src/daemon/connection.c @@ -1836,40 +1836,36 @@ parse_connection_headers (struct MHD_Connection *connection) return; } - clen = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_CONTENT_LENGTH); - if (clen != NULL) + connection->remaining_upload_size = 0; + enc = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_TRANSFER_ENCODING); + if (enc != NULL) { - cval = strtoul (clen, &end, 10); - if ( ('\0' != *end) || - ( (LONG_MAX == cval) && (errno == ERANGE) ) ) + connection->remaining_upload_size = MHD_SIZE_UNKNOWN; + if (0 == strcasecmp (enc, "chunked")) + connection->have_chunked_upload = MHD_YES; + } + else + { + clen = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_CONTENT_LENGTH); + if (clen != NULL) { + cval = strtoul (clen, &end, 10); + if ( ('\0' != *end) || + ( (LONG_MAX == cval) && (errno == ERANGE) ) ) + { #if HAVE_MESSAGES - MHD_DLOG (connection->daemon, + MHD_DLOG (connection->daemon, "Failed to parse `%s' header `%s', closing connection.\n", MHD_HTTP_HEADER_CONTENT_LENGTH, clen); #endif - CONNECTION_CLOSE_ERROR (connection, NULL); - return; - } - connection->remaining_upload_size = cval; - } - else - { - enc = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_TRANSFER_ENCODING); - if (NULL == enc) - { - /* this request (better) not have a body */ - connection->remaining_upload_size = 0; - } - else - { - connection->remaining_upload_size = MHD_SIZE_UNKNOWN; - if (0 == strcasecmp (enc, "chunked")) - connection->have_chunked_upload = MHD_YES; + CONNECTION_CLOSE_ERROR (connection, NULL); + return; + } + connection->remaining_upload_size = cval; } } } diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -106,7 +106,7 @@ extern "C" /** * Current version of the library. */ -#define MHD_VERSION 0x00091701 +#define MHD_VERSION 0x00091702 /** * MHD-internal return code for "YES".