void client_handler(client_t* client) { int ret; assert(client->fired_event != NULL); // Two stages // First, read HTTP request, interested in readable event if (client->stage == CS_READ_REQUEST) { if (client->fired_event->filter == EVFILT_READ) { ret = parse_http_request(client); if (ret) goto close; ret = generate_http_response(client); if (ret) goto close; client->stage = CS_WRITE_RESPONSE; } } // Then, write HTTP response, interested in writable event else if (client->stage == CS_WRITE_RESPONSE) { if (client->fired_event->filter == EVFILT_WRITE) { ret = write_http_response(client, client->fired_event->data); // When it went wrong or just finished correctly, // close the client if (ret) goto close; } } // Clear the event since it has been handled client->fired_event = NULL; return; close: close_client(client); }
static int mod_mapcache_request_handler(request_rec *r) { apr_table_t *params; mapcache_request *request = NULL; mapcache_context_apache_request *apache_ctx = NULL; mapcache_http_response *http_response = NULL; mapcache_context *global_ctx = NULL; if (!r->handler || strcmp(r->handler, "mapcache")) { return DECLINED; } if (r->method_number != M_GET) { return HTTP_METHOD_NOT_ALLOWED; } apache_ctx = apache_request_context_create(r); global_ctx = (mapcache_context*)apache_ctx; params = mapcache_http_parse_param_string(global_ctx, r->args); mapcache_service_dispatch_request(global_ctx,&request,r->path_info,params,global_ctx->config); if(GC_HAS_ERROR(global_ctx) || !request) { return write_http_response(apache_ctx, mapcache_core_respond_to_error(global_ctx)); } if(request->type == MAPCACHE_REQUEST_GET_CAPABILITIES) { mapcache_request_get_capabilities *req_caps = (mapcache_request_get_capabilities*)request; request_rec *original; char *url; if(r->main) original = r->main; else original = r; url = ap_construct_url(r->pool,original->uri,original); /* * remove the path_info from the end of the url (we want the url of the base of the service) * TODO: is there an apache api to access this ? */ if(*(original->path_info) && strcmp(original->path_info,"/")) { char *end = strstr(url,original->path_info); if(end) { /* make sure our url ends with a single '/' */ if(*end == '/') { char *slash = end; while((*(--slash))=='/') end--; end++; } *end = '\0'; } } http_response = mapcache_core_get_capabilities(global_ctx,request->service,req_caps, url,original->path_info,global_ctx->config); } else if( request->type == MAPCACHE_REQUEST_GET_TILE) { mapcache_request_get_tile *req_tile = (mapcache_request_get_tile*)request; http_response = mapcache_core_get_tile(global_ctx,req_tile); } else if( request->type == MAPCACHE_REQUEST_PROXY ) { mapcache_request_proxy *req_proxy = (mapcache_request_proxy*)request; http_response = mapcache_core_proxy_request(global_ctx, req_proxy); } else if( request->type == MAPCACHE_REQUEST_GET_MAP) { mapcache_request_get_map *req_map = (mapcache_request_get_map*)request; http_response = mapcache_core_get_map(global_ctx,req_map); } else if( request->type == MAPCACHE_REQUEST_GET_FEATUREINFO) { mapcache_request_get_feature_info *req_fi = (mapcache_request_get_feature_info*)request; http_response = mapcache_core_get_featureinfo(global_ctx,req_fi); } else { global_ctx->set_error(global_ctx,500,"###BUG### unknown request type"); } if(GC_HAS_ERROR(global_ctx)) { return write_http_response(apache_ctx, mapcache_core_respond_to_error(global_ctx)); } return write_http_response(apache_ctx,http_response); }
static int mod_mapcache_request_handler(request_rec *r) { apr_table_t *params; mapcache_request *request = NULL; mapcache_context_apache_request *apache_ctx = NULL; mapcache_http_response *http_response = NULL; mapcache_context *global_ctx = NULL; if (!r->handler || strcmp(r->handler, "mapcache")) { return DECLINED; } if (r->method_number != M_GET && r->method_number != M_POST) { return HTTP_METHOD_NOT_ALLOWED; } apache_ctx = apache_request_context_create(r); global_ctx = (mapcache_context*)apache_ctx; global_ctx->supports_redirects = 1; global_ctx->headers_in = r->headers_in; params = mapcache_http_parse_param_string(global_ctx, r->args); mapcache_service_dispatch_request(global_ctx,&request,r->path_info,params,global_ctx->config); if(GC_HAS_ERROR(global_ctx) || !request) { return write_http_response(apache_ctx, mapcache_core_respond_to_error(global_ctx)); } if(request->type == MAPCACHE_REQUEST_GET_CAPABILITIES) { mapcache_request_get_capabilities *req_caps = (mapcache_request_get_capabilities*)request; request_rec *original; char *url; if(r->main) original = r->main; else original = r; url = ap_construct_url(r->pool,original->uri,original); /* * remove the path_info from the end of the url (we want the url of the base of the service) * TODO: is there an apache api to access this ? */ if(*(original->path_info) && strcmp(original->path_info,"/")) { char *end = strstr(url,original->path_info); if(end) { /* make sure our url ends with a single '/' */ if(*end == '/') { char *slash = end; while((*(--slash))=='/') end--; end++; } *end = '\0'; } } http_response = mapcache_core_get_capabilities(global_ctx,request->service,req_caps, url,original->path_info,global_ctx->config); } else if( request->type == MAPCACHE_REQUEST_GET_TILE) { mapcache_request_get_tile *req_tile = (mapcache_request_get_tile*)request; http_response = mapcache_core_get_tile(global_ctx,req_tile); } else if( request->type == MAPCACHE_REQUEST_PROXY ) { const char *buf; mapcache_request_proxy *req_proxy = (mapcache_request_proxy*)request; if(r->method_number == M_POST) { read_post_body(apache_ctx, req_proxy); if(GC_HAS_ERROR(global_ctx)) { return write_http_response(apache_ctx, mapcache_core_respond_to_error(global_ctx)); } if(!req_proxy->headers) { req_proxy->headers = apr_table_make(global_ctx->pool, 2); } apr_table_set(req_proxy->headers, "Content-Type", r->content_type); if((buf = apr_table_get(r->headers_in,"X-Forwarded-For"))) { #if (AP_SERVER_MAJORVERSION_NUMBER == 2) && (AP_SERVER_MINORVERSION_NUMBER < 4) apr_table_set(req_proxy->headers, "X-Forwarded-For", apr_psprintf(global_ctx->pool,"%s, %s", buf, r->connection->remote_ip)); #else apr_table_set(req_proxy->headers, "X-Forwarded-For", apr_psprintf(global_ctx->pool,"%s, %s", buf, r->connection->client_ip)); #endif } else { #if (AP_SERVER_MAJORVERSION_NUMBER == 2) && (AP_SERVER_MINORVERSION_NUMBER < 4) apr_table_set(req_proxy->headers, "X-Forwarded-For", r->connection->remote_ip); #else apr_table_set(req_proxy->headers, "X-Forwarded-For", r->connection->client_ip); #endif } if ((buf = apr_table_get(r->headers_in, "Host"))) { const char *buf2; if((buf2 = apr_table_get(r->headers_in,"X-Forwarded-Host"))) { apr_table_set(req_proxy->headers, "X-Forwarded-Host", apr_psprintf(global_ctx->pool,"%s, %s",buf2,buf)); } else { apr_table_set(req_proxy->headers, "X-Forwarded-Host", buf); } } if ((buf = apr_table_get(r->headers_in, "X-Forwarded-Server"))) { apr_table_set(req_proxy->headers, "X-Forwarded-Server", apr_psprintf(global_ctx->pool, "%s, %s", buf, r->server->server_hostname)); } else { apr_table_set(req_proxy->headers, "X-Forwarded-Server", r->server->server_hostname); } } http_response = mapcache_core_proxy_request(global_ctx, req_proxy); } else if( request->type == MAPCACHE_REQUEST_GET_MAP) { mapcache_request_get_map *req_map = (mapcache_request_get_map*)request; http_response = mapcache_core_get_map(global_ctx,req_map); } else if( request->type == MAPCACHE_REQUEST_GET_FEATUREINFO) { mapcache_request_get_feature_info *req_fi = (mapcache_request_get_feature_info*)request; http_response = mapcache_core_get_featureinfo(global_ctx,req_fi); } else { global_ctx->set_error(global_ctx,500,"###BUG### unknown request type"); } if(GC_HAS_ERROR(global_ctx)) { return write_http_response(apache_ctx, mapcache_core_respond_to_error(global_ctx)); } return write_http_response(apache_ctx,http_response); }
void http_session::read_http_header() { auto self = shared_from_this(); // read until CRLFCRLF -> end of http header boost::asio::async_read_until(_socket, _buffer_request, HTTP_HEADER_END, [this, self](boost::system::error_code ec, std::size_t length) { if (!ec) { size_t content_length = 0; std::istream is(&_buffer_request); std::string line; std::getline(is, line); size_t sep1 = line.find(" "); size_t sep2 = line.find(" ", sep1 + 1); if (sep1 == std::string::npos || sep2 == std::string::npos) { LOG_ERROR << "invalid request " << line; _connection_close = true; write_http_response(HTTP_CODE_BAD_REQUEST); return; } _method = line.substr(0, sep1); _uri = line.substr(sep1 + 1, sep2 - sep1 - 1); _version = line.substr(sep2 + 1, line.size() - 1); // without \r at the end ! LOG_DEBUG << "request " << _method << " " << _uri << " " << _version; if (_version == HTTP_VERSION_10) { _connection_close = true; LOG_DEBUG << HTTP_VERSION_10 " -> connection close"; } while (std::getline(is, line) && line.size() > 1) // more than just \r in line { // iterate over all headers size_t pos_separator = line.find(": "); if (pos_separator == std::string::npos) { LOG_ERROR << "invalid header " << line; _connection_close = true; write_http_response(HTTP_CODE_BAD_REQUEST); return; } line[pos_separator] = 0; // put \0 in place of the : separator line[line.size() - 1] = 0; // put \0 in place of the \r at the end size_t pos_separator_params = line.find("; "); if (pos_separator_params != std::string::npos) { line[pos_separator_params] = 0; // put \0 in place of the ; separator } char* attr_name = &line[0]; char* attr_value = &line[pos_separator + 2]; if (strncmp(attr_name, HTTP_HEADER_CONTENT_LENGTH, sizeof(HTTP_HEADER_CONTENT_LENGTH)) == 0) { content_length = atol(attr_value); LOG_DEBUG << "content length " << content_length; } else if (strncmp(attr_name, HTTP_HEADER_CONNECTION, sizeof(HTTP_HEADER_CONNECTION)) == 0 && strncmp(attr_value, HTTP_HEADER_CONNECTION_CLOSE, sizeof(HTTP_HEADER_CONNECTION_CLOSE)) == 0) { _connection_close = true; LOG_DEBUG << "connection close header"; } else if (strncmp(attr_name, HTTP_HEADER_CONTENT_TYPE, sizeof(HTTP_HEADER_CONTENT_TYPE)) == 0) { LOG_DEBUG << "content type raw " << attr_value; if (strncmp(attr_value, HTTP_HEADER_CONTENT_TYPE_JSON, sizeof(HTTP_HEADER_CONTENT_TYPE_JSON)) == 0) { _content_type = CONTENT_TYPE_JSON; } else if (strncmp(attr_value, HTTP_HEADER_CONTENT_TYPE_TEXT, sizeof(HTTP_HEADER_CONTENT_TYPE_TEXT)) == 0) { _content_type = CONTENT_TYPE_TEXT; } else if (strncmp(attr_value, HTTP_HEADER_CONTENT_TYPE_XML, sizeof(HTTP_HEADER_CONTENT_TYPE_XML)) == 0) { _content_type = CONTENT_TYPE_XML; } else { _content_type = CONTENT_TYPE_OTHER; } LOG_DEBUG << "body content type " << _content_type; } } read_http_body(content_length); } else { LOG_ERROR << "error while reading http header " << ec; } }); }