static int test_multipart_splits () { struct MHD_Connection connection; struct MHD_HTTP_Header header; struct MHD_PostProcessor *pp; unsigned int want_off; size_t size; size_t splitpoint; size = strlen (FORM_DATA); for (splitpoint = 1; splitpoint < size; splitpoint++) { want_off = FORM_START; memset (&connection, 0, sizeof (struct MHD_Connection)); memset (&header, 0, sizeof (struct MHD_HTTP_Header)); connection.headers_received = &header; header.header = MHD_HTTP_HEADER_CONTENT_TYPE; header.value = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x"; header.kind = MHD_HEADER_KIND; pp = MHD_create_post_processor (&connection, 1024, &value_checker, &want_off); MHD_post_process (pp, FORM_DATA, splitpoint); MHD_post_process (pp, &FORM_DATA[splitpoint], size - splitpoint); MHD_destroy_post_processor (pp); if (want_off != FORM_END) return (int) splitpoint; } return 0; }
static int test_nested_multipart () { struct MHD_Connection connection; struct MHD_HTTP_Header header; struct MHD_PostProcessor *pp; unsigned int want_off = FORM_NESTED_START; int i; int delta; size_t size; memset (&connection, 0, sizeof (struct MHD_Connection)); memset (&header, 0, sizeof (struct MHD_HTTP_Header)); connection.headers_received = &header; header.header = MHD_HTTP_HEADER_CONTENT_TYPE; header.value = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x"; header.kind = MHD_HEADER_KIND; pp = MHD_create_post_processor (&connection, 1024, &value_checker, &want_off); i = 0; size = strlen (FORM_NESTED_DATA); while (i < size) { delta = 1 + MHD_random_ () % (size - i); MHD_post_process (pp, &FORM_NESTED_DATA[i], delta); i += delta; } MHD_destroy_post_processor (pp); if (want_off != FORM_NESTED_END) return 4; return 0; }
static int test_empty_value () { struct MHD_Connection connection; struct MHD_HTTP_Header header; struct MHD_PostProcessor *pp; unsigned int want_off = URL_EMPTY_VALUE_START; int i; int delta; size_t size; memset (&connection, 0, sizeof (struct MHD_Connection)); memset (&header, 0, sizeof (struct MHD_HTTP_Header)); connection.headers_received = &header; header.header = MHD_HTTP_HEADER_CONTENT_TYPE; header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED; header.kind = MHD_HEADER_KIND; pp = MHD_create_post_processor (&connection, 1024, &value_checker, &want_off); i = 0; size = strlen (URL_EMPTY_VALUE_DATA); while (i < size) { delta = 1 + MHD_random_ () % (size - i); MHD_post_process (pp, &URL_EMPTY_VALUE_DATA[i], delta); i += delta; } MHD_destroy_post_processor (pp); if (want_off != URL_EMPTY_VALUE_END) return 8; return 0; }
int RESTRequest::processUploadData( const char *upload_data, size_t upload_data_size ) { if( postProcessor == NULL ) { postProcessor = MHD_create_post_processor( connection, POSTBUFFERSIZE, RESTRequest::iterate_post, (void *) this ); } if( NULL == postProcessor ) { return 0; } int result = MHD_post_process( postProcessor, upload_data, upload_data_size ); printf( "processUploadData: %d\n", result ); // Attempt to do form data processing. if( result == MHD_NO ) { // The data wansn't in url-encoded form to just store it raw. inRepresentation.appendData( upload_data, upload_data_size ); } return 0; }
static int test_multipart_garbage () { struct MHD_Connection connection; struct MHD_HTTP_Header header; struct MHD_PostProcessor *pp; unsigned int want_off; size_t size = strlen (FORM_DATA); size_t splitpoint; char xdata[size + 3]; /* fill in evil garbage at the beginning */ xdata[0] = '-'; xdata[1] = 'x'; xdata[2] = '\r'; memcpy (&xdata[3], FORM_DATA, size); size += 3; size = strlen (FORM_DATA); for (splitpoint = 1; splitpoint < size; splitpoint++) { want_off = FORM_START; memset (&connection, 0, sizeof (struct MHD_Connection)); memset (&header, 0, sizeof (struct MHD_HTTP_Header)); connection.headers_received = &header; header.header = MHD_HTTP_HEADER_CONTENT_TYPE; header.value = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x"; header.kind = MHD_HEADER_KIND; pp = MHD_create_post_processor (&connection, 1024, &value_checker, &want_off); MHD_post_process (pp, xdata, splitpoint); MHD_post_process (pp, &xdata[splitpoint], size - splitpoint); MHD_destroy_post_processor (pp); if (want_off != FORM_END) return (int) splitpoint; } return 0; }
int handle(Request* request, MHD_Connection* connection, const char* url, const char* method, const char* upload_data, size_t* upload_data_size) override { UploadContext* uc = request->fUploadContext; // New connection if (!uc) { // TODO make this a method on request uc = new UploadContext; uc->connection = connection; uc->fPostProcessor = MHD_create_post_processor(connection, kBufferSize, &process_upload_data, uc); SkASSERT(uc->fPostProcessor); request->fUploadContext = uc; return MHD_YES; } // in process upload if (0 != *upload_data_size) { SkASSERT(uc->fPostProcessor); MHD_post_process(uc->fPostProcessor, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } // end of upload MHD_destroy_post_processor(uc->fPostProcessor); uc->fPostProcessor = nullptr; // parse picture from stream request->fPicture.reset( SkPicture::CreateFromStream(request->fUploadContext->fStream.detachAsStream())); if (!request->fPicture.get()) { fprintf(stderr, "Could not create picture from stream.\n"); return MHD_NO; } // pour picture into debug canvas request->fDebugCanvas.reset(new SkDebugCanvas(kImageWidth, kImageHeight)); request->fDebugCanvas->drawPicture(request->fPicture); // clear upload context delete request->fUploadContext; request->fUploadContext = nullptr; return SendTemplate(connection, true, "/"); }
static int ahc_echo (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 **unused) { static int eok; struct MHD_Response *response; struct MHD_PostProcessor *pp; int ret; if (0 != strcmp ("POST", method)) { printf ("METHOD: %s\n", method); return MHD_NO; /* unexpected method */ } pp = *unused; if (pp == NULL) { eok = 0; pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok); if (pp == NULL) abort (); *unused = pp; } MHD_post_process (pp, upload_data, *upload_data_size); if ((eok == 3) && (0 == *upload_data_size)) { response = MHD_create_response_from_buffer (strlen (url), (void *) url, MHD_RESPMEM_MUST_COPY); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); MHD_destroy_post_processor (pp); *unused = NULL; return ret; } *upload_data_size = 0; return MHD_YES; }
bool CWebServer::ProcessPostData(const HTTPRequest& request, ConnectionHandler *connectionHandler, const char *upload_data, size_t *upload_data_size, void **con_cls) const { if (connectionHandler->requestHandler == nullptr) { CLog::Log(LOGERROR, "CWebServer[%hu]: cannot handle partial HTTP POST for %s request because there is no valid request handler available", m_port, request.pathUrl.c_str()); connectionHandler->errorStatus = MHD_HTTP_INTERNAL_SERVER_ERROR; } // we only need to handle POST data if there actually is data left to handle if (*upload_data_size == 0) return false; // we may need to handle more POST data which is done in the next call to AnswerToConnection *con_cls = connectionHandler; // if nothing has gone wrong so far, process the given POST data if (connectionHandler->errorStatus == MHD_HTTP_OK) { bool postDataHandled = false; // either use MHD's POST processor if (connectionHandler->postprocessor != nullptr) postDataHandled = MHD_post_process(connectionHandler->postprocessor, upload_data, *upload_data_size) == MHD_YES; // or simply copy the data to the handler else if (connectionHandler->requestHandler != nullptr) postDataHandled = connectionHandler->requestHandler->AddPostData(upload_data, *upload_data_size); // abort if the received POST data couldn't be handled if (!postDataHandled) { CLog::Log(LOGERROR, "CWebServer[%hu]: failed to handle HTTP POST data for %s", m_port, request.pathUrl.c_str()); #if (MHD_VERSION >= 0x00095213) connectionHandler->errorStatus = MHD_HTTP_PAYLOAD_TOO_LARGE; #else connectionHandler->errorStatus = MHD_HTTP_REQUEST_ENTITY_TOO_LARGE; #endif } } // signal that we have handled the data *upload_data_size = 0; return true; }
static int test_simple_large () { struct MHD_Connection connection; struct MHD_HTTP_Header header; struct MHD_PostProcessor *pp; int i; int delta; size_t size; char data[102400]; unsigned int pos; pos = 0; memset (data, 'A', sizeof(data)); memcpy (data, "key=", 4); data[sizeof(data)-1] = '\0'; memset (&connection, 0, sizeof (struct MHD_Connection)); memset (&header, 0, sizeof (struct MHD_HTTP_Header)); connection.headers_received = &header; header.header = MHD_HTTP_HEADER_CONTENT_TYPE; header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED; header.kind = MHD_HEADER_KIND; pp = MHD_create_post_processor (&connection, 1024, &value_checker, &pos); i = 0; size = strlen (data); while (i < size) { delta = 1 + random () % (size - i); MHD_post_process (pp, &data[i], delta); i += delta; } MHD_destroy_post_processor (pp); if (pos != sizeof(data) - 5) /* minus 0-termination and 'key=' */ return 1; return 0; }
int answer_to_connection (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) { str page = {NULL, 0}; struct MHD_Response *response; int ret; void *async_data = NULL; struct httpd_cb *cb; const char *normalised_url; struct post_request *pr; str_str_t *kv; char *p; int cnt_type = HTTPD_STD_CNT_TYPE; int accept_type = HTTPD_STD_CNT_TYPE; int ret_code = MHD_HTTP_OK; LM_DBG("START *** cls=%p, connection=%p, url=%s, method=%s, " "versio=%s, upload_data[%zu]=%p, *con_cls=%p\n", cls, connection, url, method, version, *upload_data_size, upload_data, *con_cls); pr = *con_cls; if(pr == NULL){ pr = pkg_malloc(sizeof(struct post_request)); if(pr==NULL) { LM_ERR("oom while allocating post_request structure\n"); return MHD_NO; } memset(pr, 0, sizeof(struct post_request)); *con_cls = pr; pr = NULL; } if(strncmp(method, "POST", 4)==0) { if(pr == NULL){ pr = *con_cls; pr->p_list = slinkedl_init(&httpd_alloc, &httpd_free); if (pr->p_list==NULL) { LM_ERR("oom while allocating list\n"); return MHD_NO; } LM_DBG("running MHD_create_post_processor\n"); pr->pp = MHD_create_post_processor(connection, post_buf_size, &post_iterator, pr); if(pr->pp==NULL) { if (*upload_data_size == 0) { /* We need to wait for morte data before * handling the POST request */ return MHD_YES; } LM_DBG("NOT a regular POST :o)\n"); if (pr->content_type==0 && pr->content_len==0) MHD_get_connection_values(connection, MHD_HEADER_KIND, &getConnectionHeader, pr); if (pr->content_type<=0 || pr->content_len<=0) { LM_ERR("got a bogus request\n"); return MHD_NO; } if (*upload_data_size != pr->content_len) { /* For now, we don't support large POST with truncated data */ LM_ERR("got a truncated POST request\n"); return MHD_NO; } LM_DBG("got ContentType [%d] with len [%d]: %.*s\\n", pr->content_type, pr->content_len, (int)*upload_data_size, upload_data); /* Here we save data. */ switch (pr->content_type) { case HTTPD_TEXT_XML_CNT_TYPE: case HTTPD_APPLICATION_JSON_CNT_TYPE: /* Save the entire body as 'body' */ kv = (str_str_t*)slinkedl_append(pr->p_list, sizeof(str_str_t) + 1 + *upload_data_size); p = (char*)(kv + 1); kv->key.len = 1; kv->key.s = p; memcpy(p, "1", 1); p += 1; kv->val.len = *upload_data_size; kv->val.s = p; memcpy(p, upload_data, *upload_data_size); break; default: LM_ERR("Unhandled data for ContentType [%d]\n", pr->content_type); return MHD_NO; } /* Mark the fact that we consumed all data */ *upload_data_size = 0; return MHD_YES; } LM_DBG("pr=[%p] pp=[%p] p_list=[%p]\n", pr, pr->pp, pr->p_list); return MHD_YES; } else { if (pr->pp==NULL) { if (*upload_data_size == 0) { if (pr->content_type==HTTPD_TEXT_XML_CNT_TYPE) cnt_type = HTTPD_TEXT_XML_CNT_TYPE; if (pr->content_type==HTTPD_APPLICATION_JSON_CNT_TYPE) cnt_type = HTTPD_APPLICATION_JSON_CNT_TYPE; *con_cls = pr->p_list; cb = get_httpd_cb(url); if (cb) { normalised_url = &url[cb->http_root->len+1]; LM_DBG("normalised_url=[%s]\n", normalised_url); ret_code = cb->callback(cls, (void*)connection, normalised_url, method, version, upload_data, upload_data_size, con_cls, &buffer, &page); } else { page = MI_HTTP_U_URL; ret_code = MHD_HTTP_BAD_REQUEST; } /* slinkedl_traverse(pr->p_list, &httpd_print_data, NULL, NULL); */ slinkedl_list_destroy(*con_cls); pkg_free(pr); *con_cls = pr = NULL; goto send_response; } LM_DBG("NOT a regular POST :o)\n"); if (pr->content_type==0 && pr->content_len==0) MHD_get_connection_values(connection, MHD_HEADER_KIND, &getConnectionHeader, pr); if (pr->content_type<=0 || pr->content_len<=0) { LM_ERR("got a bogus request\n"); return MHD_NO; } if (*upload_data_size != pr->content_len) { /* For now, we don't support large POST with truncated data */ LM_ERR("got a truncated POST request\n"); return MHD_NO; } LM_DBG("got ContentType [%d] with len [%d]: %.*s\\n", pr->content_type, pr->content_len, (int)*upload_data_size, upload_data); /* Here we save data. */ switch (pr->content_type) { case HTTPD_TEXT_XML_CNT_TYPE: case HTTPD_APPLICATION_JSON_CNT_TYPE: /* Save the entire body as 'body' */ kv = (str_str_t*)slinkedl_append(pr->p_list, sizeof(str_str_t) + 1 + *upload_data_size); p = (char*)(kv + 1); kv->key.len = 1; kv->key.s = p; memcpy(p, "1", 1); p += 1; kv->val.len = *upload_data_size; kv->val.s = p; memcpy(p, upload_data, *upload_data_size); break; default: LM_ERR("Unhandled data for ContentType [%d]\n", pr->content_type); return MHD_NO; } /* Mark the fact that we consumed all data */ *upload_data_size = 0; return MHD_YES; } LM_DBG("running MHD_post_process: " "pp=%p status=%d upload_data_size=%zu\n", pr->pp, pr->status, *upload_data_size); if (pr->status<0) { slinkedl_list_destroy(pr->p_list); pr->p_list = NULL; /* FIXME: * It might be better to reply with an error * instead of resetting the connection via MHD_NO */ return MHD_NO; } ret =MHD_post_process(pr->pp, upload_data, *upload_data_size); LM_DBG("ret=%d upload_data_size=%zu\n", ret, *upload_data_size); if(*upload_data_size != 0) { *upload_data_size = 0; return MHD_YES; } LM_DBG("running MHD_destroy_post_processor: " "pr=[%p] pp=[%p] p_list=[%p]\n", pr, pr->pp, pr->p_list); MHD_destroy_post_processor(pr->pp); LM_DBG("done MHD_destroy_post_processor\n"); /* slinkedl_traverse(pr->p_list, &httpd_print_data, NULL, NULL); */ *con_cls = pr->p_list; cb = get_httpd_cb(url); if (cb) { normalised_url = &url[cb->http_root->len+1]; LM_DBG("normalised_url=[%s]\n", normalised_url); ret_code = cb->callback(cls, (void*)connection, normalised_url, method, version, upload_data, upload_data_size, con_cls, &buffer, &page); } else { page = MI_HTTP_U_URL; ret_code = MHD_HTTP_BAD_REQUEST; } /* slinkedl_traverse(pr->p_list, &httpd_print_data, NULL, NULL); */ slinkedl_list_destroy(*con_cls); pkg_free(pr); *con_cls = pr = NULL; } }else if(strncmp(method, "GET", 3)==0) { pr = *con_cls; MHD_get_connection_values(connection, MHD_HEADER_KIND, &getConnectionHeader, pr); accept_type = pr->accept_type; pkg_free(pr); *con_cls = pr = NULL; LM_DBG("accept_type=[%d]\n", accept_type); cb = get_httpd_cb(url); if (cb) { normalised_url = &url[cb->http_root->len+1]; LM_DBG("normalised_url=[%s]\n", normalised_url); ret_code = cb->callback(cls, (void*)connection, normalised_url, method, version, upload_data, upload_data_size, con_cls, &buffer, &page); } else { page = MI_HTTP_U_URL; ret_code = MHD_HTTP_BAD_REQUEST; } }else{ page = MI_HTTP_U_METHOD; ret_code = MHD_HTTP_METHOD_NOT_ACCEPTABLE; } send_response: if (page.s) { LM_DBG("MHD_create_response_from_data [%p:%d]\n", page.s, page.len); response = MHD_create_response_from_data(page.len, (void*)page.s, 0, 1); } else { LM_DBG("MHD_create_response_from_callback\n"); response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, buffer.len, cb->flush_data_callback, (void*)async_data, NULL); } if (cnt_type==HTTPD_TEXT_XML_CNT_TYPE || accept_type==HTTPD_TEXT_XML_CNT_TYPE) MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/xml; charset=utf-8"); if (cnt_type==HTTPD_APPLICATION_JSON_CNT_TYPE || accept_type==HTTPD_APPLICATION_JSON_CNT_TYPE) MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, "application/json"); ret = MHD_queue_response (connection, ret_code, response); MHD_destroy_response (response); return ret; }
int CWebServer::AnswerToConnection(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, unsigned int *upload_data_size, void **con_cls) #endif { if (cls == NULL || con_cls == NULL || *con_cls == NULL) { CLog::Log(LOGERROR, "CWebServer: invalid request received"); return MHD_NO; } CWebServer *server = reinterpret_cast<CWebServer*>(cls); std::auto_ptr<ConnectionHandler> conHandler(reinterpret_cast<ConnectionHandler*>(*con_cls)); HTTPMethod methodType = GetMethod(method); HTTPRequest request = { server, connection, conHandler->fullUri, url, methodType, version }; // remember if the request was new bool isNewRequest = conHandler->isNew; // because now it isn't anymore conHandler->isNew = false; // reset con_cls and set it if still necessary *con_cls = NULL; #ifdef WEBSERVER_DEBUG if (isNewRequest) { std::multimap<std::string, std::string> headerValues; GetRequestHeaderValues(connection, MHD_HEADER_KIND, headerValues); std::multimap<std::string, std::string> getValues; GetRequestHeaderValues(connection, MHD_GET_ARGUMENT_KIND, getValues); CLog::Log(LOGDEBUG, "webserver [IN] %s %s %s", version, method, request.pathUrlFull.c_str()); if (!getValues.empty()) { std::string tmp; for (std::multimap<std::string, std::string>::const_iterator get = getValues.begin(); get != getValues.end(); ++get) { if (get != getValues.begin()) tmp += "; "; tmp += get->first + " = " + get->second; } CLog::Log(LOGDEBUG, "webserver [IN] Query arguments: %s", tmp.c_str()); } for (std::multimap<std::string, std::string>::const_iterator header = headerValues.begin(); header != headerValues.end(); ++header) CLog::Log(LOGDEBUG, "webserver [IN] %s: %s", header->first.c_str(), header->second.c_str()); } #endif if (!IsAuthenticated(server, connection)) return AskForAuthentication(connection); // check if this is the first call to AnswerToConnection for this request if (isNewRequest) { // parse the Range header and store it in the request object CHttpRanges ranges; bool ranged = ranges.Parse(GetRequestHeaderValue(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_RANGE)); // look for a IHTTPRequestHandler which can take care of the current request for (std::vector<IHTTPRequestHandler *>::const_iterator it = m_requestHandlers.begin(); it != m_requestHandlers.end(); ++it) { IHTTPRequestHandler *requestHandler = *it; if (requestHandler->CanHandleRequest(request)) { // we found a matching IHTTPRequestHandler so let's get a new instance for this request IHTTPRequestHandler *handler = requestHandler->Create(request); // if we got a GET request we need to check if it should be cached if (methodType == GET) { if (handler->CanBeCached()) { bool cacheable = true; // handle Cache-Control std::string cacheControl = GetRequestHeaderValue(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CACHE_CONTROL); if (!cacheControl.empty()) { std::vector<std::string> cacheControls = StringUtils::Split(cacheControl, ","); for (std::vector<std::string>::const_iterator it = cacheControls.begin(); it != cacheControls.end(); ++it) { std::string control = *it; control = StringUtils::Trim(control); // handle no-cache if (control.compare(HEADER_VALUE_NO_CACHE) == 0) cacheable = false; } } if (cacheable) { // handle Pragma (but only if "Cache-Control: no-cache" hasn't been set) std::string pragma = GetRequestHeaderValue(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_PRAGMA); if (pragma.compare(HEADER_VALUE_NO_CACHE) == 0) cacheable = false; } CDateTime lastModified; if (handler->GetLastModifiedDate(lastModified) && lastModified.IsValid()) { // handle If-Modified-Since or If-Unmodified-Since std::string ifModifiedSince = GetRequestHeaderValue(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_IF_MODIFIED_SINCE); std::string ifUnmodifiedSince = GetRequestHeaderValue(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_IF_UNMODIFIED_SINCE); CDateTime ifModifiedSinceDate; CDateTime ifUnmodifiedSinceDate; // handle If-Modified-Since (but only if the response is cacheable) if (cacheable && ifModifiedSinceDate.SetFromRFC1123DateTime(ifModifiedSince) && lastModified.GetAsUTCDateTime() <= ifModifiedSinceDate) { struct MHD_Response *response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO); if (response == NULL) { CLog::Log(LOGERROR, "CWebServer: failed to create a HTTP 304 response"); return MHD_NO; } return FinalizeRequest(handler, MHD_HTTP_NOT_MODIFIED, response); } // handle If-Unmodified-Since else if (ifUnmodifiedSinceDate.SetFromRFC1123DateTime(ifUnmodifiedSince) && lastModified.GetAsUTCDateTime() > ifUnmodifiedSinceDate) return SendErrorResponse(connection, MHD_HTTP_PRECONDITION_FAILED, methodType); } // handle If-Range header but only if the Range header is present if (ranged && lastModified.IsValid()) { std::string ifRange = GetRequestHeaderValue(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_IF_RANGE); if (!ifRange.empty() && lastModified.IsValid()) { CDateTime ifRangeDate; ifRangeDate.SetFromRFC1123DateTime(ifRange); // check if the last modification is newer than the If-Range date // if so we have to server the whole file instead if (lastModified.GetAsUTCDateTime() > ifRangeDate) ranges.Clear(); } } // pass the requested ranges on to the request handler handler->SetRequestRanged(!ranges.IsEmpty()); } } // if we got a POST request we need to take care of the POST data else if (methodType == POST) { conHandler->requestHandler = handler; // get the content-type of the POST data std::string contentType = GetRequestHeaderValue(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_TYPE); if (!contentType.empty()) { // if the content-type is application/x-ww-form-urlencoded or multipart/form-data we can use MHD's POST processor if (StringUtils::EqualsNoCase(contentType, MHD_HTTP_POST_ENCODING_FORM_URLENCODED) || StringUtils::EqualsNoCase(contentType, MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)) { // Get a new MHD_PostProcessor conHandler->postprocessor = MHD_create_post_processor(connection, MAX_POST_BUFFER_SIZE, &CWebServer::HandlePostField, (void*)conHandler.get()); // MHD doesn't seem to be able to handle this post request if (conHandler->postprocessor == NULL) { CLog::Log(LOGERROR, "CWebServer: unable to create HTTP POST processor for %s", url); delete conHandler->requestHandler; return SendErrorResponse(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, methodType); } } } // otherwise we need to handle the POST data ourselves which is done in the next call to AnswerToConnection // as ownership of the connection handler is passed to libmicrohttpd we must not destroy it *con_cls = conHandler.release(); return MHD_YES; } return HandleRequest(handler); } } } // this is a subsequent call to AnswerToConnection for this request else { // again we need to take special care of the POST data if (methodType == POST) { if (conHandler->requestHandler == NULL) { CLog::Log(LOGERROR, "CWebServer: cannot handle partial HTTP POST for %s request because there is no valid request handler available", url); return SendErrorResponse(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, methodType); } // we only need to handle POST data if there actually is data left to handle if (*upload_data_size > 0) { // either use MHD's POST processor if (conHandler->postprocessor != NULL) MHD_post_process(conHandler->postprocessor, upload_data, *upload_data_size); // or simply copy the data to the handler else conHandler->requestHandler->AddPostData(upload_data, *upload_data_size); // signal that we have handled the data *upload_data_size = 0; // we may need to handle more POST data which is done in the next call to AnswerToConnection // as ownership of the connection handler is passed to libmicrohttpd we must not destroy it *con_cls = conHandler.release(); return MHD_YES; } // we have handled all POST data so it's time to invoke the IHTTPRequestHandler else { if (conHandler->postprocessor != NULL) MHD_destroy_post_processor(conHandler->postprocessor); return HandleRequest(conHandler->requestHandler); } } // it's unusual to get more than one call to AnswerToConnection for none-POST requests, but let's handle it anyway else { for (std::vector<IHTTPRequestHandler *>::const_iterator it = m_requestHandlers.begin(); it != m_requestHandlers.end(); ++it) { IHTTPRequestHandler *requestHandler = *it; if (requestHandler->CanHandleRequest(request)) return HandleRequest(requestHandler->Create(request)); } } } CLog::Log(LOGERROR, "CWebServer: couldn't find any request handler for %s", url); return SendErrorResponse(connection, MHD_HTTP_NOT_FOUND, methodType); }
/** * Main MHD callback for handling requests. * * * @param cls argument given together with the function * pointer when the handler was registered with MHD * @param url the requested url * @param method the HTTP method used ("GET", "PUT", etc.) * @param version the HTTP version string (i.e. "HTTP/1.1") * @param upload_data the data being uploaded (excluding HEADERS, * for a POST that fits into memory and that is encoded * with a supported encoding, the POST data will NOT be * given in upload_data and is instead available as * part of MHD_get_connection_values; very large POST * data *will* be made available incrementally in * upload_data) * @param upload_data_size set initially to the size of the * upload_data provided; the method must update this * value to the number of bytes NOT processed; * @param con_cls pointer that the callback can set to some * address and that will be preserved by MHD for future * calls for this request; since the access handler may * be called many times (i.e., for a PUT/POST operation * with plenty of upload data) this allows the application * to easily associate some request-specific state. * If necessary, this state can be cleaned up in the * global "MHD_RequestCompleted" callback (which * can be set with the MHD_OPTION_NOTIFY_COMPLETED). * Initially, <tt>*con_cls</tt> will be NULL. * @return MHS_YES if the connection was handled successfully, * MHS_NO if the socket must be closed due to a serios * error while handling the request */ static int create_response (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 **ptr) { struct MHD_Response *response; struct Request *request; struct Session *session; int ret; unsigned int i; request = *ptr; if (NULL == request) { request = calloc (1, sizeof (struct Request)); if (NULL == request) { fprintf (stderr, "calloc error: %s\n", strerror (errno)); return MHD_NO; } *ptr = request; if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) { request->pp = MHD_create_post_processor (connection, 1024, &post_iterator, request); if (NULL == request->pp) { fprintf (stderr, "Failed to setup post processor for `%s'\n", url); return MHD_NO; /* internal error */ } } return MHD_YES; } if (NULL == request->session) { request->session = get_session (connection); if (NULL == request->session) { fprintf (stderr, "Failed to setup session for `%s'\n", url); return MHD_NO; /* internal error */ } } session = request->session; session->start = time (NULL); if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) { /* evaluate POST data */ MHD_post_process (request->pp, upload_data, *upload_data_size); if (0 != *upload_data_size) { *upload_data_size = 0; return MHD_YES; } /* done with POST data, serve response */ MHD_destroy_post_processor (request->pp); request->pp = NULL; method = MHD_HTTP_METHOD_GET; /* fake 'GET' */ if (NULL != request->post_url) url = request->post_url; } if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) || (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) ) { /* find out which page to serve */ i=0; while ( (pages[i].url != NULL) && (0 != strcmp (pages[i].url, url)) ) i++; ret = pages[i].handler (pages[i].handler_cls, pages[i].mime, session, connection); if (ret != MHD_YES) fprintf (stderr, "Failed to create page for `%s'\n", url); return ret; } /* unsupported HTTP method */ response = MHD_create_response_from_buffer (strlen (METHOD_ERROR), (void *) METHOD_ERROR, MHD_RESPMEM_PERSISTENT); ret = MHD_queue_response (connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE, response); MHD_destroy_response (response); return ret; }
/** * A client has requested the given url using the given method * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT, * #MHD_HTTP_METHOD_DELETE, #MHD_HTTP_METHOD_POST, etc). The callback * must call MHD callbacks to provide content to give back to the * client and return an HTTP status code (i.e. #MHD_HTTP_OK, * #MHD_HTTP_NOT_FOUND, etc.). * * @param cls argument given together with the function * pointer when the handler was registered with MHD * @param url the requested url * @param method the HTTP method used (#MHD_HTTP_METHOD_GET, * #MHD_HTTP_METHOD_PUT, etc.) * @param version the HTTP version string (i.e. * #MHD_HTTP_VERSION_1_1) * @param upload_data the data being uploaded (excluding HEADERS, * for a POST that fits into memory and that is encoded * with a supported encoding, the POST data will NOT be * given in upload_data and is instead available as * part of #MHD_get_connection_values; very large POST * data *will* be made available incrementally in * @a upload_data) * @param upload_data_size set initially to the size of the * @a upload_data provided; the method must update this * value to the number of bytes NOT processed; * @param con_cls pointer that the callback can set to some * address and that will be preserved by MHD for future * calls for this request; since the access handler may * be called many times (i.e., for a PUT/POST operation * with plenty of upload data) this allows the application * to easily associate some request-specific state. * If necessary, this state can be cleaned up in the * global #MHD_RequestCompletedCallback (which * can be set with the #MHD_OPTION_NOTIFY_COMPLETED). * Initially, `*con_cls` will be NULL. * @return #MHD_YES if the connection was handled successfully, * #MHD_NO if the socket must be closed due to a serios * error while handling the request */ static int answer_to_connection(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 (*con_cls == NULL) { printf("CON_CLS is NULL. Request-type: %s\n", method); struct connection_info_struct *con_info; con_info = malloc(sizeof(struct connection_info_struct)); if (con_info == NULL) { return MHD_NO; } con_info->answerstring = NULL; if (strcmp(method, "POST") == 0) { con_info->postprocessor = MHD_create_post_processor(connection, POSTBUFFERSIZE, iterate_post, (void *) con_info); if (con_info->postprocessor == NULL) { free(con_info); return MHD_NO; } con_info->connectiontype = POST; } else if (strcmp(method, "DELETE") == 0) { con_info->connectiontype = DELETE; } else { con_info->connectiontype = GET; } *con_cls = (void *) con_info; return MHD_YES; } printf("CON_CLS is NOT NULL.\n"); if (0 == strcmp(method, "GET")) { char modifiableUrl [strlen(url) + 1]; strncpy(modifiableUrl, url, sizeof modifiableUrl); modifiableUrl[strlen(url)] = '\0'; char * argument = strtok(modifiableUrl, "/"); // remove api name argument = strtok(NULL, "/"); int parsedArgument = atoi(argument); int responseValue = hashGet(parsedArgument); if (responseValue >= 0) { char buffer[100]; // totally arbitrary but pretty big sprintf(buffer, "200 - OK\nValue: %d\n", responseValue); return send_page(connection, MHD_HTTP_OK, buffer); } else if (responseValue == NOT_FOUND) { return send_page(connection, 404, "404 - Not found\nThere are no entries matching your key.\n"); } else { return send_page(connection, 500, "500 - Internal server error\n"); } } if (0 == strcmp(method, "DELETE")) { printf("DELETE REQUEST to %s >>>\n", url); char modifiableUrl [strlen(url) + 1]; strncpy(modifiableUrl, url, sizeof modifiableUrl); modifiableUrl[strlen(url)] = '\0'; char * argument = strtok(modifiableUrl, "/"); // remove api name argument = strtok(NULL, "/"); int parsedArgument = atoi(argument); printf("Parsed as %d from %s\n", parsedArgument, argument); int responseValue = hashDel(parsedArgument); printf("Result: %d\n", responseValue); if (responseValue >= 0) { return send_page(connection, 200, "200 - OK\n"); } else if (responseValue == NOT_FOUND) { return send_page(connection, 404, "404 - Not found\nThere are no entries matching your key.\n"); } else { return send_page(connection, 500, "500 - Internal server error\n"); } } if (0 == strcmp(method, "POST")) { struct connection_info_struct *con_info = *con_cls; if (*upload_data_size != 0) { MHD_post_process(con_info->postprocessor, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } else if (keySet && valueSet) { keySet = 0; valueSet = 0; printf("Set %d:%d!\n", key, value); if (hashSet(key, value)) { const char *responseText = "201 - Created\n"; struct MHD_Response *response = MHD_create_response_from_buffer(strlen(responseText), (void*) responseText, MHD_RESPMEM_PERSISTENT); char buffer[100]; // totally arbitrary but pretty big sprintf(buffer, "http://localhost:%d%s/%d", port, url, key); MHD_add_response_header (response, "Location", buffer); int ret = MHD_queue_response (connection, 201, response); MHD_destroy_response(response); return MHD_YES; } else { return send_page(connection, 500, "500 - Internal server error\n"); } } else { return send_page(connection, MHD_HTTP_BAD_REQUEST, "400 - Malformed request\n"); } } return send_page(connection, MHD_HTTP_NOT_FOUND, "404 - Not found\n"); }
/** * Main callback from MHD, used to generate the page. * * @param cls NULL * @param connection connection handle * @param url requested URL * @param method GET, PUT, POST, etc. * @param version HTTP version * @param upload_data data from upload (PUT/POST) * @param upload_data_size number of bytes in "upload_data" * @param ptr our context * @return MHD_YES on success, MHD_NO to drop connection */ static int generate_page (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 **ptr) { struct MHD_Response *response; int ret; int fd; struct stat buf; if (0 != strcmp (url, "/")) { /* should be file download */ char file_data[MAGIC_HEADER_SIZE]; ssize_t got; const char *mime; if ( (0 != strcmp (method, MHD_HTTP_METHOD_GET)) && (0 != strcmp (method, MHD_HTTP_METHOD_HEAD)) ) return MHD_NO; /* unexpected method (we're not polite...) */ if ( (0 == stat (&url[1], &buf)) && (NULL == strstr (&url[1], "..")) && ('/' != url[1])) fd = open (&url[1], O_RDONLY); else fd = -1; if (-1 == fd) return MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, file_not_found_response); /* read beginning of the file to determine mime type */ got = read (fd, file_data, sizeof (file_data)); if (-1 != got) mime = magic_buffer (magic, file_data, got); else mime = NULL; (void) lseek (fd, 0, SEEK_SET); if (NULL == (response = MHD_create_response_from_fd (buf.st_size, fd))) { /* internal error (i.e. out of memory) */ (void) close (fd); return MHD_NO; } /* add mime type if we had one */ if (NULL != mime) (void) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, mime); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return ret; } if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) { /* upload! */ struct UploadContext *uc = *ptr; if (NULL == uc) { if (NULL == (uc = malloc (sizeof (struct UploadContext)))) return MHD_NO; /* out of memory, close connection */ memset (uc, 0, sizeof (struct UploadContext)); uc->fd = -1; uc->connection = connection; uc->pp = MHD_create_post_processor (connection, 64 * 1024 /* buffer size */, &process_upload_data, uc); if (NULL == uc->pp) { /* out of memory, close connection */ free (uc); return MHD_NO; } *ptr = uc; return MHD_YES; } if (0 != *upload_data_size) { if (NULL == uc->response) (void) MHD_post_process (uc->pp, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } /* end of upload, finish it! */ MHD_destroy_post_processor (uc->pp); uc->pp = NULL; if (-1 != uc->fd) { close (uc->fd); uc->fd = -1; } if (NULL != uc->response) { return MHD_queue_response (connection, MHD_HTTP_FORBIDDEN, uc->response); } else { update_directory (); return return_directory_response (connection); } } if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) || (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) ) { return return_directory_response (connection); } /* unexpected request, refuse */ return MHD_queue_response (connection, MHD_HTTP_FORBIDDEN, request_refused_response); }
static int server_handler( void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_size, void **con_cls) { if(NULL == *con_cls) { //first time, read header //puts("first"); //printf("%s %s\n", method, url); if(strcmp(method, "GET") == 0) { char *result; applog(url); if(strstr(url, "/query_") == url) { if(result=JUDGE_get_progress(url)) { struct MHD_Response *response = MHD_create_response_from_buffer(strlen(result), result, MHD_RESPMEM_MUST_FREE); // MHD_add_response_header(response, "Connection", "close"); int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; } }else if(strcmp(url, "/robots.txt") == 0) { struct MHD_Response *response = MHD_create_response_from_buffer(sizeof(robots_txt)-1, robots_txt, MHD_RESPMEM_PERSISTENT); // MHD_add_response_header(response, "Connection", "close"); int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; } return ignore_requst(connection); } if(strcmp(method, "POST") == 0 && strcmp(url, "/submit_prob") == 0) { //puts("accept"); pair *p = new pair; if(NULL == p) return MHD_NO; *con_cls = p; solution *body = new solution; if(NULL == body) return MHD_NO; p->second = body; MHD_PostProcessor *processor = MHD_create_post_processor(connection, 768, iterate_post, (void*)p); if(NULL == processor) return MHD_NO; p->first = processor; //puts("success"); return MHD_YES; } return ignore_requst(connection); }else{ pair *p = (pair*)*con_cls; if(0 != *upload_size) { //next, read body #ifdef DUMP_FOR_DEBUG p->second->raw_post_data += upload_data; #endif MHD_post_process(p->first, upload_data, *upload_size); *upload_size = 0; //puts("next"); return MHD_YES; }else{ //last time, finish reading //puts("last"); char *result; if(p->second->type == TYPE_rejudge) result = JUDGE_start_rejudge(p->second); else result = JUDGE_accept_submit(p->second); struct MHD_Response *response = MHD_create_response_from_buffer(strlen(result), result, MHD_RESPMEM_MUST_FREE); int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; } } }
int ahc_echo(void* servctx, MHD_Connection* connection, const char* url, const char* method, const char* version, const char* upload_data, size_t* upload_data_size, void** reqctx) { ServerContext* servctx_v = (ServerContext*)servctx; assert(servctx_v->MagicNumber == 0xbabeface); if (*reqctx == NULL) { assert(upload_data == NULL && *upload_data_size == 0); ConnContext* conctx = new ConnContext(); if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) { conctx->Method = HTTPMETHOD_GET; conctx->PostProcessor = NULL; } else if (strcmp(method, MHD_HTTP_METHOD_POST) == 0) { conctx->Method = HTTPMETHOD_POST; conctx->PostProcessor = MHD_create_post_processor(connection, 1024, MyPostDataIterator, conctx); } else return MHD_NO; // The first time only the headers are valid, do not respond in the first round. *reqctx = conctx; return MHD_YES; } else { ConnContext* conctx = (ConnContext*)(*reqctx); if (conctx->Method == HTTPMETHOD_GET) { assert(strcmp(method, MHD_HTTP_METHOD_GET) == 0); assert(*upload_data_size == 0); MHD_Response* response = MHD_create_response_from_buffer(sizeof(HELLO_MESSAGE), (void*)HELLO_MESSAGE, MHD_RESPMEM_PERSISTENT); MHD_add_response_header(response, "Content-Type", "text/html"); int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); // Do not call "*reqctx = NULL;" because a request completed callback would be called instead return ret; } else if (conctx->Method == HTTPMETHOD_POST) { if (*upload_data_size != 0) { MHD_post_process (conctx->PostProcessor, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } else { puts("[POST COMPLETE]"); std::string message = "<html><body>\n<p>POST</p>\n<ul>\n"; for (std::map<std::string, std::string>::iterator it = conctx->KeyValueMap.begin(); it != conctx->KeyValueMap.end(); ++it) { message += "<li>"; message += it->first; message += '='; message += it->second; message += "</li>\n"; } message += "</ul>\n</body></html>\n"; MHD_Response* response = MHD_create_response_from_buffer(message.size(), (void*)message.c_str(), MHD_RESPMEM_MUST_COPY); MHD_add_response_header(response, "Content-Type", "text/html"); int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); // Do not call "*reqctx = NULL;" because a request completed callback would be called instead return ret; } } else return MHD_NO; } }
int WebServer::createResponse (struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) { struct MHD_Response *response; struct Request *request; WebSession *session; int ret = MHD_NO; unsigned int i; request = (struct Request *)*ptr; if (NULL == request) { request = (struct Request *)calloc (1, sizeof (struct Request)); if (NULL == request) { fprintf (stderr, "calloc error: %s\n", strerror (errno)); return MHD_NO; } *ptr = request; if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) { request->pp = MHD_create_post_processor (connection, 1024, &post_iterator, request); if (NULL == request->pp) { fprintf (stderr, "Failed to setup post processor for `%s'\n", url); return MHD_NO; /* internal error */ } } return MHD_YES; } if (NULL == request->session) { request->session = getSession(connection); if (NULL == request->session) { fprintf (stderr, "Failed to setup session for `%s'\n", url); return MHD_NO; /* internal error */ } } session = request->session; session->start = time (NULL); if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) { /* evaluate POST data */ MHD_post_process (request->pp, upload_data, *upload_data_size); /* if (0 != *upload_data_size) { *upload_data_size = 0; return MHD_YES; } */ /* done with POST data, serve response */ MHD_destroy_post_processor (request->pp); request->pp = NULL; method = MHD_HTTP_METHOD_GET; /* fake 'GET' */ if (NULL != request->post_url) url = request->post_url; //handle data /* find out which page to serve */ WebPage * page = NULL; for (auto it = _pages.begin(); it != _pages.end(); it++) { WebPage *current = *it; if (strcmp (current->getURL().c_str(), url) == 0) { page = current; break; } } if (page != NULL) { page->handlePost(session, upload_data, *upload_data_size); } } if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) || (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) ) { /* find out which page to serve */ WebPage * page = NULL; for (auto it = _pages.begin(); it != _pages.end(); it++) { WebPage *current = *it; if (strcmp (current->getURL().c_str(), url) == 0) { page = current; break; } } if (page == NULL) { page = _notFoundPage; } std::cout << "Serving page" << std::endl; struct MHD_Response *response; std::string replyString = page->fillRequest(session); // return static form response = MHD_create_response_from_buffer (strlen (replyString.c_str()), (void *) replyString.c_str(), MHD_RESPMEM_MUST_COPY); if (NULL != response) { addSessionCookie(session, response); MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_ENCODING, page->getMime().c_str()); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); } /* i=0; while ( (pages[i].url != NULL) && (0 != strcmp (pages[i].url, url)) ) i++; ret = pages[i].handler (pages[i].handler_cls, pages[i].mime, session, connection); */ if (ret != MHD_YES) fprintf (stderr, "Failed to create page for `%s'\n", url); return ret; } /* unsupported HTTP method */ response = MHD_create_response_from_buffer (strlen (METHOD_ERROR), (void *) METHOD_ERROR, MHD_RESPMEM_PERSISTENT); ret = MHD_queue_response (connection, MHD_HTTP_NOT_ACCEPTABLE, response); MHD_destroy_response (response); return ret; }
static int cws_response (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 ** ptr) { int ret = MHD_NO; static int dummy; const char *webfile; char *page; char *basedir = ((cws_conn *) cls)->basedir; cws_astring *pathfile; struct MHD_Response *response; cws_handler *hdlr = ((cws_conn *) cls)->hdlr; const union MHD_ConnectionInfo *info; /* if (0 != strcmp(method, "GET")) return MHD_NO; */ webfile = url; if (&dummy != *ptr) { *ptr = &dummy; return MHD_YES; } *ptr = NULL; response = NULL; if (0 != *upload_data_size) { cws_handler *h = cws_handler_lookup (hdlr, webfile); if (h != NULL) { cws_dict *dict = NULL; struct MHD_PostProcessor *pp = MHD_create_post_processor(connection, 65536, post_processor, &dict); MHD_post_process(pp, upload_data, *upload_data_size); MHD_destroy_post_processor(pp); page = h->f(dict); printf("Page: %s\n", page); response = MHD_create_response_from_data (strlen (page), page, MHD_NO, MHD_YES); if (response) { printf("sending response\n"); MHD_add_response_header (response, "Content-Type", h->mimetype); ret = MHD_queue_response(connection, MHD_HTTP_OK, response); printf("if? %d\n", ret == MHD_YES ? 1 : 0); } MHD_destroy_response (response); free (page); cws_dict_free (&dict); } return MHD_NO; } info = MHD_get_connection_info (connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS); log_connections (inet_ntoa(((struct sockaddr_in *) info->client_addr)->sin_addr), url); if (strcmp (webfile, "/") == 0) webfile = "/index.html"; pathfile = cws_astring_new(basedir); cws_astring_cat(pathfile, webfile); if (access (CWS_ASTRING(pathfile), F_OK) != -1) { int fd = open (CWS_ASTRING(pathfile), O_RDONLY); struct stat sbuf; fstat (fd, &sbuf); response = MHD_create_response_from_fd (sbuf.st_size, fd); MHD_add_response_header (response, "Content-Type", cws_mime_type(CWS_ASTRING(pathfile))); } else { cws_handler *h = cws_handler_lookup (hdlr, webfile); if (h != NULL) { cws_dict *dict = NULL; MHD_get_connection_values (connection, MHD_GET_ARGUMENT_KIND, get_keys, &dict); page = h->f(dict); response = MHD_create_response_from_data (strlen (page), page, MHD_NO, MHD_YES); MHD_add_response_header (response, "Content-Type", h->mimetype); free (page); cws_dict_free (&dict); } else { response = MHD_create_response_from_data (strlen (ERROR_ANSWER), ERROR_ANSWER, MHD_NO, MHD_YES); MHD_add_response_header (response, "Content-Type", cws_mime_type("html")); } } if (response != NULL) { ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response (response); } cws_astring_free(pathfile); return ret; }
// Response to all POST request // 3 requests are correct : // - /GetJson --> Receive faust code / Compile Data / Send back jsonInterface // - /CreateInstance --> Receive factoryIndex / Create instance // - /DeleteFactory --> Receive factoryIndex / Delete Factory int Server::answer_post(MHD_Connection *connection, const char *url, const char *upload_data, size_t *upload_data_size, void **con_cls){ struct connection_info_struct *con_info = (connection_info_struct*)*con_cls; if (0 != *upload_data_size) { MHD_post_process(con_info->fPostprocessor, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } else { if(strcmp(url, "/GetJson") == 0){ if (compile_Data(con_info)) { return send_page(connection, con_info->fAnswerstring.c_str(), con_info->fAnswerstring.size(), MHD_HTTP_OK, "application/json"); } else { return send_page(connection, con_info->fAnswerstring.c_str(), con_info->fAnswerstring.size(), MHD_HTTP_BAD_REQUEST, "text/html"); } } else if(strcmp(url, "/GetJsonFromKey") == 0){ if (getJsonFromKey(con_info)) { return send_page(connection, con_info->fAnswerstring.c_str(), con_info->fAnswerstring.size(), MHD_HTTP_OK, "application/json"); } else { return send_page(connection, con_info->fAnswerstring.c_str(), con_info->fAnswerstring.size(), MHD_HTTP_BAD_REQUEST, "text/html"); } } else if(strcmp(url, "/CreateInstance") == 0){ if (createInstance(con_info)) { return send_page(connection, "", 0, MHD_HTTP_OK, "text/html"); } else { return send_page(connection, con_info->fAnswerstring.c_str(), con_info->fAnswerstring.size(), MHD_HTTP_BAD_REQUEST, "text/html"); } } // else if(strcmp(url, "/DeleteFactory") == 0){ // // llvm_dsp_factory* toDelete = fAvailableFactories[con_info->fSHAKey]; // // if (toDelete) { // // fAvailableFactories.erase(con_info->fSHAKey); // deleteSlaveDSPFactory(toDelete); // // return send_page(connection, "", 0, MHD_HTTP_OK, "application/html"); // } else { // return send_page(connection, "", 0, MHD_HTTP_BAD_REQUEST, "text/html"); // } // } else if(strcmp(url, "/StartAudio") == 0){ startAudio(con_info->fSHAKey); return send_page(connection, "", 0, MHD_HTTP_OK, "text/html"); } else if(strcmp(url, "/StopAudio") == 0){ stopAudio(con_info->fSHAKey); return send_page(connection, "", 0, MHD_HTTP_OK, "text/html"); } else{ return send_page(connection, "", 0, MHD_HTTP_BAD_REQUEST, "text/html"); } } }
static int answer_to_connection (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) { struct connection_info_struct *con_info = *con_cls; //printf("method =%s \n",method); if (NULL == *con_cls) { //printf("NuLl=ClS \n"); struct connection_info_struct *con_info; con_info = malloc (sizeof (struct connection_info_struct)); if (NULL == con_info) return MHD_NO; con_info->answerstring = NULL; if (0 == strcmp (method, "POST")) { con_info->postprocessor = MHD_create_post_processor (connection, POSTBUFFERSIZE, iterate_post, (void *) con_info); if (NULL == con_info->postprocessor) { free (con_info); return MHD_NO; } con_info->connectiontype = POST; } else con_info->connectiontype = GET; *con_cls = (void *) con_info; return MHD_YES; } if (0 == strcmp (method, "GET")) { char *reply; reply = malloc (strlen (askpage) + strlen (str) + 1); if (NULL == reply) return MHD_NO; snprintf (reply,strlen (askpage) + strlen (str) + 1,askpage,str); return send_page (connection,reply); } if (0 == strcmp (method, "POST")) { int ret; //char *reply; //char *str = "open"; //printf("PoSt \n"); //struct MHD_Response *response; //reply = malloc (strlen (askpage) + strlen (str) + 1); //if (NULL == reply) // return MHD_NO; //snprintf (reply,strlen (askpage) + strlen (str) + 1,askpage,str); //printf("reply= %s \n",reply); //struct connection_info_struct *con_info = *con_cls; if (*upload_data_size != 0) { MHD_post_process (con_info->postprocessor, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } else if (NULL != con_info->answerstring) return send_page (connection, con_info->answerstring); } return send_page (connection, errorpage); }
int Webserver::Handler (struct MHD_Connection *conn, const char *url, const char *method, const char *version, const char *up_data, size_t *up_data_size, void **ptr) { int ret; conninfo_t *cp; if (debug) fprintf(stderr, "%x: %s: \"%s\" conn=%x size=%d *ptr=%x\n", pthread_self(), method, url, conn, *up_data_size, *ptr); // add by zp //const char *encoding = MHD_lookup_connection_value (conn, // MHD_HEADER_KIND, // MHD_HTTP_HEADER_CONTENT_TYPE); //fprintf(stderr,"encoding: %s\n",encoding); if (*ptr == NULL) { /* do never respond on first call */ cp = (conninfo_t *)malloc(sizeof(conninfo_t)); if (cp == NULL) return MHD_NO; cp->conn_url = url; cp->conn_arg1 = NULL; cp->conn_arg2 = NULL; cp->conn_arg3 = NULL; cp->conn_arg4 = NULL; cp->conn_res = NULL; if (strcmp(method, MHD_HTTP_METHOD_POST) == 0) { cp->conn_pp = MHD_create_post_processor(conn, 1024, web_config_post, (void *)cp); // add by zp fprintf(stderr,"cp->conn_pp is %x\n",cp->conn_pp); if (cp->conn_pp == NULL) { free(cp); return MHD_NO; } cp->conn_type = CON_POST; } else if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) { cp->conn_type = CON_GET; } else { free(cp); return MHD_NO; } *ptr = (void *)cp; return MHD_YES; } if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) { // add by zp fprintf(stderr,"----------Get url:%s\n",url); if (strcmp(url, "/") == 0) ret = web_send_file(conn, "templates/advertisement.html", MHD_HTTP_OK, false); else if(strcmp(url, "/index") == 0) ret = web_send_file(conn, "templates/index.html", MHD_HTTP_OK, false); else if(strcmp(url, "/index.js") == 0) ret = web_send_file(conn, "templates/index.js", MHD_HTTP_OK, false); else if(strcmp(url, "/moive/big_buck_bunny") == 0) ret = web_send_file(conn, "moive/big_buck_bunny.ogv", MHD_HTTP_OK, false); else if(strcmp(url, "/poll") == 0){ ret = SendPollResponse(conn); //char *page = (char *)malloc(256); //sprintf(page,"<html><head><title>poll data</title></head><body>receive data:%d</body></html>\n",mydata->get_data()); //ret = web_send_data(conn,page,MHD_HTTP_OK,true,false,NULL); } else if(strcmp(url, "/css/uikit.min.css") == 0) ret = web_send_file(conn, "css/uikit.min.css", MHD_HTTP_OK, false); else if(strcmp(url, "/css/progress.min.css") == 0) ret = web_send_file(conn, "css/progress.min.css", MHD_HTTP_OK, false); else if(strcmp(url, "/js/jquery.js") == 0) ret = web_send_file(conn, "js/jquery.js", MHD_HTTP_OK, false); else if(strcmp(url, "/js/uikit.min.js") == 0) ret = web_send_file(conn, "js/uikit.min.js", MHD_HTTP_OK, false); else ret = web_send_data(conn, UNKNOWN, MHD_HTTP_NOT_FOUND, false, false, NULL); // no free, no copy return ret; } else if (strcmp(method, MHD_HTTP_METHOD_POST) == 0) { // add by zp fprintf(stderr,"----------Post url:%s \n",url); cp = (conninfo_t *)*ptr; if ( 0 == strcmp(url, "/index") ) { if (*up_data_size != 0) { MHD_post_process(cp->conn_pp, up_data, *up_data_size); *up_data_size = 0; return MHD_YES; } else ret = web_send_file(conn, "templates/index.html", MHD_HTTP_OK, false); } else if( 0 == strcmp(url,"/startapp") ){ printf("up_data_size:%d\n",*up_data_size); if (*up_data_size != 0) { // add printf("before MHD_post_process\n"); MHD_post_process(cp->conn_pp, up_data, *up_data_size); printf("after MHD_post_process\n"); *up_data_size = 0; mydata->set_data((char *)cp->conn_arg1); //printf("func:%s,line:%s,startdata:%d\n",__func__,__LINE__,cp->conn_arg1); return MHD_YES; } else ret = web_send_data(conn, EMPTY, MHD_HTTP_OK, false, false, NULL); // no free, no copy } else ret = web_send_data(conn, UNKNOWN, MHD_HTTP_NOT_FOUND, false, false, NULL); // no free, no copy return ret; } else return MHD_NO; }
int answer_to_connection( 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) { DAEMON_STATE dstate = (DAEMON_STATE)cls; REQUEST_STATE rstate = (REQUEST_STATE)*con_cls; if (rstate == NULL && added_client_overloads(dstate)) { return service_unavailable(connection); } else if (SMATCH(url, "/form.html")) { if (SMATCH(method, MHD_HTTP_METHOD_OPTIONS)) { return method_options( connection, COMMA_SEPARATED_STRING_LITERALS( MHD_HTTP_METHOD_POST, MHD_HTTP_METHOD_OPTIONS)); } else if (!SMATCH(method, MHD_HTTP_METHOD_POST)) { return bad_method( connection, COMMA_SEPARATED_STRING_LITERALS( MHD_HTTP_METHOD_POST, MHD_HTTP_METHOD_OPTIONS)); } else if (rstate == NULL && added_upload_client_overloads( dstate, TRUE)) { return service_unavailable(connection); } else if (rstate == NULL) { rstate = new_REQUEST_STATE( connection, method, &form_data_iterator); if (rstate == NULL) { return MHD_NO; } *con_cls = (void*)rstate; if (rstate->was_error) { return server_error(connection); } else { return MHD_YES; } } else if (*upload_data_size != 0) { MHD_post_process( rstate->processor, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } else if (rstate->was_filename_issue) { return forbidden( connection, "The server is unable to use the " "given filename. Please try a " "different file name."); } else if (rstate->was_error) { return server_error(connection); } else { return gen_result(connection); } } else if (SMATCH_ANY(url, "/index.html", "/index.htm", "/")) { if (SMATCH(method, MHD_HTTP_METHOD_OPTIONS)) { return method_options( connection, COMMA_SEPARATED_STRING_LITERALS( MHD_HTTP_METHOD_GET, MHD_HTTP_METHOD_HEAD, MHD_HTTP_METHOD_OPTIONS)); } else if (!SMATCH_ANY( method, MHD_HTTP_METHOD_HEAD, MHD_HTTP_METHOD_GET)) { return bad_method( connection, COMMA_SEPARATED_STRING_LITERALS( MHD_HTTP_METHOD_GET, MHD_HTTP_METHOD_HEAD, MHD_HTTP_METHOD_OPTIONS)); } else if (rstate == NULL) { rstate = new_REQUEST_STATE(connection, method, NULL); if (rstate == NULL) { return MHD_NO; } *con_cls = (void*)rstate; if (rstate->was_error) { return server_error(connection); } else { return MHD_YES; } } else { return gen_form(connection, "/form.html", dstate); } } else if (SMATCH(method, MHD_HTTP_METHOD_OPTIONS) && SMATCH(url, "*")) { return method_options( connection, COMMA_SEPARATED_STRING_LITERALS( MHD_HTTP_METHOD_OPTIONS, MHD_HTTP_METHOD_GET, MHD_HTTP_METHOD_HEAD, MHD_HTTP_METHOD_POST)); } else { return not_found(connection, "/", "the front page"); } }
int HTTPServer::answer_to_connection (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) { Logging::getInstance()->Log(Logging::INFO, "answering a connection: %s , %s, %s", url, method, upload_data); if (NULL == *con_cls) { struct connection_info_struct *con_info; con_info = (struct connection_info_struct *) malloc (sizeof (struct connection_info_struct)); if (NULL == con_info) return MHD_NO; con_info->answerstring = NULL; if (0 == strcmp (method, "POST")) { con_info->postprocessor = MHD_create_post_processor (connection, POSTBUFFERSIZE, iterate_post, (void *) con_info); if (NULL == con_info->postprocessor) { free (con_info); return MHD_NO; } con_info->connectiontype = POST; } else con_info->connectiontype = GET; *con_cls = (void *) con_info; return MHD_YES; } if (0 == strcmp (method, "GET")) { return send_page (connection, askpage); } if (0 == strcmp (method, "POST")) { struct connection_info_struct *con_info = (struct connection_info_struct *) *con_cls; if (*upload_data_size != 0) { Logging::getInstance()->Log(Logging::INFO, "Just received a data stream with content:\n%s\n", upload_data); std::string rxed_string(upload_data); JsonObject rxed_json; if(JsonObject::ParseFromString(rxed_string, rxed_json)){ unsigned long curr_time = current_date_time_msec(); long delay_time = -1; if(rxed_json.hasValue("tx_time")){ unsigned long tx_time = rxed_json.GetUInt("tx_time"); delay_time = (long) curr_time - (long) tx_time; } rxed_json.PutUInt("rx_time",current_date_time_msec()); rxed_json.PutInt("delay_time",delay_time); Logging::getInstance()->Log(Logging::INFO, "Just received a json message with content:\n%s\n", rxed_json.ToString().c_str()); //Add to Message Queue GetMessageQueue()->pushToEnd(rxed_json); }else{ //Data Stream is not JSON formatted } MHD_post_process (con_info->postprocessor, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } else if (NULL != con_info->answerstring) return send_page (connection, con_info->answerstring); } return send_page (connection, errorpage); }
FUNCTION PRIVATE DEFINITION static int answer_to_connection ( 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 ) { #ifdef DEBUG std::printf("%s %s %s\n", version, method, url); #endif Str_t smethod(method); if (*con_cls == NULL) { Connection_info_struct_t* con_info = new (VAR2STR(Connection_info_struct_t)) Connection_info_struct_t; if (con_info == NULL) return MHD_NO; con_info->answerstring.clear(); if (smethod.compare(txPOST) == 0) { con_info->postprocessor = MHD_create_post_processor(connection, POST_BUFFER_SIZE, iterate_post, (void *) con_info); if (con_info->postprocessor == NULL) { #ifdef DEBUG std::printf("[ERROR-LOG][deploy::answer_to_connection] POST Request not datas to process.\n"); #endif delete con_info; return MHD_NO; } con_info->connectiontype = POST; } else if (smethod.compare(txGET) == 0) { con_info->connectiontype = GET; } *con_cls = (void *) con_info; return MHD_YES; } if (smethod.compare(txGET) == 0) { Str_t page, mimetype; page_dispatcher(Str_t(url), page, mimetype); return send_page (connection, page, mimetype); } if (smethod.compare(txPOST) == 0) { Connection_info_struct_t* con_info = reinterpret_cast<Connection_info_struct_t*>(*con_cls); if (*upload_data_size != 0) { MHD_post_process (con_info->postprocessor, upload_data, *upload_data_size); *upload_data_size = 0; return MHD_YES; } else if (!con_info->post_key_value.empty()) { } } Str_t page, mimetype; deployapp::page_dispatcher("", page, mimetype); return send_page (connection, page, mimetype); }