[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [libmicrohttpd] post processing question
From: |
Martin Velek |
Subject: |
Re: [libmicrohttpd] post processing question |
Date: |
Fri, 31 Aug 2012 14:39:22 +0200 |
May I a question?
How to correctly refuse the POST request in my situation when the url
file is not found? I have looked into the refuse_post_example.c but I
am not more clever than before.
When I create a respond "file not found" (fileserver_example.c) for
POST requests, it fails on checking in MHD_queue_response and MHD_NO
is returned.
file: connection.c
#246 ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
#247 (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
connection->state is MHD_CONNECTION_CONTINUE_SENT
and the connection is reset. Probably it is due to continual sending
data from POST request.
I have created this code to overcome it:
if(true == page_not_found)
{
if (0 == strcmp(method, MHD_HTTP_METHOD_GET))
generate_no_page_found_response();
}
else if((0 == strcmp(method, MHD_HTTP_METHOD_POST)))
{
if (0 != *upload_data_size)
{
*upload_data_size = 0; // pretend we have processed data.
return MHD_YES; // OK
}
else
generate_no_page_found_response(); // last request data.
}//else if((0 == strcmp(method, MHD_HTTP_METHOD_POST)))
}//if(true == page_not_found)
There is a drawback, the client send waste data to server. On the
contrary, the same behavior is implemented on many server, e.g.
wget www.google.cz/dasfasdf --post-file=/tmp/very_big_file.
Any ideas how to handle POST requests?
Thank you
Martin
On Wed, Aug 29, 2012 at 11:51 AM, Christian Grothoff
<address@hidden> wrote:
> 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.
>>
>
>