/** * sends an HTTP response with content, but not content-length provided * * @param request the HTTP request to respond to * @param tcp_conn the TCP connection to send the response over */ void sendResponseWithContentButNoLength(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn) { // make sure it will get closed when finished tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE); // prepare the response headers HTTPResponse http_response(*request); http_response.setDoNotSendContentLength(); // send the response headers boost::system::error_code error_code; http_response.send(*tcp_conn, error_code); BOOST_REQUIRE(! error_code); // send the content buffer tcp_conn->write(boost::asio::buffer(m_big_buf, BIG_BUF_SIZE), error_code); BOOST_REQUIRE(! error_code); // finish (and close) the connection tcp_conn->finish(); }
void HTTPServer::handleRequest(HTTPRequestPtr& http_request, TCPConnectionPtr& tcp_conn) { if (! http_request->isValid()) { // the request is invalid or an error occured PION_LOG_INFO(m_logger, "Received an invalid HTTP request"); m_bad_request_handler(http_request, tcp_conn); return; } PION_LOG_DEBUG(m_logger, "Received a valid HTTP request"); // strip off trailing slash if the request has one std::string resource_requested(stripTrailingSlash(http_request->getResource())); // apply any redirection RedirectMap::const_iterator it = m_redirects.find(resource_requested); unsigned int num_redirects = 0; while (it != m_redirects.end()) { if (++num_redirects > MAX_REDIRECTS) { PION_LOG_ERROR(m_logger, "Maximum number of redirects (HTTPServer::MAX_REDIRECTS) exceeded for requested resource: " << http_request->getOriginalResource()); m_server_error_handler(http_request, tcp_conn, "Maximum number of redirects (HTTPServer::MAX_REDIRECTS) exceeded for requested resource"); return; } resource_requested = it->second; http_request->changeResource(resource_requested); it = m_redirects.find(resource_requested); } // if authentication activated, check current request if (m_auth) { // try to verify authentication if (! m_auth->handleRequest(http_request, tcp_conn)) { // the HTTP 401 message has already been sent by the authentication object PION_LOG_DEBUG(m_logger, "Authentication required for HTTP resource: " << resource_requested); if (http_request->getResource() != http_request->getOriginalResource()) { PION_LOG_DEBUG(m_logger, "Original resource requested was: " << http_request->getOriginalResource()); } return; } } // search for a handler matching the resource requested RequestHandler request_handler; if (findRequestHandler(resource_requested, request_handler)) { // try to handle the request try { request_handler(http_request, tcp_conn); PION_LOG_DEBUG(m_logger, "Found request handler for HTTP resource: " << resource_requested); if (http_request->getResource() != http_request->getOriginalResource()) { PION_LOG_DEBUG(m_logger, "Original resource requested was: " << http_request->getOriginalResource()); } } catch (HTTPResponseWriter::LostConnectionException& e) { // the connection was lost while or before sending the response PION_LOG_WARN(m_logger, "HTTP request handler: " << e.what()); tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE); // make sure it will get closed tcp_conn->finish(); } catch (std::bad_alloc&) { // propagate memory errors (FATAL) throw; } catch (std::exception& e) { // recover gracefully from other exceptions thrown request handlers PION_LOG_ERROR(m_logger, "HTTP request handler: " << e.what()); m_server_error_handler(http_request, tcp_conn, e.what()); } } else { // no web services found that could handle the request PION_LOG_INFO(m_logger, "No HTTP request handlers found for resource: " << resource_requested); if (http_request->getResource() != http_request->getOriginalResource()) { PION_LOG_DEBUG(m_logger, "Original resource requested was: " << http_request->getOriginalResource()); } m_not_found_handler(http_request, tcp_conn); } }