diff --git a/src/connection.cpp b/src/connection.cpp index 1e2915e..4400298 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -206,6 +206,10 @@ uint32_t Connection::write_bytes() { part.size()}; iov_count++; } + + if (message.close_after_send) { + break; + } } if (iov_count == 0) diff --git a/src/http_handler.cpp b/src/http_handler.cpp index 181560d..954f98e 100644 --- a/src/http_handler.cpp +++ b/src/http_handler.cpp @@ -213,11 +213,12 @@ void HttpHandler::on_data_arrived(std::string_view data, Connection &conn) { if (!state) { // Create a temporary arena and add error response directly to avoid // sequence issues - Arena error_arena; auto json_response = R"({"error":"Internal server error"})"; auto http_response = - format_json_response(500, json_response, error_arena, 0, true); - conn.append_bytes(http_response, std::move(error_arena), true); + format_json_response(500, json_response, state->pending.arena, 0, true); + state->send_ordered_response(conn, state->get_next_sequence_id(), + http_response, std::move(state->pending.arena), + true); return; } @@ -247,7 +248,9 @@ void HttpHandler::on_data_arrived(std::string_view data, Connection &conn) { auto json_response = R"({"error":"Bad request"})"; auto http_response = format_json_response(400, json_response, state->pending.arena, 0, true); - conn.append_bytes(http_response, std::move(state->pending.arena), true); + state->send_ordered_response(conn, state->get_next_sequence_id(), + http_response, std::move(state->pending.arena), + true); return; } } @@ -326,7 +329,7 @@ void HttpHandler::handle_post_commit(Connection &conn, } // Basic validation passed - mark for 4-stage pipeline processing - const_cast(state).basic_validation_passed = true; + state.basic_validation_passed = true; // Response will be sent after 4-stage pipeline processing is complete } @@ -502,75 +505,6 @@ void HttpHandler::handle_not_found(Connection &conn, HttpRequestState &state) { state.connection_close); } -// HTTP utility methods -void HttpHandler::send_response(Connection &conn, int status_code, - std::string_view content_type, - std::string_view body, Arena response_arena, - int64_t http_request_id, - bool close_connection) { - - // Status text - std::string_view status_text; - switch (status_code) { - case 200: - status_text = "OK"; - break; - case 400: - status_text = "Bad Request"; - break; - case 404: - status_text = "Not Found"; - break; - case 500: - status_text = "Internal Server Error"; - break; - default: - status_text = "Unknown"; - break; - } - - const char *connection_header = close_connection ? "close" : "keep-alive"; - - auto response = response_arena.allocate_span(1); - - response[0] = - format(response_arena, - "HTTP/1.1 %d %.*s\r\n" - "Content-Type: %.*s\r\n" - "Content-Length: %zu\r\n" - "X-Response-ID: %ld\r\n" - "Connection: %s\r\n" - "\r\n%.*s", - status_code, static_cast(status_text.size()), - status_text.data(), static_cast(content_type.size()), - content_type.data(), body.size(), http_request_id, - connection_header, static_cast(body.size()), body.data()); - - conn.append_bytes(response, std::move(response_arena), close_connection); -} - -void HttpHandler::send_json_response(Connection &conn, int status_code, - std::string_view json, - Arena response_arena, - int64_t http_request_id, - bool close_connection) { - send_response(conn, status_code, "application/json", json, - std::move(response_arena), http_request_id, close_connection); -} - -void HttpHandler::send_error_response(Connection &conn, int status_code, - std::string_view message, - Arena response_arena, - int64_t http_request_id, - bool close_connection) { - std::string_view json = - format(response_arena, R"({"error":"%.*s"})", - static_cast(message.size()), message.data()); - - send_json_response(conn, status_code, json, std::move(response_arena), - http_request_id, close_connection); -} - void HttpConnectionState::send_ordered_response( Connection &conn, int64_t sequence_id, std::span http_response, Arena arena, diff --git a/src/http_handler.hpp b/src/http_handler.hpp index 2c4532f..8fae3b7 100644 --- a/src/http_handler.hpp +++ b/src/http_handler.hpp @@ -24,9 +24,7 @@ struct RouteMatch; struct HttpResponseContext { int64_t sequence_id; // For response ordering in pipelining int64_t http_request_id; // For X-Response-ID header - std::string_view content_type; - int status_code; - bool connection_close; // Whether to close connection after response + bool connection_close; // Whether to close connection after response }; /** @@ -153,18 +151,6 @@ private: void handle_not_found(Connection &conn, HttpRequestState &state); // HTTP utilities - static void send_response(Connection &conn, int status_code, - std::string_view content_type, - std::string_view body, Arena response_arena, - int64_t http_request_id, bool close_connection); - static void send_json_response(Connection &conn, int status_code, - std::string_view json, Arena response_arena, - int64_t http_request_id, - bool close_connection); - static void send_error_response(Connection &conn, int status_code, - std::string_view message, - Arena response_arena, int64_t http_request_id, - bool close_connection); // Helper functions for formatting responses without sending static std::span