library/src/network/httpd/BP-HTTPdDefaultCallbacks.cc
// The following access handler callback will be used if none is provided.  It
// simply acts as a generic (but very capable) access handler that routes requests
// based on the /request_handlers/ found within the httpd hreg.
The following access handler callback will be used if none is provided.  It
simply acts as a generic (but very capable) access handler that routes requests
based on the /request_handlers/ found within the httpd hreg.
The following access handler callback will be used if none is provided . It simply acts as a generic ( but very capable ) access handler that routes requests based on the / request_handlers / found within the httpd hreg .
int  BP_HTTPdDefaultAccessHandlerCallback
(
        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
)
{
	if(!url)
		return MHD_NO;
	if(!method)
		return MHD_NO;
	if(!version)
		return MHD_NO;
	if(BP_StringIsReasonablePrintableString((char *) url, bpstrlen((char *) url), BP_FALSE, BP_FALSE) != BP_TRUE)
	{
			return MHD_NO;
	}
	if(BP_StringIsReasonablePrintableString((char *) method, bpstrlen((char *) method), BP_FALSE, BP_FALSE) != BP_TRUE)
	{
			return MHD_NO;
	}
	if(BP_StringIsReasonablePrintableString((char *) version, bpstrlen((char *) version), BP_FALSE, BP_FALSE) != BP_TRUE)
	{
			return MHD_NO;
	}
	P_BP_HTTPD_SESSION httpd = (P_BP_HTTPD_SESSION) cls;
	P_BP_HTTPD_REQUEST_HANDLER request_handler = BP_HTTPdRequestHandlerLookup(httpd, (char *) url);
	if(!request_handler)
		return MHD_NO;
	P_BP_HTTPD_REQUEST request = NULL;
	if(!*con_cls)
	{
		P_BP_HTTPD_REQUEST request = BP_HTTPdRequestAdd
		(
			httpd,
			request_handler,
			connection,
			url,
			method,
			version
		);
		if(!request)
			return MHD_NO;
		*con_cls = (void *) request;
		return MHD_YES;
	}
	else
	{
		request = (P_BP_HTTPD_REQUEST)*con_cls;
		if(request->http_method == BP_HTTPD_METHOD_POST)
		{
			%
			%
			MHD_post_process(request->pp, upload_data, *upload_data_size);
			if(*upload_data_size)
			{
				*upload_data_size = 0;
				return MHD_YES;
			}
			MHD_destroy_post_processor(request->pp);
			request->pp = NULL;
		}
	}
	if(!cls)
	{
		if(*con_cls)
			cls = *con_cls;
		else
			return MHD_NO;
	}
	int val_header_status = MHD_get_connection_values(connection, MHD_HEADER_KIND, BP_HTTPdDefaultHeaderIteratorCallback, (void *) request);
	if(val_header_status < 0)
	{
	}
	int val_cookie_status = MHD_get_connection_values(connection, MHD_COOKIE_KIND, BP_HTTPdDefaultCookieIteratorCallback, (void *) request);
	if(val_cookie_status < 0)
	{
	}
	int val_get_status = MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, BP_HTTPdDefaultGetIteratorCallback, (void *) request);
	if(val_get_status < 0)
	{
	}
	P_BP_HTTPD_USER_SESSION session = (P_BP_HTTPD_USER_SESSION) NULL;
	if(request->arg_hreg)
	{
		P_BP_HTTPD_REQUEST_VAR session_key = BP_HTTPdRequestVarArgRegistryLookup
		(
				request,
				BP_HTTPD_REQUEST_VAR_TYPE_COOKIE,
				request->httpd->cookie_key
		);
		if(session_key)
		{
			if(session_key->data)
			{
				printf("\n SESSION KEY?: %p - %s", session_key, session_key->data);
				printf("\n ");
				session = BP_HTTPdSessionAuthUserFromSessionId
				(
						httpd,
						session_key->data
				);
			}
		}
	}
	if(!session)
	{
		P_BP_HTTPD_REQUEST_VAR user_key = BP_HTTPdRequestVarArgRegistryLookup
		(
				request,
				BP_HTTPD_REQUEST_VAR_TYPE_POST_DATA,
				"lu"
		);
		P_BP_HTTPD_REQUEST_VAR pass_key = BP_HTTPdRequestVarArgRegistryLookup
		(
				request,
				BP_HTTPD_REQUEST_VAR_TYPE_POST_DATA,
				"lp"
		);
		if(user_key && pass_key)
		{
			session = BP_HTTPdSessionAuthUserFromCreds
			(
					httpd,
					user_key->data,
					pass_key->data
			);
		}
	}
	if(session)
		request->session = (void *) session;
	httpd = request->httpd;
	if(!httpd->system_hreg)
		return MHD_NO;
    char *response_buff = "<html>blah</html>";
    size_t do_premature_exit_for_benchmark = 0;
    if(do_premature_exit_for_benchmark)
    {
    	conn_nr++;
    	printf("\n Servicing connection: %u", conn_nr);
		struct MHD_Response *response = MHD_create_response_from_buffer
		(
				bpstrlen (response_buff),
				(void *) response_buff,
				MHD_RESPMEM_MUST_COPY
		);
		int ret = MHD_queue_response
		(
				connection,
				MHD_HTTP_OK,
				response
		);
		MHD_destroy_response (response);
		return MHD_YES;
    }
    printf("\n !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    printf("\n !!! ATTEMPTING REQUEST: %s ", url);
    printf("\n !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    BP_ERROR_T request_status = BP_HTTPdRequestHandlerDispatch
	(
			request,
			(char *) url,
			connection,
			url,
			method,
			version,
			upload_data,
			upload_data_size,
			con_cls
	);
    %%%%
    %%%%
    if(!request->is_websocket_and_request_destruction_must_be_handled_externally)
    {
		printf("\n !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		printf("\n !!! EXITING/DESTROYING REQUEST !!!!!!!!!!!!!!!!!!!!!!!!!");
		printf("\n !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		printf("\n");
       	BP_HTTPdRequestDestroy(httpd, request);
    }
    else
    {
		printf("\n !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		printf("\n !!! EXITING REQUEST HANDLER FOR WEBSOCKET (data not destroyed) !!!!!!!");
		printf("\n !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		printf("\n");
    }
    return MHD_YES;
}
int BP_HTTPdDefaultAccessHandlerCallback ( 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 ) { if ( ! url ) return MHD_NO ; if ( ! method ) return MHD_NO ; if ( ! version ) return MHD_NO ; if ( BP_StringIsReasonablePrintableString ( ( char * ) url , bpstrlen ( ( char * ) url ) , BP_FALSE , BP_FALSE ) != BP_TRUE ) { return MHD_NO ; } if ( BP_StringIsReasonablePrintableString ( ( char * ) method , bpstrlen ( ( char * ) method ) , BP_FALSE , BP_FALSE ) != BP_TRUE ) { return MHD_NO ; } if ( BP_StringIsReasonablePrintableString ( ( char * ) version , bpstrlen ( ( char * ) version ) , BP_FALSE , BP_FALSE ) != BP_TRUE ) { return MHD_NO ; } P_BP_HTTPD_SESSION httpd = ( P_BP_HTTPD_SESSION ) cls ; P_BP_HTTPD_REQUEST_HANDLER request_handler = BP_HTTPdRequestHandlerLookup ( httpd , ( char * ) url ) ; if ( ! request_handler ) return MHD_NO ; P_BP_HTTPD_REQUEST request = NULL ; if ( ! * con_cls ) { P_BP_HTTPD_REQUEST request = BP_HTTPdRequestAdd ( httpd , request_handler , connection , url , method , version ) ; if ( ! request ) return MHD_NO ; * con_cls = ( void * ) request ; return MHD_YES ; } else { request = ( P_BP_HTTPD_REQUEST ) * con_cls ; if ( request -> http_method == BP_HTTPD_METHOD_POST ) { MHD_post_process ( request -> pp , upload_data , * upload_data_size ) ; if ( * upload_data_size ) { * upload_data_size = 0 ; return MHD_YES ; } MHD_destroy_post_processor ( request -> pp ) ; request -> pp = NULL ; } } if ( ! cls ) { if ( * con_cls ) cls = * con_cls ; else return MHD_NO ; } int val_header_status = MHD_get_connection_values ( connection , MHD_HEADER_KIND , BP_HTTPdDefaultHeaderIteratorCallback , ( void * ) request ) ; if ( val_header_status < 0 ) { } int val_cookie_status = MHD_get_connection_values ( connection , MHD_COOKIE_KIND , BP_HTTPdDefaultCookieIteratorCallback , ( void * ) request ) ; if ( val_cookie_status < 0 ) { } int val_get_status = MHD_get_connection_values ( connection , MHD_GET_ARGUMENT_KIND , BP_HTTPdDefaultGetIteratorCallback , ( void * ) request ) ; if ( val_get_status < 0 ) { } P_BP_HTTPD_USER_SESSION session = ( P_BP_HTTPD_USER_SESSION ) NULL ; if ( request -> arg_hreg ) { P_BP_HTTPD_REQUEST_VAR session_key = BP_HTTPdRequestVarArgRegistryLookup ( request , BP_HTTPD_REQUEST_VAR_TYPE_COOKIE , request -> httpd -> cookie_key ) ; if ( session_key ) { if ( session_key -> data ) { printf ( " \n " , session_key , session_key -> data ) ; printf ( " \n " ) ; session = BP_HTTPdSessionAuthUserFromSessionId ( httpd , session_key -> data ) ; } } } if ( ! session ) { P_BP_HTTPD_REQUEST_VAR user_key = BP_HTTPdRequestVarArgRegistryLookup ( request , BP_HTTPD_REQUEST_VAR_TYPE_POST_DATA , " " ) ; P_BP_HTTPD_REQUEST_VAR pass_key = BP_HTTPdRequestVarArgRegistryLookup ( request , BP_HTTPD_REQUEST_VAR_TYPE_POST_DATA , " " ) ; if ( user_key && pass_key ) { session = BP_HTTPdSessionAuthUserFromCreds ( httpd , user_key -> data , pass_key -> data ) ; } } if ( session ) request -> session = ( void * ) session ; httpd = request -> httpd ; if ( ! httpd -> system_hreg ) return MHD_NO ; char * response_buff = " " ; size_t do_premature_exit_for_benchmark = 0 ; if ( do_premature_exit_for_benchmark ) { conn_nr ++ ; printf ( " \n " , conn_nr ) ; struct MHD_Response * response = MHD_create_response_from_buffer ( bpstrlen ( response_buff ) , ( void * ) response_buff , MHD_RESPMEM_MUST_COPY ) ; int ret = MHD_queue_response ( connection , MHD_HTTP_OK , response ) ; MHD_destroy_response ( response ) ; return MHD_YES ; } printf ( " \n " ) ; printf ( " \n " , url ) ; printf ( " \n " ) ; BP_ERROR_T request_status = BP_HTTPdRequestHandlerDispatch ( request , ( char * ) url , connection , url , method , version , upload_data , upload_data_size , con_cls ) ; if ( ! request -> is_websocket_and_request_destruction_must_be_handled_externally ) { printf ( " \n " ) ; printf ( " \n " ) ; printf ( " \n " ) ; printf ( " \n " ) ; BP_HTTPdRequestDestroy ( httpd , request ) ; } else { printf ( " \n " ) ; printf ( " \n " ) ; printf ( " \n " ) ; printf ( " \n " ) ; } return MHD_YES ; }
The following access handler callback will be used if none is provided.
The following access handler callback will be used if none is provided .
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Immediate Disqualifiers %%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // run basic checks // URL string check // Method string check. // Version string check. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Request Handler Lookup %%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // set the localized httpd pointer // attempt to lookup the handler in the hash table // ensure we have a request handler // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% CLS Selector %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // this will hold the populate request structure // check to see if we're at the tail of the request chain. Typically // there are at least two passes per each request.  This ensures that we pass the // httpd session along through each pass. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Create Request Object %%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // attempt to add the request to the queue // if the request failed basic sanity or composition, we // exit immediately. // set marker to new request value // return indicating that we want to finish the request (this // will loop the request into the second (finishing) part) // set the request structure from con_cls at this point. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Process POST Data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Because of the way MHD works, the first request sent only // sends header information.  This allows us to pregen a request // for use and pass it through again if post data is detected. // attempt to process data based on the callback // if we have post data continue to gather it // destroy the post processor // set pp to null (prevents dual free) // ensure we have a httpd session // reset the session on continue here // --- End Iterative Post Processing ------------ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Do Rate Limit Calculations %%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // TODO: Wait for email response from MHD developers to see how to get //       the full raw request data and size. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Attempt to Retrieve Headers %%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // attempt to retrieve connection values // printf("\n UNABLE TO RETRIEVE HEADER VALS"); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Attempt to Retrieve Cookies %%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // attempt to retrieve connection values // printf("\n UNABLE TO RETRIEVE COOKIE VALS"); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Attempt to Retrieve HTTP Get Vars %%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // attempt to retrieve connection values // printf("\n UNABLE TO GET GET VARS"); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Cookie -> Session Checks %%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // session (filled dynamically) // if we have arguments, attempt session lookup from cookie values // Attempts to lookup an argument from the argument registry // if we found our session key, attempt to lookup value // attempt to lookup the session // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Attempt Auth from User Password %%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Attempts to lookup an argument from the argument registry // Attempts to lookup an argument from the argument registry // if there is a user key and pass key we can attempt a lookup // attempt to authenticate the user from creds if they're passed in // set the session here if it was previously filled // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Run Basic Sanity Checks %%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // IMPORTANT NOTE: At this point we only work with the httpd via the requests pointer // the httpd must have a hash registry associated with it // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Optional Inline Benchmarking for Testing %%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // This is mostly for testing libmicrohttpd itself.  I use this little block // to stress test how many connections the libmicrohttpd library can handle // by setting do_premature_exit_for_benchmark to non-zero.  It causes the application // to exit immediately after dumping a static page. // set the response buffer // display connection number // create arbitrary response // queue the response out // destroy the response // return the yes indicator // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Lookup Request Processor %%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // dbg: request message // attempt to dispatch the request to the appropriate handler // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Post Request Logging and Cleanup %%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // destroy the request before exit // destroy the request // destroy the request before exit // return indicating success