From d232bc07f41d70402a4bc708189f61e3827d9ef4 Mon Sep 17 00:00:00 2001 From: ithewei Date: Tue, 17 Mar 2026 17:18:06 +0800 Subject: [PATCH 1/2] feat: add HTTP_STATUS_CLOSE to support (#816) --- examples/http_server_test.cpp | 6 ++++++ http/server/HttpHandler.cpp | 20 +++++++++++++++++--- http/server/HttpService.h | 6 ++++-- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/examples/http_server_test.cpp b/examples/http_server_test.cpp index 2b01c0011..0adb3aee4 100644 --- a/examples/http_server_test.cpp +++ b/examples/http_server_test.cpp @@ -97,6 +97,12 @@ int main(int argc, char** argv) { writer->End(); }); + // curl -v http://ip:port/close + // Test HTTP_STATUS_CLOSE: closes connection without sending any response + router.GET("/close", [](HttpRequest* req, HttpResponse* resp) { + return HTTP_STATUS_CLOSE; + }); + // middleware router.AllowCORS(); router.Use([](HttpRequest* req, HttpResponse* resp) { diff --git a/http/server/HttpHandler.cpp b/http/server/HttpHandler.cpp index 29aa363c4..9c686bf66 100644 --- a/http/server/HttpHandler.cpp +++ b/http/server/HttpHandler.cpp @@ -254,6 +254,10 @@ void HttpHandler::onHeadersComplete() { handleRequestHeaders(); if (service->headerHandler) { const int status_code = customHttpHandler(service->headerHandler); + if (status_code == HTTP_STATUS_CLOSE) { + state = WANT_CLOSE; + return; + } if (status_code != HTTP_STATUS_OK && status_code != HTTP_STATUS_NEXT) { SetError(ERR_REQUEST, static_cast(status_code)); return; @@ -338,6 +342,10 @@ void HttpHandler::onMessageComplete() { } } else { status_code = HandleHttpRequest(); + if (status_code == HTTP_STATUS_CLOSE) { + state = WANT_CLOSE; + return; + } if (status_code != HTTP_STATUS_NEXT) { SendHttpResponse(); } @@ -478,7 +486,7 @@ int HttpHandler::HandleHttpRequest() { pResp->status_code = (http_status)status_code; if (pResp->status_code >= 400 && pResp->body.size() == 0 && pReq->method != HTTP_HEAD) { if (service->errorHandler) { - customHttpHandler(service->errorHandler); + status_code = customHttpHandler(service->errorHandler); } else { defaultErrorHandler(); } @@ -492,7 +500,13 @@ int HttpHandler::HandleHttpRequest() { pResp->headers["Etag"] = fc->etag; } if (service->postprocessor) { - customHttpHandler(service->postprocessor); + status_code = customHttpHandler(service->postprocessor); + } + + // Handle HTTP_STATUS_CLOSE: close connection without response + if (status_code == HTTP_STATUS_CLOSE) { + state = WANT_CLOSE; + return HTTP_STATUS_CLOSE; } if (writer && writer->state != hv::HttpResponseWriter::SEND_BEGIN) { @@ -760,7 +774,7 @@ int HttpHandler::GetSendData(char** data, size_t* len) { if (parser->IsComplete()) state = WANT_SEND; else return 0; case HANDLE_END: - state = WANT_SEND; + state = WANT_SEND; case WANT_SEND: state = SEND_HEADER; case SEND_HEADER: diff --git a/http/server/HttpService.h b/http/server/HttpService.h index 8124354f2..16ef7a3c2 100644 --- a/http/server/HttpService.h +++ b/http/server/HttpService.h @@ -29,11 +29,13 @@ /* * @param[in] req: parsed structured http request * @param[out] resp: structured http response - * @return 0: handle next - * http_status_code: handle done + * @return HTTP_STATUS_NEXT: handle next + * HTTP_STATUS_CLOSE: close connection + * http_status_code: handle done */ #define HTTP_STATUS_NEXT 0 #define HTTP_STATUS_UNFINISHED 0 +#define HTTP_STATUS_CLOSE -100 // NOTE: http_sync_handler run on IO thread typedef std::function http_sync_handler; // NOTE: http_async_handler run on hv::async threadpool From af025695ccf4bfb4fbde0ffb7d7132e9ca93f785 Mon Sep 17 00:00:00 2001 From: ithewei Date: Tue, 17 Mar 2026 18:22:22 +0800 Subject: [PATCH 2/2] fix: handle HTTP_STATUS_CLOSE before and after postprocessor --- http/server/HttpHandler.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/http/server/HttpHandler.cpp b/http/server/HttpHandler.cpp index 9c686bf66..005967328 100644 --- a/http/server/HttpHandler.cpp +++ b/http/server/HttpHandler.cpp @@ -492,6 +492,11 @@ int HttpHandler::HandleHttpRequest() { } } } + // Handle HTTP_STATUS_CLOSE: close connection without response + if (status_code == HTTP_STATUS_CLOSE) { + state = WANT_CLOSE; + return HTTP_STATUS_CLOSE; + } if (fc) { pResp->content = fc->filebuf.base; pResp->content_length = fc->filebuf.len; @@ -501,12 +506,10 @@ int HttpHandler::HandleHttpRequest() { } if (service->postprocessor) { status_code = customHttpHandler(service->postprocessor); - } - - // Handle HTTP_STATUS_CLOSE: close connection without response - if (status_code == HTTP_STATUS_CLOSE) { - state = WANT_CLOSE; - return HTTP_STATUS_CLOSE; + if (status_code == HTTP_STATUS_CLOSE) { + state = WANT_CLOSE; + return HTTP_STATUS_CLOSE; + } } if (writer && writer->state != hv::HttpResponseWriter::SEND_BEGIN) {