libmicrohttpd

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

commit f55c9a8e984e5e28b66b0edf792c6de861b4daee
parent a8f8a27bc027d4a0f565a6e4e579d64192f5b846
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri,  2 Aug 2013 21:42:29 +0000

-fix connect/content-length handling

Diffstat:
MChangeLog | 7+++++++
Msrc/include/microhttpd.h | 2+-
Msrc/microhttpd/connection.c | 98++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/microhttpd/connection_https.c | 1-
4 files changed, 63 insertions(+), 45 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,10 @@ +Fri Aug 2 20:55:47 CEST 2013 + Fix HTTP 1.1 compliance with respect to not returning + content-length headers for successful "CONNECT" requests. + Note that for unsuccessful "CONNECT" requests with an + empty response body, users must now explicitly set the + content-length header. -CG + Sun Jul 28 16:35:17 CEST 2013 Fixing build issue (missing #ifdef) in conjunction with --disable-messages. -blueness 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 0x00092104 +#define MHD_VERSION 0x00092105 /** * MHD-internal return code for "YES". diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c @@ -141,24 +141,19 @@ MHD_get_connection_values (struct MHD_Connection *connection, /** - * This function can be used to append an entry to - * the list of HTTP headers of a connection (so that the - * MHD_get_connection_values function will return - * them -- and the MHD PostProcessor will also - * see them). This maybe required in certain - * situations (see Mantis #1399) where (broken) - * HTTP implementations fail to supply values needed - * by the post processor (or other parts of the - * application). - * <p> - * This function MUST only be called from within - * the MHD_AccessHandlerCallback (otherwise, access - * maybe improperly synchronized). Furthermore, - * the client must guarantee that the key and - * value arguments are 0-terminated strings that - * are NOT freed until the connection is closed. - * (The easiest way to do this is by passing only - * arguments to permanently allocated strings.). + * This function can be used to append an entry to the list of HTTP + * headers of a connection (so that the MHD_get_connection_values + * function will return them -- and the MHD PostProcessor will also + * see them). This maybe required in certain situations (see Mantis + * #1399) where (broken) HTTP implementations fail to supply values + * needed by the post processor (or other parts of the application). + * + * This function MUST only be called from within the + * MHD_AccessHandlerCallback (otherwise, access maybe improperly + * synchronized). Furthermore, the client must guarantee that the key + * and value arguments are 0-terminated strings that are NOT freed + * until the connection is closed. (The easiest way to do this is by + * passing only arguments to permanently allocated strings.). * * @param connection the connection for which a * value should be set @@ -186,15 +181,15 @@ MHD_set_connection_value (struct MHD_Connection *connection, pos->next = NULL; /* append 'pos' to the linked list of headers */ if (NULL == connection->headers_received_tail) - { - connection->headers_received = pos; - connection->headers_received_tail = pos; - } + { + connection->headers_received = pos; + connection->headers_received_tail = pos; + } else - { - connection->headers_received_tail->next = pos; - connection->headers_received_tail = pos; - } + { + connection->headers_received_tail->next = pos; + connection->headers_received_tail = pos; + } return MHD_YES; } @@ -550,9 +545,27 @@ add_extra_headers (struct MHD_Connection *connection) add_close = MHD_YES; /* client asked for it, so add it */ /* if not present, add content length */ - if (NULL == MHD_get_response_header (connection->response, - MHD_HTTP_HEADER_CONTENT_LENGTH)) + if ( (NULL == MHD_get_response_header (connection->response, + MHD_HTTP_HEADER_CONTENT_LENGTH)) && + ( (0 != strcasecmp (connection->method, + MHD_HTTP_METHOD_CONNECT)) || + (0 != connection->response->total_size) ) ) { + /* + Here we add a content-length if one is missing; however, + for 'connect' methods, the responses MUST NOT include a + content-length header *if* the response code is 2xx (in + which case we expect there to be no body). Still, + as we don't know the response code here in some cases, we + simply only force adding a content-length header if this + is not a 'connect' or if the response is not empty + (which is kind of more sane, because if some crazy + application did return content with a 2xx status code, + then having a content-length might again be a good idea). + + Note that the change from 'SHOULD NOT' to 'MUST NOT' is + a recent development of the HTTP 1.1 specification. + */ SPRINTF (buf, MHD_UNSIGNED_LONG_LONG_PRINTF, (MHD_UNSIGNED_LONG_LONG) connection->response->total_size); @@ -783,12 +796,12 @@ transmit_error_response (struct MHD_Connection *connection, "Error %u (`%s') processing request, closing connection.\n", status_code, message); #endif - EXTRA_CHECK (connection->response == NULL); + EXTRA_CHECK (NULL == connection->response); response = MHD_create_response_from_buffer (strlen (message), (void *) message, MHD_RESPMEM_PERSISTENT); MHD_queue_response (connection, status_code, response); - EXTRA_CHECK (connection->response != NULL); + EXTRA_CHECK (NULL != connection->response); MHD_destroy_response (response); if (MHD_NO == build_header_response (connection)) { @@ -1130,10 +1143,10 @@ parse_cookie_header (struct MHD_Connection *connection) hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_COOKIE); - if (hdr == NULL) + if (NULL == hdr) return MHD_YES; cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES); - if (cpy == NULL) + if (NULL == cpy) { #if HAVE_MESSAGES MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n"); @@ -1144,9 +1157,9 @@ parse_cookie_header (struct MHD_Connection *connection) } memcpy (cpy, hdr, strlen (hdr) + 1); pos = cpy; - while (pos != NULL) + while (NULL != pos) { - while (*pos == ' ') + while (' ' == *pos) pos++; /* skip spaces */ sce = pos; @@ -1183,7 +1196,7 @@ parse_cookie_header (struct MHD_Connection *connection) } if (semicolon[0] == '\0') semicolon = NULL; - if (semicolon != NULL) + if (NULL != semicolon) { semicolon[0] = '\0'; semicolon++; @@ -1214,7 +1227,7 @@ static int parse_initial_message_line (struct MHD_Connection *connection, char *line) { char *uri; - char *httpVersion; + char *http_version; char *args; if (NULL == (uri = strchr (line, ' '))) @@ -1224,11 +1237,11 @@ parse_initial_message_line (struct MHD_Connection *connection, char *line) uri++; while (uri[0] == ' ') uri++; - httpVersion = strchr (uri, ' '); - if (httpVersion != NULL) + http_version = strchr (uri, ' '); + if (NULL != http_version) { - httpVersion[0] = '\0'; - httpVersion++; + http_version[0] = '\0'; + http_version++; } if (connection->daemon->uri_log_callback != NULL) connection->client_context @@ -1246,10 +1259,10 @@ parse_initial_message_line (struct MHD_Connection *connection, char *line) connection, uri); connection->url = uri; - if (NULL == httpVersion) + if (NULL == http_version) connection->version = ""; else - connection->version = httpVersion; + connection->version = http_version; return MHD_YES; } @@ -1796,7 +1809,6 @@ update_last_activity (struct MHD_Connection *connection) } - /** * This function handles a particular connection when it has been * determined that there is data to be read off a socket. diff --git a/src/microhttpd/connection_https.c b/src/microhttpd/connection_https.c @@ -131,7 +131,6 @@ MHD_tls_connection_handle_write (struct MHD_Connection *connection) static int MHD_tls_connection_handle_idle (struct MHD_Connection *connection) { - struct MHD_Daemon *daemon = connection->daemon; unsigned int timeout; #if DEBUG_STATES