libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

commit 6abf440a7148642864d570c313eca3f29ac4be64
parent d85d8e86350e1788ad5f8915ba9eb64e9d718bcc
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date:   Thu, 27 Aug 2026 11:33:26 +0200

test_client_server: added testing on responses with unknwon size

Diffstat:
Msrc/tests/client_server/libtest.h | 33+++++++++++++++++++++++++++++++++
Msrc/tests/client_server/libtest_convenience_server_reply.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/tests/client_server/test_client_server.c | 17+++++++++++++++++
Msrc/tests/client_server/test_http2.c | 19+++++++++++++++++++
4 files changed, 121 insertions(+), 14 deletions(-)

diff --git a/src/tests/client_server/libtest.h b/src/tests/client_server/libtest.h @@ -559,6 +559,39 @@ MHDT_server_reply_file ( /** + * Writes text from @a cls to a temporary file and then uses the file + * descriptor to serve the content to the client without indicating the size + * of the content. + * + * The reply is sent by chunked encoding (HTTP/1.1) or is terminated by + * the end of the stream (HTTP/2), the size of the content is detected by + * the end of the file. + * + * @param cls argument given together with the function + * pointer when the handler was registered with MHD + * @param request the request object + * @param path the requested uri (without arguments after "?") + * @param method the HTTP method used (#MHD_HTTP_METHOD_GET, + * #MHD_HTTP_METHOD_PUT, etc.) + * @param upload_size the size of the message upload content payload, + * #MHD_SIZE_UNKNOWN for chunked uploads (if the + * final chunk has not been processed yet) + * @return action how to proceed, NULL + * if the request must be aborted due to a serious + * error while handling the request (implies closure + * of underling data stream, for HTTP/1.1 it means + * socket closure). + */ +const struct MHD_Action * +MHDT_server_reply_file_unknown_size ( + void *cls, + struct MHD_Request *MHD_RESTRICT request, + const struct MHD_String *MHD_RESTRICT path, + enum MHD_HTTP_Method method, + uint_fast64_t upload_size); + + +/** * Returns an emtpy response with a custom header * set from @a cls and the #MHD_HTTP_STATUS_NO_CONTENT. * diff --git a/src/tests/client_server/libtest_convenience_server_reply.c b/src/tests/client_server/libtest_convenience_server_reply.c @@ -84,23 +84,20 @@ MHDT_server_reply_text ( } -const struct MHD_Action * -MHDT_server_reply_file ( - void *cls, - struct MHD_Request *MHD_RESTRICT request, - const struct MHD_String *MHD_RESTRICT path, - enum MHD_HTTP_Method method, - uint_fast64_t upload_size) +/** + * Create a temporary file and put the @a text to it. + * Exit the test if the file cannot be created or written. + * + * @param text the text to put to the file + * @return the FD of the file with the @a text + */ +static int +tmpfile_with_text (const char *text) { - const char *text = cls; size_t written = 0u; size_t tlen = strlen (text); int fd; - (void)path; - (void)method; - (void)upload_size; /* Unused */ - fd = MHDT_create_tmpfile (); if (-1 == fd) { @@ -134,12 +131,53 @@ MHDT_server_reply_file ( fflush (stderr); exit (99); } + return fd; +} + + +const struct MHD_Action * +MHDT_server_reply_file ( + void *cls, + struct MHD_Request *MHD_RESTRICT request, + const struct MHD_String *MHD_RESTRICT path, + enum MHD_HTTP_Method method, + uint_fast64_t upload_size) +{ + const char *text = cls; + + (void)path; + (void)method; + (void)upload_size; /* Unused */ + + return MHD_action_from_response ( + request, + MHD_response_from_fd (MHD_HTTP_STATUS_OK, + tmpfile_with_text (text), + 0 /* offset */, + strlen (text))); +} + + +const struct MHD_Action * +MHDT_server_reply_file_unknown_size ( + void *cls, + struct MHD_Request *MHD_RESTRICT request, + const struct MHD_String *MHD_RESTRICT path, + enum MHD_HTTP_Method method, + uint_fast64_t upload_size) +{ + const char *text = cls; + + (void)path; + (void)method; + (void)upload_size; /* Unused */ + return MHD_action_from_response ( request, MHD_response_from_fd (MHD_HTTP_STATUS_OK, - fd, + tmpfile_with_text (text), 0 /* offset */, - tlen)); + MHD_SIZE_UNKNOWN)); } diff --git a/src/tests/client_server/test_client_server.c b/src/tests/client_server/test_client_server.c @@ -232,6 +232,23 @@ main (int argc, char *argv[]) .timeout_ms = 5000, }, { + .label = "simple get, file response, unknown size", + .server_cb = &MHDT_server_reply_file_unknown_size, + .server_cb_cls = (void *)"Hello world", + .client_cb = &MHDT_client_get_root, + .client_cb_cls = "Hello world", + .timeout_ms = 2500, + }, + { + /* The end of the content is detected by the end of the file */ + .label = "medium body get, file response, unknown size", + .server_cb = &MHDT_server_reply_file_unknown_size, + .server_cb_cls = medium_text, + .client_cb = &MHDT_client_get_root, + .client_cb_cls = medium_text, + .timeout_ms = 5000, + }, + { .label = "medium body get, file response", .server_cb = &MHDT_server_reply_file, .server_cb_cls = medium_text, diff --git a/src/tests/client_server/test_http2.c b/src/tests/client_server/test_http2.c @@ -200,6 +200,25 @@ main (int argc, char *argv[]) .http_version = 2, }, { + .label = "simple get, file response, unknown size", + .server_cb = &MHDT_server_reply_file_unknown_size, + .server_cb_cls = (void *)"Hello world", + .client_cb = &MHDT_client_get_root, + .client_cb_cls = "Hello world", + .timeout_ms = 2500, + .http_version = 2, + }, + { + /* The end of the content is detected by the end of the file */ + .label = "medium body get, file response, unknown size", + .server_cb = &MHDT_server_reply_file_unknown_size, + .server_cb_cls = medium_text, + .client_cb = &MHDT_client_get_root, + .client_cb_cls = medium_text, + .timeout_ms = 5000, + .http_version = 2, + }, + { .label = "medium body get, file response", .server_cb = &MHDT_server_reply_file, .server_cb_cls = medium_text,