expand tests

This commit is contained in:
Christian Grothoff
2024-07-24 11:25:54 +02:00
parent 95256aecd4
commit 7d0ef5a5a4
4 changed files with 175 additions and 4 deletions
+56 -4
View File
@@ -1129,16 +1129,19 @@ struct MHD_DynContentZCIoVec
* The number of elements in @a iov
*/
unsigned int iov_count;
/**
* The pointer to the array with @a iov_count elements.
*/
const struct MHD_IoVec *iov;
/**
* The callback to free resources.
* It is called once the full array of iov elements is sent.
* No callback is called if NULL.
*/
MHD_FreeCallback iov_fcb;
/**
* The parameter for @a iov_fcb
*/
@@ -1149,6 +1152,7 @@ struct MHD_DynContentZCIoVec
* The action type returned by Dynamic Content Creator callback
*/
struct MHD_DynamicContentCreatorAction;
/**
* The context used for Dynamic Content Creator callback
*/
@@ -1163,7 +1167,7 @@ struct MHD_DynamicContentCreatorContext;
* The total size of the data in the buffer and in @a iov_data must
* be non-zero.
* @param[in,out] ctx the pointer the context as provided to the callback
* @param data_size the amount of the data placed to the provided buffer,
* @param data_size the amount of the data placed to the provided buffer (not @a iov_data),
* cannot be larger than provided buffer size,
* must be non-zero if @a iov_data is NULL or has no data,
* @param iov_data the optional pointer to the iov data,
@@ -1184,13 +1188,52 @@ MHD_DCC_action_continue_zc (
MHD_FN_PAR_NONNULL_ (1)
MHD_FN_PAR_CSTR_ (4);
#define MHD_DCC_action_continue(ctx,data_size,chunk_ext) \
/**
* Set action to "continue processing", the data is provided in the
* buffer and/or in the zero-copy @a iov_data.
* If data is provided both in the buffer and @a ivo_data then
* data in the buffer sent first, following the iov data.
* The total size of the data in the buffer and in @a iov_data must
* be non-zero.
* @param[in,out] ctx the pointer the context as provided to the callback
* @param data_size the amount of the data placed to the provided buffer (not @a iov_data),
* cannot be larger than provided buffer size,
* must be non-zero.
* @param chunk_ext the optional pointer to chunk extension string,
* can be NULL to not use chunk extension,
* ignored if chunked encoding is not used
* @return the pointer to the action if succeed,
* NULL (equivalent of MHD_DCC_action_abort())in case of any error
*/
#define MHD_DCC_action_continue_ce(ctx,data_size,chunk_ext) \
MHD_DCC_action_continue_zc (ctx, data_size, NULL, chunk_ext)
/**
* Set action to "continue processing", the data is provided in the
* buffer and/or in the zero-copy @a iov_data.
* If data is provided both in the buffer and @a ivo_data then
* data in the buffer sent first, following the iov data.
* The total size of the data in the buffer and in @a iov_data must
* be non-zero.
* @param[in,out] ctx the pointer the context as provided to the callback
* @param data_size the amount of the data placed to the provided buffer;
* cannot be larger than provided buffer size,
* must be non-zero.
*
* @return the pointer to the action if succeed,
* NULL (equivalent of MHD_DCC_action_abort())in case of any error
*/
#define MHD_DCC_action_continue(ctx,data_size) \
MHD_DCC_action_continue_ce (ctx, data_size, NULL)
/**
* Set action to "finished".
* If function failed for any reason, the action is automatically
* set to "stop with error".
*
* @param[in,out] ctx the pointer the context as provided to the callback
* @param num_footers number of elements in the @a footers array,
* must be zero if @a footers is NULL
@@ -1209,8 +1252,17 @@ MHD_DCC_action_finished_with_footer (
MHD_FN_PAR_NONNULL_ (1);
#define MHD_DCC_action_finished(action) \
MHD_DCC_set_action_finished_with_footer (action, 0, NULL)
/**
* Set action to "finished".
* If function failed for any reason, the action is automatically
* set to "stop with error".
*
* @param[in,out] ctx the pointer the context as provided to the callback
* @return the pointer to the action if succeed,
* NULL (equivalent of MHD_DCC_action_abort())in case of any error
*/
#define MHD_DCC_action_finished(ctx) \
MHD_DCC_set_action_finished_with_footer (ctx, 0, NULL)
/**
+29
View File
@@ -218,6 +218,35 @@ MHDT_server_reply_text (
uint_fast64_t upload_size);
/**
* Returns the text from @a cls as the response to any
* request, but using chunks by returning @a cls
* word-wise (breaking into chunks at spaces).
*
* @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_chunked_text (
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 writes text from @a cls to a temporary file
* and then uses the file descriptor to serve the
@@ -366,3 +366,85 @@ MHDT_server_reply_check_upload (
&check_upload_cb,
(void *) want);
}
/**
* Closure for #chunk_return.
*/
struct ChunkContext
{
/**
* Where we are in the buffer.
*/
const char *pos;
};
/**
* Function that returns a string in chunks.
*
* @param dyn_cont_cls must be a `struct ChunkContext`
* @param ctx the context to produce the action to return,
* the pointer is only valid until the callback returns
* @param pos position in the datastream to access;
* note that if a `struct MHD_Response` object is re-used,
* it is possible for the same content reader to
* be queried multiple times for the same data;
* however, if a `struct MHD_Response` is not re-used,
* libmicrohttpd guarantees that "pos" will be
* the sum of all data sizes provided by this callback
* @param[out] buf where to copy the data
* @param max maximum number of bytes to copy to @a buf (size of @a buf)
* @return action to use,
* NULL in case of any error (the response will be aborted)
*/
static const struct MHD_DynamicContentCreatorAction *
chunk_return (void *cls,
struct MHD_DynamicContentCreatorContext *ctx,
uint_fast64_t pos,
void *buf,
size_t max)
{
struct ChunkContext *cc = cls;
size_t imax = strlen (cc->pos);
const char *space = strchr (cc->pos, ' ');
if (0 == imax)
return MHD_DCC_action_finished (ctx);
if (imax > space - cc->pos + 1)
imax = space - cc->pos;
if (imax > max)
imax = max;
memcpy (buf,
cc->pos,
imax);
cc->pos += imax;
return MHD_DCC_action_continue (ctx,
imax);
}
const struct MHD_Action *
MHDT_server_reply_chunked_text (
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;
struct ChunkContext *cc;
cc = malloc (sizeof (struct ChunkContext));
if (NULL == cc)
return NULL;
cc->pos = text;
return MHD_action_from_response (
request,
MHD_response_from_callback (MHD_HTTP_STATUS_OK,
MHD_SIZE_UNKNOWN,
&chunk_return,
cc,
&free));
}
@@ -238,6 +238,14 @@ main (int argc, char *argv[])
.timeout_ms = 5000,
.num_clients = 1
},
{
.label = "chunked response get",
.server_cb = &MHDT_server_reply_chunked_text,
.server_cb_cls = "Hello world",
.client_cb = &MHDT_client_get_root,
.client_cb_cls = "Hello world",
.timeout_ms = 2500,
},
// TODO: chunked download
{
.label = NULL,