libmicrohttpd
[Top][All Lists]
Advanced

[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.
>>
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]