Nice, your advice manipulated me into moving basic auth and page check into the first call of AccessHandlerCallback.
Thank you Martin On Fri, Aug 31, 2012 at 2:55 PM, Christian Grothoff <[email protected]> wrote: > The correct way is to send the error responds upon the very first callback > to your handler > (the one where "*con_cls" is usually still NULL and where 0 == > *upload_data_size). This will then send the error code to the client > instead of the (otherwise auto-generated) "100 CONTINUE". As a result, HTTP > 1.1-clients would not perform the upload. You might want to read up on "100 > CONTINUE" in HTTP for details. > > Happy hacking! > > Christian > > > On 08/31/2012 02:39 PM, Martin Velek wrote: >> >> 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 >> <[email protected]> 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. >>>> >>> > >
