Dear Martin,
You can totally do it later (the disadvantage being that then the client
will have started the upload, and if you're then out-of-memory and
cannot handle the request, bandwidth will be wasted). So the question
is if it is worse to put the test on filepost1 vs. filepost2 into the PP
callback vs. delaying creating the PP. That's a very minor engineering
decision IMO.
You also do not have to use the post processor at all --- if you are in
a setting where parsing of the upload data is not required or trivial,
you can also handle it yourself and never create a post processor. For
very, very small systems (< 128k RAM/ROM), this might be the best option.
Happy hacking!
Christian
On 08/29/2012 11:42 AM, Martin Velek wrote:
Hello,
is it mandatory to create MHD_create_post_processor during the first
call of function MHD_AccessHandlerCallback? In all post examples, it
is done in if (NULL == *con_cls){ ... }.
Or can I create it later (second call of MHD_AccessHandlerCallback)?:
if (0 == strcmp (method, "POST"))
{
if(false == was_not_alredy_created)
{
con_info->postprocessor = MHD_create_post_processor
(connection, POSTBUFFERSIZE, iterate_post, (void *) con_info);
}
if (0 != *upload_data_size)
{
MHD_post_process (con_info->postprocessor, upload_data,
*upload_data_size);
*upload_data_size = 0;
return MHD_YES;
}
}
Thanks You for answer(s)
Martin
-------------------------------- A very very long reason
--------------------------
I am trying to create a small web server based on libmicrohttpd
handling also SSI and CGI requests (a function which returns buffer).
It offers own interface e.g. only http_server_start(). Internals of
Libmicrohttpd are mostly hidden, e.g. the function
http_server_set_credentials(const char * username, const char *
password) sets user and password for basic http auth and
http_server_setup_handler() sets user callback for handling requests.
My AccessHandlerCallback is a static function and call user's callback.
#define HTTP_NEW_CONNECTION ((void *)(~0))
static int AccessHandlerCallback(void *cls, struct MHD_Connection *connection,
const char *url, const char *method, const char *version,
const char *upload_data, size_t *upload_data_size, void
**con_cls) {
int ret = MHD_NO;
char *user = NULL;
char *pass = NULL;
if (NULL == *con_cls)
{
/*
* Thus, we will generate no response until the parameter is
non-null—implying the callback was called before at least once.
* We do not need to share information between different calls
of
the callback, so we can set the parameter to any adress
* that is assured to be not null.
*/
*con_cls = HTTP_NEW_CONNECTION;
return MHD_YES;
}
// get username and password
user = MHD_basic_auth_get_username_password (connection,&pass);
// check if it is valid
if (false == check_credentials(user, pass))
{
// no, send denied reply
struct MHD_Response * response =
MHD_create_response_from_buffer(strlen(AUTH_FAIL_PAGE), (void *)
AUTH_FAIL_PAGE, MHD_RESPMEM_PERSISTENT);
MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE,
"text/html""; charset=iso-8859-2");
// Set headers to always close connection
MHD_add_response_header (response,MHD_HTTP_HEADER_CONNECTION,
"close");
ret = MHD_queue_basic_auth_fail_response(connection,
AUTHENTICATION_REALM_MESSAGE, response);
MHD_destroy_response (response);
}
else
{
if(NULL != url_handler.url_callback)
{
ret = url_handler.url_callback(connection,
url_handler.url_callback_cls, url, method, upload_data,
upload_data_size, con_cls);
}
else
{
ret = MHD_NO;
}
}
// Dealocate because of MHD.
free (user);
free (pass);
return ret;
}
I would like to handle more than one page (1 ... n files) e.g. from
this GET request.
"<html><body>Upload a file, please!<br>
<form action=\"/filepost1\" method=\"post\"
enctype=\"multipart/form-data\">
<input name=\"file\" type=\"file\">
<input type=\"submit\" value=\" Send \"></form>
<form action=\"/filepost2\" method=\"post\"
enctype=\"multipart/form-data\">
<input name=\"file\" type=\"file\">
<input type=\"submit\" value=\" Send \"></form>
</body></html>";
Both files /filepost1 and /filepost2 have different
MHD_PostDataIterator, filepost1 stores file onto harddisk, filepost2
to memory.
Which MHD_PostDataIterator will be used, it is defined in a user
callback called from AccessHandlerCallback. This is the reason of my
question.