From 1ad2e50829addb00501973f8e0a4b5586fe7809c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:43:00 +0000 Subject: [PATCH 1/3] Initial plan From b8f13880f8cbb9911504d3b282a8f38e02643cec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:52:10 +0000 Subject: [PATCH 2/3] feat: add auto port assignment when setPort(0) is called --- config.mk | 20 +++----------------- docs/cn/HttpServer.md | 6 +++--- examples/httpd/httpd.cpp | 2 +- http/server/HttpServer.cpp | 21 +++++++++++++++++++-- http/server/HttpServer.h | 8 +++++--- 5 files changed, 31 insertions(+), 26 deletions(-) diff --git a/config.mk b/config.mk index ad7852caa..a6ed94508 100644 --- a/config.mk +++ b/config.mk @@ -1,37 +1,23 @@ + PREFIX=/usr/local INSTALL_INCDIR=$(PREFIX)/include/hv INSTALL_LIBDIR=$(PREFIX)/lib - BUILD_SHARED=yes BUILD_STATIC=yes - -# modules -# include icmp dns ftp smtp WITH_PROTOCOL=no - WITH_EVPP=yes WITH_HTTP=yes WITH_HTTP_SERVER=yes WITH_HTTP_CLIENT=yes WITH_MQTT=no - -# features -# base/hsocket.h: Unix Domain Socket ENABLE_UDS=no -# base/RAII.cpp: Windows MiniDumpWriteDump ENABLE_WINDUMP=no -# http/http_content.h: KeyValue,QueryParams,MultiPart USE_MULTIMAP=no - -# dependencies -# for http/client WITH_CURL=no -# for http2 WITH_NGHTTP2=no -# for SSL/TLS WITH_OPENSSL=no WITH_GNUTLS=no WITH_MBEDTLS=no - -# rudp WITH_KCP=no +WITH_IO_URING=no +CONFIG_DATE=20260710 \ No newline at end of file diff --git a/docs/cn/HttpServer.md b/docs/cn/HttpServer.md index 22d88672b..69a4f225c 100644 --- a/docs/cn/HttpServer.md +++ b/docs/cn/HttpServer.md @@ -10,8 +10,8 @@ class HttpServer { // 设置监听主机 void setHost(const char* host = "0.0.0.0"); - // 设置监听端口 - void setPort(int port = 0, int ssl_port = 0); + // 设置监听端口,port=0 表示自动分配空闲端口 + void setPort(int port = 0, int ssl_port = -1); // 设置监听文件描述符 void setListenFD(int fd = -1, int ssl_fd = -1); @@ -34,7 +34,7 @@ class HttpServer { // 占用当前线程运行 int run(bool wait = true); - // 不占用当前线程运行 + // 不占用当前线程运行,返回实际监听的HTTP端口号(port=0时为OS分配的端口) int start(); // 停止服务 diff --git a/examples/httpd/httpd.cpp b/examples/httpd/httpd.cpp index 32fd54096..0e5248ba4 100644 --- a/examples/httpd/httpd.cpp +++ b/examples/httpd/httpd.cpp @@ -129,7 +129,7 @@ int parse_confile(const char* confile) { if (HV_WITH_SSL) { g_http_server.https_port = ini.Get("https_port"); } - if (g_http_server.port == 0 && g_http_server.https_port == 0) { + if (g_http_server.port < 0 && g_http_server.https_port < 0) { printf("Please config listen port!\n"); exit(-10); } diff --git a/http/server/HttpServer.cpp b/http/server/HttpServer.cpp index aa296fe8b..2c290dd9f 100644 --- a/http/server/HttpServer.cpp +++ b/http/server/HttpServer.cpp @@ -4,6 +4,7 @@ #include "herr.h" #include "hlog.h" #include "htime.h" +#include "hsocket.h" #include "EventLoop.h" using namespace hv; @@ -178,15 +179,31 @@ static void WINAPI loop_thread_stdcall(void* userdata) { */ int http_server_run(http_server_t* server, int wait) { // http_port - if (server->port > 0) { + if (server->port >= 0) { server->listenfd[0] = Listen(server->port, server->host); if (server->listenfd[0] < 0) return server->listenfd[0]; + if (server->port == 0) { + // port=0: OS auto-assigned a free port, retrieve the actual port + sockaddr_u localaddr; + socklen_t addrlen = sizeof(localaddr); + if (getsockname(server->listenfd[0], &localaddr.sa, &addrlen) == 0) { + server->port = sockaddr_port(&localaddr); + } + } hlogi("http server listening on %s:%d", server->host, server->port); } // https_port - if (server->https_port > 0 && HV_WITH_SSL) { + if (server->https_port >= 0 && HV_WITH_SSL) { server->listenfd[1] = Listen(server->https_port, server->host); if (server->listenfd[1] < 0) return server->listenfd[1]; + if (server->https_port == 0) { + // https_port=0: OS auto-assigned a free port, retrieve the actual port + sockaddr_u localaddr; + socklen_t addrlen = sizeof(localaddr); + if (getsockname(server->listenfd[1], &localaddr.sa, &addrlen) == 0) { + server->https_port = sockaddr_port(&localaddr); + } + } hlogi("https server listening on %s:%d", server->host, server->https_port); } // SSL_CTX diff --git a/http/server/HttpServer.h b/http/server/HttpServer.h index 79b3772da..1d99823a3 100644 --- a/http/server/HttpServer.h +++ b/http/server/HttpServer.h @@ -40,7 +40,7 @@ typedef struct http_server_s { // https_port = DEFAULT_HTTPS_PORT; // port = 8080; // https_port = 8443; - port = https_port = 0; + port = https_port = -1; http_version = 1; worker_processes = 0; worker_threads = 0; @@ -102,7 +102,7 @@ class HV_EXPORT HttpServer : public http_server_t { if (host) strcpy(this->host, host); } - void setPort(int port = 0, int ssl_port = 0) { + void setPort(int port = 0, int ssl_port = -1) { if (port >= 0) this->port = port; if (ssl_port >= 0) this->https_port = ssl_port; } @@ -150,7 +150,9 @@ class HV_EXPORT HttpServer : public http_server_t { } int start(const char* ip_port = NULL) { - return run(ip_port, false); + int ret = run(ip_port, false); + if (ret != 0) return ret; + return this->port; } int stop() { From 3235815ab6b2396e2ad7c22df87448331564e1e1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:56:07 +0000 Subject: [PATCH 3/3] fix: add getsockname error logging and improve start() docs --- http/server/HttpServer.cpp | 4 ++++ http/server/HttpServer.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/http/server/HttpServer.cpp b/http/server/HttpServer.cpp index 2c290dd9f..34648f363 100644 --- a/http/server/HttpServer.cpp +++ b/http/server/HttpServer.cpp @@ -188,6 +188,8 @@ int http_server_run(http_server_t* server, int wait) { socklen_t addrlen = sizeof(localaddr); if (getsockname(server->listenfd[0], &localaddr.sa, &addrlen) == 0) { server->port = sockaddr_port(&localaddr); + } else { + hloge("getsockname failed: %s", strerror(errno)); } } hlogi("http server listening on %s:%d", server->host, server->port); @@ -202,6 +204,8 @@ int http_server_run(http_server_t* server, int wait) { socklen_t addrlen = sizeof(localaddr); if (getsockname(server->listenfd[1], &localaddr.sa, &addrlen) == 0) { server->https_port = sockaddr_port(&localaddr); + } else { + hloge("getsockname failed: %s", strerror(errno)); } } hlogi("https server listening on %s:%d", server->host, server->https_port); diff --git a/http/server/HttpServer.h b/http/server/HttpServer.h index 1d99823a3..4733f3877 100644 --- a/http/server/HttpServer.h +++ b/http/server/HttpServer.h @@ -149,6 +149,10 @@ class HV_EXPORT HttpServer : public http_server_t { return http_server_run(this, wait); } + // start(":8080") + // start("0.0.0.0:8080") + // start("[::]:8080") + // @return actual http port on success (OS-assigned when port=0), negative on error int start(const char* ip_port = NULL) { int ret = run(ip_port, false); if (ret != 0) return ret;