libmicrohttpd

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

commit 7cb018fd3364d37b36970b99f630e374d94b15b2
parent f78f507c193b87f1a0d1f019a00b5ba1152ff567
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri,  2 Mar 2012 23:00:11 +0000

changing order in which headers are returned to match the order in which we received them from the network

Diffstat:
MChangeLog | 4++++
Mdoc/microhttpd.texi | 11++++++++---
Msrc/daemon/connection.c | 54++++++++++++++++++++++++++++++++----------------------
Msrc/daemon/internal.h | 5+++++
Msrc/include/microhttpd.h | 2+-
Msrc/testcurl/daemontest_post_loop.c | 11++++++-----
6 files changed, 56 insertions(+), 31 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,7 @@ +Fri Mar 2 23:44:56 CET 2012 + Making sure that MHD_get_connection_values iterates over the + headers in the order in which they were received. -CG + Wed Feb 1 09:39:12 CET 2012 Fixed compilation problem on MinGW. -BS diff --git a/doc/microhttpd.texi b/doc/microhttpd.texi @@ -1205,7 +1205,12 @@ right now). Get all the headers matching @var{kind} from the request. The @var{iterator} callback is invoked once for each header, with -@var{iterator_cls} as first argument. Return the number of entries +@var{iterator_cls} as first argument. After version 0.9.19, the +headers are iterated in the same order as they were received from +the network; previous versions iterated over the headers in reverse +order. + +@code{MHD_get_connection_values} returns the number of entries iterated over; this can be less than the number of headers if, while iterating, @var{iterator} returns @code{MHD_NO}. @@ -1224,8 +1229,8 @@ would contain the string ``key''. @deftypefun int MHD_set_connection_value (struct MHD_Connection *connection, enum MHD_ValueKind kind, const char * key, const char * value) -This function can be used to add an entry to -the HTTP headers of a connection (so that the +This function can be used to append an entry to +the list of HTTP headers of a connection (so that the @code{MHD_get_connection_values function} will return them -- and the MHD PostProcessor will also see them). This maybe required in certain diff --git a/src/daemon/connection.c b/src/daemon/connection.c @@ -144,8 +144,8 @@ MHD_get_connection_values (struct MHD_Connection *connection, /** - * This function can be used to add an entry to - * the HTTP headers of a connection (so that the + * 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 @@ -186,8 +186,18 @@ MHD_set_connection_value (struct MHD_Connection *connection, pos->header = (char *) key; pos->value = (char *) value; pos->kind = kind; - pos->next = connection->headers_received; - connection->headers_received = pos; + 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; + } + else + { + connection->headers_received_tail->next = pos; + connection->headers_received_tail = pos; + } return MHD_YES; } @@ -207,15 +217,11 @@ MHD_lookup_connection_value (struct MHD_Connection *connection, { struct MHD_HTTP_Header *pos; - if (connection == NULL) + if (NULL == connection) return NULL; - pos = connection->headers_received; - while (pos != NULL) - { - if ((0 != (pos->kind & kind)) && (0 == strcasecmp (key, pos->header))) - return pos->value; - pos = pos->next; - } + for (pos = connection->headers_received; NULL != pos; pos = pos->next) + if ((0 != (pos->kind & kind)) && (0 == strcasecmp (key, pos->header))) + return pos->value; return NULL; } @@ -1036,18 +1042,25 @@ get_next_header_line (struct MHD_Connection *connection) return rbuf; } + /** + * Add an entry to the HTTP headers of a connection. If this fails, + * transmit an error response (request too big). + * + * @param connection the connection for which a + * value should be set + * @param kind kind of the value + * @param key key for the value + * @param value the value itself * @return MHD_NO on failure (out of memory), MHD_YES for success */ static int connection_add_header (struct MHD_Connection *connection, char *key, char *value, enum MHD_ValueKind kind) { - struct MHD_HTTP_Header *hdr; - - hdr = MHD_pool_allocate (connection->pool, - sizeof (struct MHD_HTTP_Header), MHD_YES); - if (hdr == NULL) + if (MHD_NO == MHD_set_connection_value (connection, + kind, + key, value)) { #if HAVE_MESSAGES MHD_DLOG (connection->daemon, @@ -1057,14 +1070,10 @@ connection_add_header (struct MHD_Connection *connection, REQUEST_TOO_BIG); return MHD_NO; } - hdr->next = connection->headers_received; - hdr->header = key; - hdr->value = value; - hdr->kind = kind; - connection->headers_received = hdr; return MHD_YES; } + /** * Parse and unescape the arguments given by the client as part * of the HTTP request URI. @@ -2289,6 +2298,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) connection->continue_message_write_offset = 0; connection->responseCode = 0; connection->headers_received = NULL; + connection->headers_received_tail = NULL; connection->response_write_position = 0; connection->have_chunked_upload = MHD_NO; connection->method = NULL; diff --git a/src/daemon/internal.h b/src/daemon/internal.h @@ -464,6 +464,11 @@ struct MHD_Connection struct MHD_HTTP_Header *headers_received; /** + * Tail of linked list of parsed headers. + */ + struct MHD_HTTP_Header *headers_received_tail; + + /** * Response to transmit (initially NULL). */ struct MHD_Response *response; 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 0x00091300 +#define MHD_VERSION 0x00091301 /** * MHD-internal return code for "YES". diff --git a/src/testcurl/daemontest_post_loop.c b/src/testcurl/daemontest_post_loop.c @@ -432,7 +432,8 @@ testExternalPost () } curl_multi_cleanup (multi); MHD_stop_daemon (d); - fprintf (stderr, "\n"); + if (LOOPCOUNT >= 99) + fprintf (stderr, "\n"); return 0; } @@ -470,7 +471,7 @@ main (int argc, char *const *argv) start_time = now(); errorCount += testInternalPost (); fprintf (stderr, - oneone ? "%s: Sequential POSTs (http/1.1) %f/s" : "%s: Sequential POSTs (http/1.0) %f/s", + oneone ? "%s: Sequential POSTs (http/1.1) %f/s\n" : "%s: Sequential POSTs (http/1.0) %f/s\n", "internal select", (double) 1000 * LOOPCOUNT / (now() - start_time + 1.0)); GAUGER ("internal select", @@ -480,7 +481,7 @@ main (int argc, char *const *argv) start_time = now(); errorCount += testMultithreadedPost (); fprintf (stderr, - oneone ? "%s: Sequential POSTs (http/1.1) %f/s" : "%s: Sequential POSTs (http/1.0) %f/s", + oneone ? "%s: Sequential POSTs (http/1.1) %f/s\n" : "%s: Sequential POSTs (http/1.0) %f/s\n", "multithreaded post", (double) 1000 * LOOPCOUNT / (now() - start_time + 1.0)); GAUGER ("Multithreaded select", @@ -490,7 +491,7 @@ main (int argc, char *const *argv) start_time = now(); errorCount += testMultithreadedPoolPost (); fprintf (stderr, - oneone ? "%s: Sequential POSTs (http/1.1) %f/s" : "%s: Sequential POSTs (http/1.0) %f/s", + oneone ? "%s: Sequential POSTs (http/1.1) %f/s\n" : "%s: Sequential POSTs (http/1.0) %f/s\n", "thread with pool", (double) 1000 * LOOPCOUNT / (now() - start_time + 1.0)); GAUGER ("thread with pool", @@ -500,7 +501,7 @@ main (int argc, char *const *argv) start_time = now(); errorCount += testExternalPost (); fprintf (stderr, - oneone ? "%s: Sequential POSTs (http/1.1) %f/s" : "%s: Sequential POSTs (http/1.0) %f/s", + oneone ? "%s: Sequential POSTs (http/1.1) %f/s\n" : "%s: Sequential POSTs (http/1.0) %f/s\n", "external select", (double) 1000 * LOOPCOUNT / (now() - start_time + 1.0)); GAUGER ("external select",