From 0ab35f8abd31d879b49dd7bcab017629974cee82 Mon Sep 17 00:00:00 2001 From: adam Date: Sun, 11 Oct 2026 09:51:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor(config):=20=E5=88=A0=E6=8E=89=2014=20?= =?UTF-8?q?=E4=B8=AA=E4=BB=8E=E6=9C=AA=E8=A2=AB=E8=AF=BB=E5=8F=96=E7=9A=84?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=AD=97=E6=AE=B5=E4=B8=8E=204=20=E4=B8=AA?= =?UTF-8?q?=E5=81=87=E6=97=8B=E9=92=AE=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2.10 roadmap d2(配置静默失效全线)。核实结论:`uvhttp_config_t` 原 26 个 字段中 14 个从不被任何执行路径读取 —— 它们被 set_defaults 填默认值、被 validate 校验范围、被 print 打印,然后被整个库忽略。 三个公共 API 报告成功、打 INFO 日志,对服务器行为零影响: - uvhttp_config_update_size_limits:写 max_body_size/max_header_size 后打 "Limits updated - Body: %zu -> %zu" - uvhttp_set_max_body_size(builder):写 max_body_size,返回 builder - uvhttp_set_timeout(builder):写 request_timeout/keepalive_timeout - uvhttp_config_update_read_buffer_size:写 read_buffer_size 这些字段的真实权威(逐个核实): - read_buffer_size → 编译期 UVHTTP_READ_BUFFER_SIZE(connection.c:647) - max_body_size → 编译期 UVHTTP_MAX_BODY_SIZE(request.c:308 等 4 处) - max_url_size → MAX_URL_LEN 2048(request.h:60) - max_header_size → 无任何实现 - max_requests_per_connection → 无任何实现(keep-alive 无上限) - request_timeout / keepalive_timeout → config->connection_timeout (connection.c:1551-1553,二者是同一裁决者的两个别名) - rate_limit_* 四项 → server->rate_limit_*(uvhttp_server_enable_rate_limit) - cache_default_max_entries / cache_default_ttl → 编译期常量 - lru_cache_batch_eviction_size → 编译期常量 取舍:删而非接。max_body_size 看似一条线就能接上,但 request body、 response body、compress 阈值三条路径各自独立,接一个留三个就是"两套权威" —— 正是本轮要治的病。需要可调时,把字段与读取它的代码一起加回来。 改动面: - uvhttp_config_t 26 → 12 字段,validate/print/set_defaults 同步收敛 - 4 个假旋钮 API 删除,头文件补"字段要么权威要么不存在"的规则说明 - 11 个测试用例组(validate 边界 / update API / 全字段用例)随 API 消失 - ConfigSetDefaultsValid 强化为钉住**存活** 12 个字段的默认值 —— 它是那份 清单的守门人:字段增减必须与"谁读它"同步 - 6 个示例改为只演示真实生效的字段(原先 helloworld/config_demo 把死字段 当卖点演示并打印) - docs/spec/config-api.md 重写:列出 14 字段的"真实权威归属表" + 存活 12 字段的真实默认值/范围(该表改动前就已失真:列了结构体里根本不存在的 max_headers / tcp_nodelay / tcp_keepalive) - 中英文档 10 处配置示例同步(FAQ / performance / introduction / TUTORIAL 参数表 / PERFORMANCE_TESTING_STANDARD) 顺带修一个既有 ASan 泄漏(与本次配置改动无关,但会卡住 ASan release 门禁): test_server_simple_handlers_coverage 的 GetHeader 用例在 #455 改成用 uvhttp_request_add_header 构造可查询 header 后,没有释放它堆分配的 headers_extra —— request 本身在栈上,不会有人替你调析构。main 上即复现。 验证:ctest 120/120(含 ASan 全量);cppcheck(CI 同参数)零告警; test-validity 门禁 PASS(零断言测试新增 0);examples 全量构建通过; 本 PR 触达的 src/include/test 文件 clang-format 18.1.8 全合规(release 门禁口径)。 --- docs/dev/PERFORMANCE_TESTING_STANDARD.md | 4 +- docs/guide/FAQ.md | 15 +- docs/guide/TUTORIAL.md | 27 +- docs/guide/introduction.md | 8 +- docs/guide/performance.md | 6 +- docs/spec/config-api.md | 54 +++- docs/zh/dev/PERFORMANCE_TESTING_STANDARD.md | 4 +- docs/zh/guide/FAQ.md | 13 +- docs/zh/guide/TUTORIAL.md | 23 +- docs/zh/guide/introduction.md | 8 +- docs/zh/guide/performance.md | 6 +- examples/01_basics/helloworld.c | 30 +- examples/01_basics/helloworld_complete.c | 30 +- examples/06_advanced/config_demo.c | 30 +- examples/06_advanced/simple_config.c | 22 +- .../08_e2e_tests/test_config_simple_e2e.c | 18 +- include/uvhttp_config.h | 62 +--- include/uvhttp_server.h | 14 +- src/uvhttp_config.c | 222 +------------ src/uvhttp_server.c | 17 - test/unit/test_config_enhanced_coverage.cpp | 130 ++++---- test/unit/test_config_full_coverage.cpp | 294 +++--------------- test/unit/test_server_api_coverage.cpp | 12 - test/unit/test_server_boost_coverage.cpp | 27 -- .../test_server_simple_handlers_coverage.cpp | 5 + 25 files changed, 326 insertions(+), 755 deletions(-) diff --git a/docs/dev/PERFORMANCE_TESTING_STANDARD.md b/docs/dev/PERFORMANCE_TESTING_STANDARD.md index 5a54d560..7951b64e 100644 --- a/docs/dev/PERFORMANCE_TESTING_STANDARD.md +++ b/docs/dev/PERFORMANCE_TESTING_STANDARD.md @@ -181,9 +181,9 @@ ls -lh build/dist/lib/libuvhttp.a ```c // Recommended configuration config.max_connections = 10000; -config.read_buffer_size = 16384; +config.connection_timeout = 60; config.write_buffer_size = 16384; -config.keepalive_timeout = 60; +config.backlog = 256; config.connection_timeout = 30; ``` diff --git a/docs/guide/FAQ.md b/docs/guide/FAQ.md index 10442021..39bc95ed 100644 --- a/docs/guide/FAQ.md +++ b/docs/guide/FAQ.md @@ -341,10 +341,13 @@ int on_message(uvhttp_ws_connection_t* ws_conn, const char* data, **Answer:** ```c -// Enable Keep-Alive by setting configuration +// Keep-Alive is on by default. The idle timeout is connection_timeout +// (seconds, valid 5-300); the old keepalive_timeout / request_timeout +// fields were removed in v2.10 because no code path ever read them. uvhttp_config_t* config = NULL; uvhttp_config_new(&config); -config->keepalive_timeout = 60; // 60 seconds +uvhttp_config_set_defaults(config); +config->connection_timeout = 60; // 60 seconds uvhttp_server_t* server = NULL; uvhttp_server_new(loop, &server); @@ -415,11 +418,13 @@ uvhttp_server_listen(server, "0.0.0.0", 8081); **Answer:** ```c -// Increase timeout values +// Increase the idle timeout (connection_timeout: 5-300 seconds). +// There is no separate request_timeout / keepalive_timeout — v2.10 removed +// both fields because the connection timer is driven by connection_timeout. uvhttp_config_t* config = NULL; uvhttp_config_new(&config); -config->keepalive_timeout = 300; // 5 minutes -config->request_timeout = 60; // 1 minute +uvhttp_config_set_defaults(config); +config->connection_timeout = 300; // 5 minutes uvhttp_server_t* server = NULL; uvhttp_server_new(loop, &server); diff --git a/docs/guide/TUTORIAL.md b/docs/guide/TUTORIAL.md index 2e59d124..820a41e5 100644 --- a/docs/guide/TUTORIAL.md +++ b/docs/guide/TUTORIAL.md @@ -2308,9 +2308,10 @@ void* memory_pool_alloc(memory_pool_t* pool) { #### 11.2 Connection Optimization ```c -// Enable Keep-Alive +// Keep-Alive is on by default; connection_timeout is the knob the +// connection timer reads (5-300 seconds). uvhttp_config_t* config = uvhttp_config_new(); -config->keepalive_timeout = 30; // 30 seconds +config->connection_timeout = 30; // 30 seconds server->config = config; // Connection reuse @@ -2523,13 +2524,25 @@ if (result != UVHTTP_OK) { ### B. Configuration Parameters +Every parameter below is read by the server at runtime. Limits that look +configurable but are not (body/header/URL size, read buffer size, request +timeout, requests per connection) are compile-time constants in +`uvhttp_constants.h` — v2.10 removed the config fields that never took effect. + | Parameter | Default | Description | |------|--------|------| -| max_connections | 1000 | Maximum number of connections | -| max_body_size | 1048576 | Maximum request body size (1MB) | -| read_buffer_size | 8192 | Read buffer size | -| keepalive_timeout | 30 | Keep-Alive timeout (seconds) | -| request_timeout | 60 | Request timeout (seconds) | +| max_connections | 2048 | Maximum number of connections | +| backlog | 256 | Listen queue length | +| connection_timeout | 60 | Idle connection timeout (seconds, 5-300) | +| max_file_size | 10MB | Maximum static file response size | +| trust_proxy_headers | 0 | Honour X-Forwarded-For for client IP | +| websocket_max_frame_size | 16MB | Maximum WebSocket frame size | +| websocket_max_message_size | 64MB | Maximum WebSocket message size | +| websocket_ping_interval | 30 | Ping interval (seconds) | +| websocket_ping_timeout | 10 | Ping timeout (seconds) | +| tcp_keepalive_timeout | 60 | TCP keepalive idle time (seconds) | +| sendfile_timeout_ms | 30000 | sendfile wait timeout | +| sendfile_max_retry | 2 | sendfile retry count | ### C. HTTP Status Codes diff --git a/docs/guide/introduction.md b/docs/guide/introduction.md index 7cf1613b..44537e67 100644 --- a/docs/guide/introduction.md +++ b/docs/guide/introduction.md @@ -155,9 +155,11 @@ uvhttp_tls_context_load_cert_chain(tls_ctx, "server.crt"); uvhttp_tls_context_load_private_key(tls_ctx, "server.key"); server->tls_ctx = tls_ctx; -// Example: Set reasonable resource limits -server->max_connections = 1000; -server->config->max_body_size = 10 * 1024 * 1024; // 10MB +// Example: Set reasonable resource limits (fields an execution path reads). +// Body/header/URL limits are compile-time constants (UVHTTP_MAX_BODY_SIZE etc.), +// not config entries — v2.10 removed the config fields that never took effect. +server->config->max_connections = 1000; +server->config->max_file_size = 10 * 1024 * 1024; // 10MB ``` --- diff --git a/docs/guide/performance.md b/docs/guide/performance.md index 8af895fb..cebd4a54 100644 --- a/docs/guide/performance.md +++ b/docs/guide/performance.md @@ -190,12 +190,14 @@ uvhttp_router_add_route(router, "/api/posts", posts_handler); ### 5. Configure Keep-Alive -Adjust keep-alive timeout based on your workload: +Adjust the idle timeout based on your workload. `connection_timeout` is the +field the connection timer actually reads (valid range 5-300 seconds): ```c uvhttp_config_t* config = NULL; uvhttp_config_new(&config); -config->keepalive_timeout = 60; // seconds +uvhttp_config_set_defaults(config); +config->connection_timeout = 60; // seconds ``` ## Performance Testing diff --git a/docs/spec/config-api.md b/docs/spec/config-api.md index 6571015a..8d1ca3ea 100644 --- a/docs/spec/config-api.md +++ b/docs/spec/config-api.md @@ -46,21 +46,45 @@ set at the server level and can be shared across multiple server instances. ## Configurable Options -| Field | Type | Default | Range | Description | -|-------|------|---------|-------|-------------| -| `max_connections` | size_t | 2048 | 1-65535 | Max concurrent connections | -| `keepalive_timeout` | int | 60 | 0-3600 | Keep-alive timeout (seconds) | -| `request_timeout` | int | 30 | 1-3600 | Request timeout (seconds) | -| `max_header_size` | size_t | 8192 | 256-65536 | Max header size (bytes) | -| `max_body_size` | size_t | 10485760 | 1024-1073741824 | Max body size (bytes) | -| `max_headers` | int | 64 | 8-256 | Max header count | -| `read_buffer_size` | size_t | 4096 | 256-65536 | Read buffer size (bytes) | -| `backlog` | int | 128 | 0-65535 | TCP listen backlog | -| `tcp_nodelay` | int | 1 | 0-1 | TCP_NODELAY | -| `tcp_keepalive` | int | 1 | 0-1 | TCP keepalive | -| `websocket_max_frame_size` | size_t | 65536 | 1024-1048576 | Max WebSocket frame (bytes) | -| `websocket_ping_interval` | int | 30 | 5-300 | Ping interval (seconds) | -| `websocket_ping_timeout` | int | 10 | 3-60 | Ping timeout (seconds) | +**Rule: a field is either authoritative or absent.** Every field below is read +by at least one execution path. v2.10 deleted the 14 fields that were set, +validated, printed — and then ignored by the whole library: + +| Removed field (v2.10) | What actually owned that limit | +|---|---| +| `read_buffer_size` | compile-time `UVHTTP_READ_BUFFER_SIZE` (per-connection buffer, `connection.c`) | +| `max_body_size` | compile-time `UVHTTP_MAX_BODY_SIZE` (`request.c` / `response.c` / `utils.c`) | +| `max_header_size` | nothing enforced it at all | +| `max_url_size` | `MAX_URL_LEN` (2048) in `request.h` | +| `max_requests_per_connection` | nothing enforced it at all | +| `request_timeout`, `keepalive_timeout` | `connection_timeout` (`connection.c` idle timer) — these were two extra names for the same knob | +| `rate_limit_window`, `rate_limit_max_requests`, `rate_limit_max_window_seconds`, `rate_limit_min_timeout_seconds` | `server->rate_limit_*`, set by `uvhttp_server_enable_rate_limit()` | +| `cache_default_max_entries`, `cache_default_ttl` | compile-time `UVHTTP_CACHE_DEFAULT_MAX_ENTRIES` / `_TTL` | +| `lru_cache_batch_eviction_size` | compile-time `UVHTTP_LRU_CACHE_*_BATCH_EVICTION_SIZE` | + +`uvhttp_set_timeout()`, `uvhttp_set_max_body_size()`, +`uvhttp_config_update_size_limits()` and +`uvhttp_config_update_read_buffer_size()` were removed with them: they wrote +those fields and reported success. If you need one of these limits to be +runtime-tunable, add the field back **together with the code that reads it** — +a config entry nobody reads is documentation, not control. + +### Surviving fields + +| Field | Type | Default | Valid range | Read by | +|-------|------|---------|-------------|---------| +| `max_connections` | int | 2048 | 1-65535 | `server.c` connection cap | +| `backlog` | int | 256 | validated only as `<= max_connections` (warn) | `server.c` listen | +| `connection_timeout` | int | 60 | 5-300 | `connection.c` idle timer | +| `max_file_size` | size_t | 10 MB | not range-checked | `static.c` file responses | +| `trust_proxy_headers` | int | 0 | 0 or 1 | `request.c` client-IP resolution | +| `websocket_max_frame_size` | int | 16 MB | 1 KB-256 MB | `websocket.c` | +| `websocket_max_message_size` | int | 64 MB | 1 KB-1 GB, `>= frame_size` | `websocket.c` | +| `websocket_ping_interval` | int | 30 | 1-3600 | `websocket.c` | +| `websocket_ping_timeout` | int | 10 | 1-3600 | `websocket.c` | +| `tcp_keepalive_timeout` | int | 60 | 1-7200 | `server.c` TCP keepalive | +| `sendfile_timeout_ms` | int | 30000 | 1000-300000 | `static.c` sendfile wait | +| `sendfile_max_retry` | int | 2 | `>= 0` | `static.c` sendfile retry | ## Behavior Rules diff --git a/docs/zh/dev/PERFORMANCE_TESTING_STANDARD.md b/docs/zh/dev/PERFORMANCE_TESTING_STANDARD.md index 5bc81773..95ff90ff 100644 --- a/docs/zh/dev/PERFORMANCE_TESTING_STANDARD.md +++ b/docs/zh/dev/PERFORMANCE_TESTING_STANDARD.md @@ -181,9 +181,9 @@ ls -lh build/dist/lib/libuvhttp.a ```c // 推荐配置 config.max_connections = 10000; -config.read_buffer_size = 16384; +config.backlog = 256; config.write_buffer_size = 16384; -config.keepalive_timeout = 60; +config.connection_timeout = 60; config.connection_timeout = 30; ``` diff --git a/docs/zh/guide/FAQ.md b/docs/zh/guide/FAQ.md index 356e038f..7b953a0e 100644 --- a/docs/zh/guide/FAQ.md +++ b/docs/zh/guide/FAQ.md @@ -318,9 +318,13 @@ int on_message(uvhttp_ws_connection_t* ws_conn, const char* data, ### Q21: 如何启用连接池? ```c +// Keep-Alive 默认开启。空闲超时由 connection_timeout 决定(秒,5-300); +// 原来的 keepalive_timeout / request_timeout 字段在 v2.10 被删除, +// 因为没有任何代码路径读取它们。 uvhttp_config_t* config = NULL; uvhttp_config_new(&config); -config->keepalive_timeout = 60; // 60 秒 +uvhttp_config_set_defaults(config); +config->connection_timeout = 60; // 60 秒 uvhttp_server_t* server = NULL; uvhttp_server_new(loop, &server); @@ -382,10 +386,13 @@ uvhttp_server_listen(server, "0.0.0.0", 8081); ### Q26: 连接超时错误 ```c +// 调大空闲超时(connection_timeout,合法范围 5-300 秒)。 +// 没有独立的 request_timeout / keepalive_timeout —— v2.10 删除了这两个字段, +// 连接计时器读的是 connection_timeout。 uvhttp_config_t* config = NULL; uvhttp_config_new(&config); -config->keepalive_timeout = 300; // 5 分钟 -config->request_timeout = 60; // 1 分钟 +uvhttp_config_set_defaults(config); +config->connection_timeout = 300; // 5 分钟 uvhttp_server_t* server = NULL; uvhttp_server_new(loop, &server); diff --git a/docs/zh/guide/TUTORIAL.md b/docs/zh/guide/TUTORIAL.md index 8d31a5d7..a0012f8b 100644 --- a/docs/zh/guide/TUTORIAL.md +++ b/docs/zh/guide/TUTORIAL.md @@ -2305,7 +2305,7 @@ void* memory_pool_alloc(memory_pool_t* pool) { ```c // 启用 Keep-Alive uvhttp_config_t* config = uvhttp_config_new(); -config->keepalive_timeout = 30; // 30秒 +config->connection_timeout = 30; // 30秒(Keep-Alive 默认开启) server->config = config; // 连接复用 @@ -2520,13 +2520,24 @@ if (result != UVHTTP_OK) { ### B. 配置参数 +以下参数都会被服务器在运行时读取。看起来可配置、实际不是的限额(请求体 / +请求头 / URL 大小、读缓冲大小、请求超时、每连接请求数)由 +`uvhttp_constants.h` 的编译期常量决定 —— v2.10 删除了那些从未生效的配置字段。 + | 参数 | 默认值 | 说明 | |------|--------|------| -| max_connections | 1000 | 最大连接数 | -| max_body_size | 1048576 | 最大请求体大小 (1MB) | -| read_buffer_size | 8192 | 读取缓冲区大小 | -| keepalive_timeout | 30 | Keep-Alive 超时 (秒) | -| request_timeout | 60 | 请求超时 (秒) | +| max_connections | 2048 | 最大连接数 | +| backlog | 256 | 监听队列长度 | +| connection_timeout | 60 | 空闲连接超时(秒,5-300) | +| max_file_size | 10MB | 静态文件响应大小上限 | +| trust_proxy_headers | 0 | 是否采信 X-Forwarded-For 作为客户端 IP | +| websocket_max_frame_size | 16MB | WebSocket 单帧上限 | +| websocket_max_message_size | 64MB | WebSocket 消息上限 | +| websocket_ping_interval | 30 | ping 间隔(秒) | +| websocket_ping_timeout | 10 | ping 超时(秒) | +| tcp_keepalive_timeout | 60 | TCP keepalive 空闲时间(秒) | +| sendfile_timeout_ms | 30000 | sendfile 等待超时 | +| sendfile_max_retry | 2 | sendfile 重试次数 | ### C. HTTP 状态码 diff --git a/docs/zh/guide/introduction.md b/docs/zh/guide/introduction.md index 0f0421b7..4d627ba5 100644 --- a/docs/zh/guide/introduction.md +++ b/docs/zh/guide/introduction.md @@ -149,9 +149,11 @@ uvhttp_tls_context_load_cert_chain(tls_ctx, "server.crt"); uvhttp_tls_context_load_private_key(tls_ctx, "server.key"); server->tls_ctx = tls_ctx; -// 设置资源限制 -server->max_connections = 1000; -server->config->max_body_size = 10 * 1024 * 1024; // 10MB +// 设置资源限制(只列执行路径真正读取的字段)。请求体 / 请求头 / URL 上限 +// 是编译期常量(UVHTTP_MAX_BODY_SIZE 等),不是配置项 —— v2.10 删除了那些 +// 从未生效的配置字段。 +server->config->max_connections = 1000; +server->config->max_file_size = 10 * 1024 * 1024; // 10MB ``` --- diff --git a/docs/zh/guide/performance.md b/docs/zh/guide/performance.md index 9c276893..4ce3719a 100644 --- a/docs/zh/guide/performance.md +++ b/docs/zh/guide/performance.md @@ -189,12 +189,14 @@ uvhttp_router_add_route(router, "/api/posts", posts_handler); ### 5. 配置 Keep-Alive -根据工作负载调整 keep-alive 超时: +根据工作负载调整空闲超时。连接计时器实际读取的是 `connection_timeout` +(合法范围 5-300 秒): ```c uvhttp_config_t* config = NULL; uvhttp_config_new(&config); -config->keepalive_timeout = 60; // 秒 +uvhttp_config_set_defaults(config); +config->connection_timeout = 60; // 秒 ``` ## 性能测试 diff --git a/examples/01_basics/helloworld.c b/examples/01_basics/helloworld.c index 46d2b273..e056405a 100644 --- a/examples/01_basics/helloworld.c +++ b/examples/01_basics/helloworld.c @@ -96,16 +96,16 @@ static int hello_handler(uvhttp_request_t* request, uvhttp_response_t* response) "Hello, World!\n\n" "=== Server Configuration ===\n" "Max connections: %d\n" - "Max requests per connection: %d\n" + "Backlog: %d\n" "Active connections: %zu\n" - "Max body size: %zuMB\n" - "Read buffer size: %zuKB\n" + "Connection timeout: %ds\n" + "Max body size (compile-time): %zuMB\n" "===========================\n", config->max_connections, - config->max_requests_per_connection, + config->backlog, active_connections, - config->max_body_size / (1024 * 1024), - (size_t)config->read_buffer_size / 1024 + config->connection_timeout, + (size_t)UVHTTP_MAX_BODY_SIZE / (1024 * 1024) ); uvhttp_response_set_status(response, 200); @@ -146,13 +146,15 @@ int main() { /* Apply defaults, then override a few values. */ uvhttp_config_set_defaults(config); + /* Every field below is read by the server: max_connections caps + * concurrent connections, backlog sizes the listen queue, and + * connection_timeout drives the per-connection idle timer + * (connection.c). Limits that look configurable but are not were + * removed in v2.10 - body/header/URL/read-buffer sizes are owned by + * the compile-time constants in uvhttp_constants.h. */ config->max_connections = 500; - config->max_requests_per_connection = 100; config->backlog = 128; - config->max_body_size = 1048576; /* 1MB */ - config->read_buffer_size = 8192; - config->keepalive_timeout = 30; - config->request_timeout = 60; + config->connection_timeout = 60; if (uvhttp_config_validate(config) != UVHTTP_OK) { fprintf(stderr, "Configuration validation failed\n"); @@ -162,10 +164,8 @@ int main() { printf("Configuration loaded successfully:\n"); printf(" Max connections: %d\n", config->max_connections); - printf(" Max requests per connection: %d\n", - config->max_requests_per_connection); - printf(" Max body size: %zu bytes\n", config->max_body_size); - printf(" Read buffer size: %d bytes\n", config->read_buffer_size); + printf(" Backlog: %d\n", config->backlog); + printf(" Connection timeout: %d s\n", config->connection_timeout); /* Get the default loop. */ uv_loop_t* loop = uv_default_loop(); diff --git a/examples/01_basics/helloworld_complete.c b/examples/01_basics/helloworld_complete.c index a132a09d..ed04d2c7 100644 --- a/examples/01_basics/helloworld_complete.c +++ b/examples/01_basics/helloworld_complete.c @@ -99,16 +99,16 @@ static int hello_handler(uvhttp_request_t* request, "Hello, World!\n\n" "=== Server Configuration ===\n" "Max connections: %d\n" - "Max requests per connection: %d\n" + "Backlog: %d\n" "Active connections: %zu\n" - "Max body size: %zuMB\n" - "Read buffer size: %zuKB\n" + "Connection timeout: %ds\n" + "Max body size (compile-time): %zuMB\n" "===========================\n", config->max_connections, - config->max_requests_per_connection, + config->backlog, active_connections, - config->max_body_size / (1024 * 1024), - (size_t)config->read_buffer_size / 1024 + config->connection_timeout, + (size_t)UVHTTP_MAX_BODY_SIZE / (1024 * 1024) ); uvhttp_response_set_status(response, 200); @@ -145,13 +145,15 @@ int main() { int cleanup_needed = 1; /* Set values directly (no defaults applied first). */ + /* Every field below is read by the server: max_connections caps + * concurrent connections, backlog sizes the listen queue, and + * connection_timeout drives the per-connection idle timer + * (connection.c). Limits that look configurable but are not were + * removed in v2.10 - body/header/URL/read-buffer sizes are owned by + * the compile-time constants in uvhttp_constants.h. */ config->max_connections = 500; - config->max_requests_per_connection = 100; config->backlog = 128; - config->max_body_size = 1048576; /* 1MB */ - config->read_buffer_size = 8192; - config->keepalive_timeout = 30; - config->request_timeout = 60; + config->connection_timeout = 60; if (uvhttp_config_validate(config) != UVHTTP_OK) { fprintf(stderr, "Configuration validation failed\n"); @@ -164,10 +166,8 @@ int main() { printf("Configuration loaded successfully:\n"); printf(" Max connections: %d\n", config->max_connections); - printf(" Max requests per connection: %d\n", - config->max_requests_per_connection); - printf(" Max body size: %zu bytes\n", config->max_body_size); - printf(" Read buffer size: %d bytes\n", config->read_buffer_size); + printf(" Backlog: %d\n", config->backlog); + printf(" Connection timeout: %d s\n", config->connection_timeout); /* Get the default loop. */ uv_loop_t* loop = uv_default_loop(); diff --git a/examples/06_advanced/config_demo.c b/examples/06_advanced/config_demo.c index 447373d0..8fc37150 100644 --- a/examples/06_advanced/config_demo.c +++ b/examples/06_advanced/config_demo.c @@ -79,20 +79,18 @@ int demo_handler(uvhttp_request_t* request, uvhttp_response_t* response) { "

当前配置信息

" "" "

请求时间: %s

" "", config->max_connections, - config->max_requests_per_connection, + config->backlog, g_app->server ? g_app->server->active_connections : (size_t)0, g_app->request_count, - config->max_body_size / (1024 * 1024), - config->read_buffer_size / 1024, + config->connection_timeout, ctime(&(time_t){time(NULL)}) ); @@ -184,12 +182,14 @@ int config_api_handler(uvhttp_request_t* request, uvhttp_response_t* response) { return uvhttp_response_send(response); } + /* 只报告真正生效的字段。v2.10 删除了 14 个"设置成功但无人读取"的 + * 配置字段(max_body_size / read_buffer_size / max_header_size 等)—— + * 它们的真实上限来自编译期常量,报告出来只会误导使用者。 */ cJSON_AddNumberToObject(json_obj, "max_connections", config->max_connections); - cJSON_AddNumberToObject(json_obj, "max_requests_per_connection", config->max_requests_per_connection); - cJSON_AddNumberToObject(json_obj, "max_body_size", (double)config->max_body_size); - cJSON_AddNumberToObject(json_obj, "max_header_size", (double)config->max_header_size); - cJSON_AddNumberToObject(json_obj, "read_buffer_size", config->read_buffer_size); cJSON_AddNumberToObject(json_obj, "backlog", config->backlog); + cJSON_AddNumberToObject(json_obj, "connection_timeout", config->connection_timeout); + cJSON_AddNumberToObject(json_obj, "max_body_size_compile_time", + (double)UVHTTP_MAX_BODY_SIZE); cJSON_AddNumberToObject(json_obj, "current_active_connections", g_app->server ? (double)g_app->server->active_connections : 0.0); cJSON_AddNumberToObject(json_obj, "total_requests_handled", g_app->request_count); @@ -258,11 +258,11 @@ void config_adjustment_timer(uv_timer_t* handle) { void print_config_info(const uvhttp_config_t* config) { printf("=== 服务器配置信息 ===\n"); printf("最大连接数: %d\n", config->max_connections); - printf(" 每连接最大请求数: %d\n", config->max_requests_per_connection); - printf("最大请求体大小: %zuMB\n", config->max_body_size / (1024 * 1024)); - printf("最大请求头大小: %zuKB\n", config->max_header_size / 1024); - printf("读取缓冲区大小: %dKB\n", config->read_buffer_size / 1024); printf("监听队列大小: %d\n", config->backlog); + printf("连接超时: %d秒\n", config->connection_timeout); + printf("最大文件响应大小: %zuMB\n", config->max_file_size / (1024 * 1024)); + printf("最大请求体大小(编译期常量): %zuMB\n", + (size_t)UVHTTP_MAX_BODY_SIZE / (1024 * 1024)); printf("当前分配器: %s\n", uvhttp_allocator_name()); printf("========================\n"); } @@ -286,7 +286,7 @@ uvhttp_config_t* load_config_demo() { // 2. 代码中直接覆盖某些配置 printf("代码中自定义配置...\n"); config->max_connections = 3000; // 演示用,实际中应该基于需求设置 - config->max_requests_per_connection = 200; + config->connection_timeout = 90; printf(" 代码设置最大连接数: %d\n", config->max_connections); // 5. 验证配置 diff --git a/examples/06_advanced/simple_config.c b/examples/06_advanced/simple_config.c index f0ee6e40..0159fd12 100644 --- a/examples/06_advanced/simple_config.c +++ b/examples/06_advanced/simple_config.c @@ -54,13 +54,13 @@ int simple_handler(uvhttp_request_t* request, uvhttp_response_t* response) { "UVHTTP 简单配置示例\n\n" "当前配置:\n" "- 最大连接数: %d\n" - "- 每连接最大请求数: %d\n" + "- 监听队列长度: %d\n" "- 当前活动连接数: %zu\n" - "- 最大请求体大小: %zuMB\n", + "- 连接超时: %d 秒\n", config->max_connections, - config->max_requests_per_connection, + config->backlog, server ? server->active_connections : 0, - config->max_body_size / (1024 * 1024) + config->connection_timeout ); uvhttp_response_set_status(response, 200); @@ -118,10 +118,12 @@ int main() { // 设置并发连接数限制 printf("设置配置参数...\n"); - config->max_connections = 1500; // 最大1500个并发连接 - config->max_requests_per_connection = 100; // 每个连接最多100个请求 - config->max_body_size = 2 * 1024 * 1024; // 2MB最大请求体 - config->read_buffer_size = 8192; // 8KB读取缓冲区 + // 只设置真正会被服务器读取的字段。请求体上限、读缓冲大小等在 v2.10 + // 被移出配置结构 —— 它们由 uvhttp_constants.h 的编译期常量决定, + // 放进配置里只会"设置成功但毫无作用"。 + config->max_connections = 1500; // 最大1500个并发连接 + config->backlog = 256; // 监听队列长度 + config->connection_timeout = 60; // 空闲连接超时(秒) // 验证配置 if (uvhttp_config_validate(config) != UVHTTP_OK) { @@ -163,8 +165,8 @@ int main() { // 启动服务器 printf("启动服务器 (端口 8080)...\n"); - printf("配置: 最大连接数=%d, 每连接最大请求数=%d\n", - config->max_connections, config->max_requests_per_connection); + printf("配置: 最大连接数=%d, 监听队列=%d, 连接超时=%d秒\n", + config->max_connections, config->backlog, config->connection_timeout); if (uvhttp_server_listen(g_app_context->server, "0.0.0.0", 8080) != UVHTTP_OK) { fprintf(stderr, "服务器启动失败\n"); diff --git a/examples/08_e2e_tests/test_config_simple_e2e.c b/examples/08_e2e_tests/test_config_simple_e2e.c index ec9983b4..88769cfb 100644 --- a/examples/08_e2e_tests/test_config_simple_e2e.c +++ b/examples/08_e2e_tests/test_config_simple_e2e.c @@ -37,22 +37,12 @@ static int config_get_handler(uvhttp_request_t* request, snprintf(response_body, sizeof(response_body), "Configuration:\n" "Max Connections: %d\n" - "Read Buffer Size: %d\n" "Backlog: %d\n" - "Keepalive Timeout: %d\n" - "Request Timeout: %d\n" - "Max Body Size: %zu\n" - "Max Header Size: %zu\n" - "Max URL Size: %zu\n" + "Connection Timeout: %d\n" "Max File Size: %zu", app->config->max_connections, - app->config->read_buffer_size, app->config->backlog, - app->config->keepalive_timeout, - app->config->request_timeout, - app->config->max_body_size, - app->config->max_header_size, - app->config->max_url_size, + app->config->connection_timeout, app->config->max_file_size); uvhttp_response_set_status(response, 200); @@ -151,8 +141,8 @@ int main(int argc, char** argv) { printf("Default configuration loaded\n"); printf(" Max Connections: %d\n", app.config->max_connections); - printf(" Request Timeout: %d\n", app.config->request_timeout); - printf(" Max Body Size: %zu\n", app.config->max_body_size); + printf(" Backlog: %d\n", app.config->backlog); + printf(" Connection Timeout: %d\n", app.config->connection_timeout); /* Create server */ uvhttp_error_t result = uvhttp_server_new(loop, &app.server); diff --git a/include/uvhttp_config.h b/include/uvhttp_config.h index 2a7c96a7..83bb6807 100644 --- a/include/uvhttp_config.h +++ b/include/uvhttp_config.h @@ -25,34 +25,17 @@ typedef struct uvhttp_context uvhttp_context_t; /* Configuration structure */ typedef struct { /* Server configuration */ - int max_connections; /* Maximum connections, default 1000, based on system - resource limits */ - int read_buffer_size; /* Read buffer size, default 8KB, balance memory and - performance */ + int max_connections; /* Maximum connections, default 1000, based on system + resource limits */ int backlog; /* Listen queue length, default 128, Linux kernel default */ - int keepalive_timeout; /* Keep-Alive timeout, default 30 seconds, balance - * connection reuse and resource release - */ - int request_timeout; /* Request timeout, default 30 seconds, based on common - web application requirements */ int connection_timeout; /* Connection timeout (seconds), default 60 seconds, prevent slow connection attacks */ /* Performance configuration */ - size_t max_body_size; /* Maximum request body size, default 10MB, prevent - DoS attacks */ - size_t max_header_size; /* Maximum request header size, default 8KB, - HTTP/1.1 recommended value */ - size_t max_url_size; /* Maximum URL length, default 2KB, browser limit */ size_t max_file_size; /* Maximum file size for file response, default 100MB, balance memory and bandwidth */ /* Security configuration */ - int max_requests_per_connection; /* Maximum requests per connection, default - * 100, prevent long connection abuse - */ - int rate_limit_window; /* Rate limiting time window, default 60 seconds, - balance accuracy and performance */ int trust_proxy_headers; /* Trust X-Forwarded-For/X-Real-IP when resolving * client IP. Default 0 (spoof-safe): always use * the TCP peer address. Enable only behind a @@ -76,30 +59,22 @@ typedef struct { performance and reliability */ int sendfile_max_retry; /* sendfile maximum retry count, default 3 times, empirical value */ - - /* Cache configuration */ - int cache_default_max_entries; /* Cache default maximum entries, default - * 1000, based on memory and performance - * balance - */ - int cache_default_ttl; /* Cache default TTL, default 3600 seconds (1 hour), - * common web cache strategy - */ - int lru_cache_batch_eviction_size; /* LRU cache batch eviction size, default - * 10, performance optimization - */ - - /* Rate limiting configuration */ - int rate_limit_max_requests; /* Rate limit max requests, default 100, - prevent abuse */ - int rate_limit_max_window_seconds; /* Rate limit window, default 60 - seconds, same as rate_limit_window */ - int rate_limit_min_timeout_seconds; /* Rate limit timeout when limit - * exceeded, Default 1 seconds, prevent - * request spam - */ } uvhttp_config_t; +/* Every field above is read by at least one execution path: these are the + * compile-time defaults' runtime overrides. v2.10 deleted the 14 fields whose + * values never reached the server (read_buffer_size, max_body_size, + * max_header_size, max_url_size, max_requests_per_connection, + * request_timeout, keepalive_timeout, the four rate_limit_* fields, + * cache_default_max_entries, cache_default_ttl, + * lru_cache_batch_eviction_size) - they were set, validated, printed, and then + * ignored by every code path. Behaviour for those limits is owned by the + * compile-time constants in uvhttp_constants.h (UVHTTP_MAX_BODY_SIZE, + * UVHTTP_READ_BUFFER_SIZE, MAX_URL_LEN, UVHTTP_CACHE_DEFAULT_*), or, for rate + * limiting, by uvhttp_server_enable_rate_limit() on the server itself. + * A field that is neither authoritative nor absent is noise: if you need one + * of these knobs, add it back together with the code that reads it. */ + /* Configuration management functions */ /** * @brief Create new configuration object @@ -120,11 +95,6 @@ void uvhttp_config_print(const uvhttp_config_t* config); /* Dynamic configuration adjustment */ int uvhttp_config_update_max_connections(uvhttp_context_t* context, int max_connections); -int uvhttp_config_update_read_buffer_size(uvhttp_context_t* context, - int buffer_size); -int uvhttp_config_update_size_limits(uvhttp_context_t* context, - size_t max_body_size, - size_t max_header_size); /* Get current configuration */ const uvhttp_config_t* uvhttp_config_get_current(uvhttp_context_t* context); diff --git a/include/uvhttp_server.h b/include/uvhttp_server.h index 233e2f66..323ed980 100644 --- a/include/uvhttp_server.h +++ b/include/uvhttp_server.h @@ -474,13 +474,17 @@ uvhttp_server_builder_t* uvhttp_any(uvhttp_server_builder_t* server, const char* path, uvhttp_request_handler_t handler); -/* Simplified configuration API */ +/* Simplified configuration API + * + * uvhttp_set_timeout() and uvhttp_set_max_body_size() were removed in v2.10: + * they wrote config->request_timeout / keepalive_timeout / max_body_size, and + * no execution path ever read those fields (the real limits are owned by the + * compile-time constants UVHTTP_CONNECTION_TIMEOUT_DEFAULT and + * UVHTTP_MAX_BODY_SIZE). Both returned the builder, so callers had no way to + * see that nothing changed. Use uvhttp_set_max_connections() for the one knob + * that is real. */ uvhttp_server_builder_t* uvhttp_set_max_connections( uvhttp_server_builder_t* server, int max_conn); -uvhttp_server_builder_t* uvhttp_set_timeout(uvhttp_server_builder_t* server, - int timeout); -uvhttp_server_builder_t* uvhttp_set_max_body_size( - uvhttp_server_builder_t* server, size_t size); /* Request accessors live in uvhttp_request.h: * uvhttp_request_get_header() (was also uvhttp_get_header) diff --git a/src/uvhttp_config.c b/src/uvhttp_config.c index 40f8463e..aa52c3f0 100644 --- a/src/uvhttp_config.c +++ b/src/uvhttp_config.c @@ -46,19 +46,11 @@ void uvhttp_config_set_defaults(uvhttp_config_t* config) { return; config->max_connections = UVHTTP_DEFAULT_MAX_CONNECTIONS; - config->read_buffer_size = UVHTTP_DEFAULT_READ_BUFFER_SIZE; config->backlog = UVHTTP_DEFAULT_BACKLOG; - config->keepalive_timeout = UVHTTP_DEFAULT_KEEPALIVE_TIMEOUT; - config->request_timeout = UVHTTP_DEFAULT_REQUEST_TIMEOUT; config->connection_timeout = UVHTTP_CONNECTION_TIMEOUT_DEFAULT; - config->max_body_size = UVHTTP_DEFAULT_MAX_BODY_SIZE; - config->max_header_size = UVHTTP_DEFAULT_MAX_HEADER_SIZE; - config->max_url_size = UVHTTP_DEFAULT_MAX_URL_SIZE; config->max_file_size = UVHTTP_DEFAULT_MAX_FILE_SIZE; - config->max_requests_per_connection = UVHTTP_DEFAULT_MAX_REQUESTS_PER_CONN; - config->rate_limit_window = UVHTTP_DEFAULT_RATE_LIMIT_WINDOW; config->trust_proxy_headers = 0; /* default: never trust proxy headers */ /* WebSocket config */ @@ -72,19 +64,6 @@ void uvhttp_config_set_defaults(uvhttp_config_t* config) { config->tcp_keepalive_timeout = UVHTTP_TCP_KEEPALIVE_TIMEOUT; config->sendfile_timeout_ms = UVHTTP_SENDFILE_TIMEOUT_MS; config->sendfile_max_retry = UVHTTP_SENDFILE_DEFAULT_MAX_RETRY; - - /* cacheconfig */ - config->cache_default_max_entries = UVHTTP_CACHE_DEFAULT_MAX_ENTRIES; - config->cache_default_ttl = UVHTTP_CACHE_DEFAULT_TTL; - config->lru_cache_batch_eviction_size = - UVHTTP_LRU_CACHE_BATCH_EVICTION_SIZE; - - /* limit stream config */ - config->rate_limit_max_requests = UVHTTP_RATE_LIMIT_MAX_REQUESTS; - config->rate_limit_max_window_seconds = - UVHTTP_RATE_LIMIT_MAX_WINDOW_SECONDS; - config->rate_limit_min_timeout_seconds = - UVHTTP_RATE_LIMIT_MIN_TIMEOUT_SECONDS; } /* Validate configuration */ @@ -99,10 +78,12 @@ int uvhttp_config_validate(const uvhttp_config_t* config) { * * UVHTTP_MIN_CONNECTIONS: Minimum connections, ensure basic server * functionality UVHTTP_MAX_CONNECTIONS_HARD: Hard limit, based on system - * file descriptor limit UVHTTP_MIN_BUFFER_SIZE: Minimum buffer, ensure - * basic HTTP processing capability UVHTTP_MAX_BUFFER_SIZE: Maximum buffer, - * balance memory usage and performance UVHTTP_MAX_BODY_SIZE_CONFIG: Maximum - * request body, prevent memory exhaustion attack + * file descriptor limit + * + * Only fields that an execution path actually reads are validated here; + * v2.10 removed the 14 fields whose values never reached the server (see + * the "fields are either authoritative or absent" rule in docs/spec/ + * config-api.md). * * Performance considerations: * - Each connection consumes about 4KB memory (buffer + struct) @@ -112,13 +93,8 @@ int uvhttp_config_validate(const uvhttp_config_t* config) { */ #define UVHTTP_MIN_CONNECTIONS 1 #define UVHTTP_MAX_CONNECTIONS_HARD 65535 /* Based on system limits */ -#define UVHTTP_MIN_BUFFER_SIZE 1024 -#define UVHTTP_MAX_BUFFER_SIZE (1024 * 1024) -#define UVHTTP_MIN_BODY_SIZE 1024 -#define UVHTTP_MAX_BODY_SIZE_CONFIG \ - (100 * 1024 * 1024) /* Avoid conflict with macros in header file */ - /* Core validation: connection count and buffer size */ + /* Core validation: connection count */ if (config->max_connections < UVHTTP_MIN_CONNECTIONS || config->max_connections > UVHTTP_MAX_CONNECTIONS_HARD) { UVHTTP_LOG_ERROR("max_connections=%d exceeds valid range [%d-%d]", @@ -127,22 +103,6 @@ int uvhttp_config_validate(const uvhttp_config_t* config) { return UVHTTP_ERROR_INVALID_PARAM; } - if (config->read_buffer_size < UVHTTP_MIN_BUFFER_SIZE || - config->read_buffer_size > UVHTTP_MAX_BUFFER_SIZE) { - UVHTTP_LOG_ERROR("read_buffer_size=%d exceeds valid range [%d-%d]", - config->read_buffer_size, UVHTTP_MIN_BUFFER_SIZE, - UVHTTP_MAX_BUFFER_SIZE); - return UVHTTP_ERROR_INVALID_PARAM; - } - - if (config->max_body_size < UVHTTP_MIN_BODY_SIZE || - config->max_body_size > UVHTTP_MAX_BODY_SIZE_CONFIG) { - UVHTTP_LOG_ERROR("max_body_size=%zu exceeds valid range [%zu-%zu]", - config->max_body_size, (size_t)UVHTTP_MIN_BODY_SIZE, - (size_t)UVHTTP_MAX_BODY_SIZE_CONFIG); - return UVHTTP_ERROR_INVALID_PARAM; - } - /* Validate new runtime configuration */ if (config->websocket_max_frame_size < UVHTTP_WEBSOCKET_CONFIG_MIN_FRAME_SIZE || @@ -225,100 +185,6 @@ int uvhttp_config_validate(const uvhttp_config_t* config) { return UVHTTP_ERROR_INVALID_PARAM; } - if (config->cache_default_max_entries < UVHTTP_CACHE_MIN_MAX_ENTRIES || - config->cache_default_max_entries > UVHTTP_CACHE_MAX_MAX_ENTRIES) { - - UVHTTP_LOG_ERROR( - "cache_default_max_entries=%d exceeds valid range [%d-%d]", - - config->cache_default_max_entries, UVHTTP_CACHE_MIN_MAX_ENTRIES, - - UVHTTP_CACHE_MAX_MAX_ENTRIES); - - return UVHTTP_ERROR_INVALID_PARAM; - } - - if (config->cache_default_ttl < UVHTTP_CACHE_MIN_TTL || - - config->cache_default_ttl > UVHTTP_CACHE_MAX_TTL) { - - UVHTTP_LOG_ERROR("cache_default_ttl=%d exceeds valid range [%d-%d]", - - config->cache_default_ttl, UVHTTP_CACHE_MIN_TTL, - - UVHTTP_CACHE_MAX_TTL); - - return UVHTTP_ERROR_INVALID_PARAM; - } - - if (config->lru_cache_batch_eviction_size < - UVHTTP_LRU_CACHE_MIN_BATCH_EVICTION_SIZE || - - config->lru_cache_batch_eviction_size > - UVHTTP_LRU_CACHE_MAX_BATCH_EVICTION_SIZE) { - - UVHTTP_LOG_ERROR( - "lru_cache_batch_eviction_size=%d exceeds valid range [%d-%d]", - - config->lru_cache_batch_eviction_size, - - UVHTTP_LRU_CACHE_MIN_BATCH_EVICTION_SIZE, - - UVHTTP_LRU_CACHE_MAX_BATCH_EVICTION_SIZE); - - return UVHTTP_ERROR_INVALID_PARAM; - } - - if (config->rate_limit_max_requests < UVHTTP_RATE_LIMIT_MIN_MAX_REQUESTS || - - config->rate_limit_max_requests > UVHTTP_RATE_LIMIT_MAX_MAX_REQUESTS) { - - UVHTTP_LOG_ERROR( - "rate_limit_max_requests=%d exceeds valid range [%d-%d]", - - config->rate_limit_max_requests, UVHTTP_RATE_LIMIT_MIN_MAX_REQUESTS, - - UVHTTP_RATE_LIMIT_MAX_MAX_REQUESTS); - - return UVHTTP_ERROR_INVALID_PARAM; - } - - if (config->rate_limit_max_window_seconds < - UVHTTP_RATE_LIMIT_MIN_WINDOW_SECONDS || - - config->rate_limit_max_window_seconds > - UVHTTP_RATE_LIMIT_MAX_WINDOW_SECONDS) { - - UVHTTP_LOG_ERROR( - "rate_limit_max_window_seconds=%d exceeds valid range [%d-%d]", - - config->rate_limit_max_window_seconds, - - UVHTTP_RATE_LIMIT_MIN_WINDOW_SECONDS, - - UVHTTP_RATE_LIMIT_MAX_WINDOW_SECONDS); - - return UVHTTP_ERROR_INVALID_PARAM; - } - - if (config->rate_limit_min_timeout_seconds < - UVHTTP_RATE_LIMIT_MIN_TIMEOUT_SECONDS || - - config->rate_limit_min_timeout_seconds > - UVHTTP_RATE_LIMIT_MAX_TIMEOUT_SECONDS) { - - UVHTTP_LOG_ERROR( - "rate_limit_min_timeout_seconds=%d exceeds valid range [%d-%d]", - - config->rate_limit_min_timeout_seconds, - - UVHTTP_RATE_LIMIT_MIN_TIMEOUT_SECONDS, - - UVHTTP_RATE_LIMIT_MAX_TIMEOUT_SECONDS); - - return UVHTTP_ERROR_INVALID_PARAM; - } - /* Configuration dependency validation */ if (config->websocket_max_message_size < config->websocket_max_frame_size) { UVHTTP_LOG_ERROR("websocket_max_message_size=%d < " @@ -383,19 +249,10 @@ void uvhttp_config_print(const uvhttp_config_t* config) { printf("\n=== UVHTTP Configuration ===\n"); printf("Server:\n"); printf(" Max Connections: %d\n", config->max_connections); - printf(" Read Buffer Size: %d bytes\n", config->read_buffer_size); printf(" Backlog: %d\n", config->backlog); - printf(" Keepalive Timeout: %d seconds\n", config->keepalive_timeout); - printf(" Request Timeout: %d seconds\n", config->request_timeout); - - printf("\nPerformance:\n"); - printf(" Max Body Size: %zu bytes\n", config->max_body_size); - printf(" Max Header Size: %zu bytes\n", config->max_header_size); - printf(" Max URL Size: %zu bytes\n", config->max_url_size); - printf("\nSecurity:\n"); - printf(" Max Requests per Connection: %d\n", - config->max_requests_per_connection); - printf(" Rate Limit Window: %d seconds\n", config->rate_limit_window); + printf(" Connection Timeout: %d seconds\n", config->connection_timeout); + printf(" Max File Size: %zu bytes\n", config->max_file_size); + printf(" Trust Proxy Headers: %d\n", config->trust_proxy_headers); printf("==============================\n\n"); } @@ -437,65 +294,6 @@ int uvhttp_config_update_max_connections(uvhttp_context_t* context, return UVHTTP_ERROR_INVALID_PARAM; } -/* Dynamically update read buffer size */ -int uvhttp_config_update_read_buffer_size(uvhttp_context_t* context, - int buffer_size) { - if (!context) { - return UVHTTP_ERROR_INVALID_PARAM; - } - if (buffer_size < 1024 || buffer_size > 1048576) { - return UVHTTP_ERROR_INVALID_PARAM; - } - - if (context->current_config) { - int old_value = - ((uvhttp_config_t*)context->current_config)->read_buffer_size; - ((uvhttp_config_t*)context->current_config)->read_buffer_size = - buffer_size; - - UVHTTP_LOG_INFO("Read buffer size updated: %d -> %d", old_value, - buffer_size); - (void)old_value; - return UVHTTP_OK; - } - - return UVHTTP_ERROR_INVALID_PARAM; -} - -/* Dynamically update size limits */ -int uvhttp_config_update_size_limits(uvhttp_context_t* context, - size_t max_body_size, - size_t max_header_size) { - if (!context) { - return UVHTTP_ERROR_INVALID_PARAM; - } - if (max_body_size < 1024 || max_body_size > 100 * 1024 * 1024) { - return UVHTTP_ERROR_INVALID_PARAM; - } - if (max_header_size < 512 || max_header_size > 64 * 1024) { - return UVHTTP_ERROR_INVALID_PARAM; - } - - if (context->current_config) { - size_t old_body = - ((uvhttp_config_t*)context->current_config)->max_body_size; - size_t old_header = - ((uvhttp_config_t*)context->current_config)->max_header_size; - - ((uvhttp_config_t*)context->current_config)->max_body_size = - max_body_size; - ((uvhttp_config_t*)context->current_config)->max_header_size = - max_header_size; - UVHTTP_LOG_INFO("Limits updated - Body: %zu -> %zu, Header: %zu -> %zu", - old_body, max_body_size, old_header, max_header_size); - (void)old_body; - (void)old_header; - return UVHTTP_OK; - } - - return UVHTTP_ERROR_INVALID_PARAM; -} - /* Set global configuration */ void uvhttp_config_set_current(uvhttp_context_t* context, uvhttp_config_t* config) { diff --git a/src/uvhttp_server.c b/src/uvhttp_server.c index 06386410..dcc75215 100644 --- a/src/uvhttp_server.c +++ b/src/uvhttp_server.c @@ -1032,23 +1032,6 @@ uvhttp_server_builder_t* uvhttp_set_max_connections( return server; } -uvhttp_server_builder_t* uvhttp_set_timeout(uvhttp_server_builder_t* server, - int timeout) { - if (server && server->config) { - server->config->request_timeout = timeout; - server->config->keepalive_timeout = timeout; - } - return server; -} - -uvhttp_server_builder_t* uvhttp_set_max_body_size( - uvhttp_server_builder_t* server, size_t size) { - if (server && server->config) { - server->config->max_body_size = size; - } - return server; -} - // Server run and cleanup int uvhttp_server_run(uvhttp_server_builder_t* server) { if (!server || !server->loop) diff --git a/test/unit/test_config_enhanced_coverage.cpp b/test/unit/test_config_enhanced_coverage.cpp index d36c4082..8edaecaa 100644 --- a/test/unit/test_config_enhanced_coverage.cpp +++ b/test/unit/test_config_enhanced_coverage.cpp @@ -1,29 +1,30 @@ /* uvhttp_config.c 增强覆盖率测试 */ -#include -#include "uvhttp_config.h" #include "uvhttp_allocator.h" +#include "uvhttp_config.h" #include "uvhttp_error.h" -#include + +#include #include +#include #include /* 测试配置创建和释放 */ TEST(UvhttpConfigEnhancedCoverageTest, CreateAndFree) { uvhttp_config_t* config = NULL; uvhttp_error_t result; - + /* 测试正常创建 */ result = uvhttp_config_new(&config); EXPECT_EQ(result, UVHTTP_OK); ASSERT_NE(config, nullptr); - + /* 测试释放 */ uvhttp_config_free(config); - + /* 测试释放NULL */ uvhttp_config_free(NULL); - + /* 测试NULL输出参数 */ result = uvhttp_config_new(NULL); EXPECT_NE(result, UVHTTP_OK); @@ -33,25 +34,22 @@ TEST(UvhttpConfigEnhancedCoverageTest, CreateAndFree) { TEST(UvhttpConfigEnhancedCoverageTest, SetDefaults) { uvhttp_config_t* config = NULL; uvhttp_error_t result; - + result = uvhttp_config_new(&config); ASSERT_EQ(result, UVHTTP_OK); - + /* 测试设置默认值 */ uvhttp_config_set_defaults(config); - - /* 验证一些默认值 */ + + /* 验证存活字段的默认值(v2.10 删除了 14 个无人读取的字段) */ EXPECT_GT(config->max_connections, 0); - EXPECT_GT(config->read_buffer_size, 0); EXPECT_GT(config->backlog, 0); - EXPECT_GT(config->keepalive_timeout, 0); - EXPECT_GT(config->request_timeout, 0); - EXPECT_GT(config->max_body_size, 0); - EXPECT_GT(config->max_header_size, 0); - EXPECT_GT(config->max_url_size, 0); - + EXPECT_GT(config->connection_timeout, 0); + EXPECT_GT(config->max_file_size, 0u); + EXPECT_EQ(config->trust_proxy_headers, 0); + uvhttp_config_free(config); - + /* 测试NULL参数 */ uvhttp_config_set_defaults(NULL); } @@ -60,31 +58,31 @@ TEST(UvhttpConfigEnhancedCoverageTest, SetDefaults) { TEST(UvhttpConfigEnhancedCoverageTest, Validate) { uvhttp_config_t* config = NULL; uvhttp_error_t result; - + result = uvhttp_config_new(&config); ASSERT_EQ(result, UVHTTP_OK); - + uvhttp_config_set_defaults(config); - + /* 测试有效配置 */ int valid = uvhttp_config_validate(config); EXPECT_EQ(valid, UVHTTP_OK); - + /* 测试无效配置 - 负值 */ config->max_connections = -1; valid = uvhttp_config_validate(config); EXPECT_NE(valid, UVHTTP_OK); - + /* 恢复有效值 */ config->max_connections = 1000; - - /* 测试无效配置 - 零值(小于最小缓冲区大小) */ - config->read_buffer_size = 0; + + /* 测试无效配置 - 零值(连接超时必须为正,否则 uv_timer_start 立即超时) */ + config->connection_timeout = 0; valid = uvhttp_config_validate(config); EXPECT_NE(valid, UVHTTP_OK); - + uvhttp_config_free(config); - + /* 测试NULL参数 */ valid = uvhttp_config_validate(NULL); EXPECT_NE(valid, UVHTTP_OK); @@ -94,17 +92,17 @@ TEST(UvhttpConfigEnhancedCoverageTest, Validate) { TEST(UvhttpConfigEnhancedCoverageTest, Print) { uvhttp_config_t* config = NULL; uvhttp_error_t result; - + result = uvhttp_config_new(&config); ASSERT_EQ(result, UVHTTP_OK); - + uvhttp_config_set_defaults(config); - + /* 测试打印配置 */ uvhttp_config_print(config); - + uvhttp_config_free(config); - + /* 测试NULL参数 */ uvhttp_config_print(NULL); } @@ -114,10 +112,10 @@ TEST(UvhttpConfigEnhancedCoverageTest, FileLoadAndSave) { uvhttp_config_t* config = NULL; uvhttp_error_t result; const char* test_file = "/tmp/test_uvhttp_config.tmp"; - + result = uvhttp_config_new(&config); ASSERT_EQ(result, UVHTTP_OK); - + uvhttp_config_set_defaults(config); /* 配置文件和环境变量加载功能已移除,符合极简工程原则 */ @@ -129,24 +127,18 @@ TEST(UvhttpConfigEnhancedCoverageTest, FileLoadAndSave) { TEST(UvhttpConfigEnhancedCoverageTest, DynamicUpdate) { uvhttp_config_t* config = NULL; uvhttp_error_t result; - + result = uvhttp_config_new(&config); ASSERT_EQ(result, UVHTTP_OK); - + uvhttp_config_set_defaults(config); - - /* 测试更新最大连接数 */ + + /* 更新入口只剩 max_connections 一个(v2.10 删除了 + * update_read_buffer_size / update_size_limits —— 它们写入的字段无人读取, + * 却返回成功并打印 "Limits updated" 日志) */ int update_result = uvhttp_config_update_max_connections(NULL, 2000); EXPECT_NE(update_result, 0); - - /* 测试更新读缓冲区大小 */ - update_result = uvhttp_config_update_read_buffer_size(NULL, 8192); - EXPECT_NE(update_result, 0); - - /* 测试更新大小限制 */ - update_result = uvhttp_config_update_size_limits(NULL, 1024 * 1024, 8192); - EXPECT_NE(update_result, 0); - + uvhttp_config_free(config); } @@ -156,36 +148,26 @@ TEST(UvhttpConfigEnhancedCoverageTest, DynamicUpdate) { TEST(UvhttpConfigEnhancedCoverageTest, BoundaryValues) { uvhttp_config_t* config = NULL; uvhttp_error_t result; - + result = uvhttp_config_new(&config); ASSERT_EQ(result, UVHTTP_OK); - + /* 测试最小值 */ config->max_connections = 1; - config->read_buffer_size = 1024; /* 最小缓冲区大小 */ config->backlog = 1; - config->keepalive_timeout = 1; - config->request_timeout = 1; - config->max_body_size = 1024; - config->max_header_size = 256; - config->max_url_size = 64; - + config->connection_timeout = UVHTTP_CONNECTION_TIMEOUT_MIN; + int valid = uvhttp_config_validate(config); EXPECT_EQ(valid, UVHTTP_OK); - + /* 测试最大值 */ config->max_connections = 65535; - config->read_buffer_size = 1024 * 1024; config->backlog = 65535; - config->keepalive_timeout = 86400; /* 24小时 */ - config->request_timeout = 86400; - config->max_body_size = 100 * 1024 * 1024; /* 100MB,最大限制 */ - config->max_header_size = 8192; /* 合理的最大值 */ - config->max_url_size = 4096; /* 合理的最大值 */ - + config->connection_timeout = UVHTTP_CONNECTION_TIMEOUT_MAX; + valid = uvhttp_config_validate(config); EXPECT_EQ(valid, UVHTTP_OK); - + uvhttp_config_free(config); } @@ -194,21 +176,21 @@ TEST(UvhttpConfigEnhancedCoverageTest, MemoryAllocation) { uvhttp_config_t* config1 = NULL; uvhttp_config_t* config2 = NULL; uvhttp_error_t result; - + /* 测试多次创建和释放 */ result = uvhttp_config_new(&config1); EXPECT_EQ(result, UVHTTP_OK); - + result = uvhttp_config_new(&config2); EXPECT_EQ(result, UVHTTP_OK); - + ASSERT_NE(config1, nullptr); ASSERT_NE(config2, nullptr); ASSERT_NE(config1, config2); - + uvhttp_config_free(config1); uvhttp_config_free(config2); - - /* 注意:不测试重复释放,因为 uvhttp_config_free 应该能够安全地处理 NULL 指针 - * 但是重复释放非 NULL 指针会导致双重释放错误 */ + + /* 注意:不测试重复释放,因为 uvhttp_config_free 应该能够安全地处理 NULL + * 指针 但是重复释放非 NULL 指针会导致双重释放错误 */ } \ No newline at end of file diff --git a/test/unit/test_config_full_coverage.cpp b/test/unit/test_config_full_coverage.cpp index 9241bbee..e3b300e9 100644 --- a/test/unit/test_config_full_coverage.cpp +++ b/test/unit/test_config_full_coverage.cpp @@ -1,7 +1,7 @@ /** * @file test_config_full_coverage.cpp * @brief Comprehensive coverage tests for uvhttp_config module - * + * * This test file aims to achieve 100% coverage for uvhttp_config.c by testing: * - NULL parameter handling * - Memory allocation failures @@ -11,25 +11,24 @@ * - Edge cases and boundary conditions */ -#include -#include - #include "uvhttp_config.h" #include "uvhttp_context.h" #include "uvhttp_error.h" +#include +#include #include class UvhttpConfigTest : public ::testing::Test { -protected: + protected: void SetUp() override { uv_error = uv_loop_init(&loop); ASSERT_EQ(uv_error, 0); - + uvhttp_error_t err = uvhttp_config_new(&config); ASSERT_EQ(err, UVHTTP_OK); ASSERT_NE(config, nullptr); - + err = uvhttp_context_create(&loop, &context); ASSERT_EQ(err, UVHTTP_OK); ASSERT_NE(context, nullptr); @@ -60,10 +59,10 @@ class UvhttpConfigTest : public ::testing::Test { TEST_F(UvhttpConfigTest, ConfigNewSuccess) { uvhttp_config_t* test_config = nullptr; uvhttp_error_t err = uvhttp_config_new(&test_config); - + EXPECT_EQ(err, UVHTTP_OK); EXPECT_NE(test_config, nullptr); - + uvhttp_config_free(test_config); } @@ -84,13 +83,29 @@ TEST_F(UvhttpConfigTest, ConfigSetDefaultsNull) { TEST_F(UvhttpConfigTest, ConfigSetDefaultsValid) { uvhttp_config_set_defaults(config); - - // Verify default values are set - EXPECT_GT(config->max_connections, 0); - EXPECT_GT(config->read_buffer_size, 0); - EXPECT_GT(config->backlog, 0); - EXPECT_GT(config->keepalive_timeout, 0); - EXPECT_GT(config->request_timeout, 0); + + // Pin every surviving field to its documented default. v2.10 deleted the 14 + // fields nothing read; this test is the inventory that must keep shrinking + // or growing only together with the code that reads the field - never on + // its own. + EXPECT_EQ(config->max_connections, UVHTTP_DEFAULT_MAX_CONNECTIONS); + EXPECT_EQ(config->backlog, UVHTTP_DEFAULT_BACKLOG); + EXPECT_EQ(config->connection_timeout, UVHTTP_CONNECTION_TIMEOUT_DEFAULT); + EXPECT_EQ(config->max_file_size, UVHTTP_DEFAULT_MAX_FILE_SIZE); + EXPECT_EQ(config->trust_proxy_headers, 0); + EXPECT_EQ(config->websocket_max_frame_size, + UVHTTP_WEBSOCKET_DEFAULT_MAX_FRAME_SIZE); + EXPECT_EQ(config->websocket_max_message_size, + UVHTTP_WEBSOCKET_DEFAULT_MAX_MESSAGE_SIZE); + EXPECT_EQ(config->websocket_ping_interval, + UVHTTP_WEBSOCKET_DEFAULT_PING_INTERVAL); + EXPECT_EQ(config->websocket_ping_timeout, + UVHTTP_WEBSOCKET_DEFAULT_PING_TIMEOUT); + EXPECT_EQ(config->tcp_keepalive_timeout, UVHTTP_TCP_KEEPALIVE_TIMEOUT); + EXPECT_EQ(config->sendfile_timeout_ms, UVHTTP_SENDFILE_TIMEOUT_MS); + EXPECT_EQ(config->sendfile_max_retry, UVHTTP_SENDFILE_DEFAULT_MAX_RETRY); + + EXPECT_EQ(uvhttp_config_validate(config), UVHTTP_OK); } // Configuration validation tests @@ -123,42 +138,6 @@ TEST_F(UvhttpConfigTest, ConfigValidateValidConnections) { EXPECT_EQ(result, UVHTTP_OK); } -TEST_F(UvhttpConfigTest, ConfigValidateMinBufferSize) { - config->read_buffer_size = 512; // Below minimum - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateMaxBufferSize) { - config->read_buffer_size = 2 * 1024 * 1024; // Above maximum - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateValidBufferSize) { - config->read_buffer_size = 8192; - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_OK); -} - -TEST_F(UvhttpConfigTest, ConfigValidateMinBodySize) { - config->max_body_size = 512; // Below minimum - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateMaxBodySize) { - config->max_body_size = 200 * 1024 * 1024; // Above maximum - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateValidBodySize) { - config->max_body_size = 10 * 1024 * 1024; - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_OK); -} - // WebSocket configuration validation TEST_F(UvhttpConfigTest, ConfigValidateMinWebSocketFrameSize) { config->websocket_max_frame_size = 0; // Below minimum @@ -167,7 +146,8 @@ TEST_F(UvhttpConfigTest, ConfigValidateMinWebSocketFrameSize) { } TEST_F(UvhttpConfigTest, ConfigValidateMaxWebSocketFrameSize) { - config->websocket_max_frame_size = 300 * 1024 * 1024; // Above maximum (256MB) + config->websocket_max_frame_size = + 300 * 1024 * 1024; // Above maximum (256MB) int result = uvhttp_config_validate(config); EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); } @@ -179,14 +159,16 @@ TEST_F(UvhttpConfigTest, ConfigValidateMinWebSocketMessageSize) { } TEST_F(UvhttpConfigTest, ConfigValidateMaxWebSocketMessageSize) { - config->websocket_max_message_size = 2ULL * 1024 * 1024 * 1024; // Above maximum (1GB) + config->websocket_max_message_size = + 2ULL * 1024 * 1024 * 1024; // Above maximum (1GB) int result = uvhttp_config_validate(config); EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); } TEST_F(UvhttpConfigTest, ConfigValidateMessageSizeLessThanFrameSize) { config->websocket_max_frame_size = 16 * 1024 * 1024; - config->websocket_max_message_size = 8 * 1024 * 1024; // Less than frame size + config->websocket_max_message_size = + 8 * 1024 * 1024; // Less than frame size int result = uvhttp_config_validate(config); EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); } @@ -225,55 +207,7 @@ TEST_F(UvhttpConfigTest, ConfigValidateMaxSendfileTimeout) { } // Cache configuration validation -TEST_F(UvhttpConfigTest, ConfigValidateMinCacheMaxEntries) { - config->cache_default_max_entries = -1; // Below minimum (0) - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateMaxCacheMaxEntries) { - config->cache_default_max_entries = 1000000; // Above maximum - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateMinCacheTTL) { - config->cache_default_ttl = -1; // Below minimum (0) - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateMaxCacheTTL) { - config->cache_default_ttl = 86400 * 2; // Above maximum - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - // Rate limiting validation -TEST_F(UvhttpConfigTest, ConfigValidateMinRateLimitMaxRequests) { - config->rate_limit_max_requests = 0; // Below minimum - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateMaxRateLimitMaxRequests) { - config->rate_limit_max_requests = 20000000; // Above maximum (10000000) - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateMinRateLimitWindowSeconds) { - config->rate_limit_max_window_seconds = 0; // Below minimum - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigValidateMaxRateLimitWindowSeconds) { - config->rate_limit_max_window_seconds = 100000; // Above maximum (86400) - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - // Configuration print tests TEST_F(UvhttpConfigTest, ConfigPrintNull) { // Should not crash @@ -341,71 +275,6 @@ TEST_F(UvhttpConfigTest, ConfigUpdateMaxConnectionsValid) { EXPECT_EQ(config->max_connections, 500); } -TEST_F(UvhttpConfigTest, ConfigUpdateReadBufferSizeNullContext) { - int result = uvhttp_config_update_read_buffer_size(nullptr, 8192); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateReadBufferSizeMinValue) { - int result = uvhttp_config_update_read_buffer_size(context, 512); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateReadBufferSizeMaxValue) { - int result = uvhttp_config_update_read_buffer_size(context, 2 * 1024 * 1024); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateReadBufferSizeNoConfig) { - int result = uvhttp_config_update_read_buffer_size(context, 8192); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateReadBufferSizeValid) { - uvhttp_config_set_current(context, config); - int result = uvhttp_config_update_read_buffer_size(context, 16384); - EXPECT_EQ(result, UVHTTP_OK); - EXPECT_EQ(config->read_buffer_size, 16384); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateSizeLimitsNullContext) { - int result = uvhttp_config_update_size_limits(nullptr, 1024, 512); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateSizeLimitsMinBodySize) { - int result = uvhttp_config_update_size_limits(context, 512, 512); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateSizeLimitsMaxBodySize) { - int result = uvhttp_config_update_size_limits(context, 200 * 1024 * 1024, 512); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateSizeLimitsMinHeaderSize) { - int result = uvhttp_config_update_size_limits(context, 1024, 256); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateSizeLimitsMaxHeaderSize) { - int result = uvhttp_config_update_size_limits(context, 1024, 128 * 1024); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateSizeLimitsNoConfig) { - int result = uvhttp_config_update_size_limits(context, 1024, 512); - EXPECT_EQ(result, UVHTTP_ERROR_INVALID_PARAM); -} - -TEST_F(UvhttpConfigTest, ConfigUpdateSizeLimitsValid) { - uvhttp_config_set_current(context, config); - int result = uvhttp_config_update_size_limits(context, 20 * 1024 * 1024, 16384); - EXPECT_EQ(result, UVHTTP_OK); - EXPECT_EQ(config->max_body_size, 20 * 1024 * 1024); - EXPECT_EQ(config->max_header_size, 16384); -} - // Boundary value tests TEST_F(UvhttpConfigTest, ConfigBoundaryConnectionsMin) { config->max_connections = 1; @@ -419,57 +288,26 @@ TEST_F(UvhttpConfigTest, ConfigBoundaryConnectionsMax) { EXPECT_EQ(result, UVHTTP_OK); } -TEST_F(UvhttpConfigTest, ConfigBoundaryBufferSizeMin) { - config->read_buffer_size = 1024; - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_OK); -} - -TEST_F(UvhttpConfigTest, ConfigBoundaryBufferSizeMax) { - config->read_buffer_size = 1024 * 1024; - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_OK); -} - -TEST_F(UvhttpConfigTest, ConfigBoundaryBodySizeMin) { - config->max_body_size = 1024; - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_OK); -} - -TEST_F(UvhttpConfigTest, ConfigBoundaryBodySizeMax) { - config->max_body_size = 100 * 1024 * 1024; - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_OK); -} - // All configuration fields tests TEST_F(UvhttpConfigTest, ConfigAllServerFields) { config->max_connections = 1000; - config->read_buffer_size = 8192; config->backlog = 128; - config->keepalive_timeout = 30; - config->request_timeout = 30; config->connection_timeout = 60; - + int result = uvhttp_config_validate(config); EXPECT_EQ(result, UVHTTP_OK); } TEST_F(UvhttpConfigTest, ConfigAllPerformanceFields) { - config->max_body_size = 10 * 1024 * 1024; - config->max_header_size = 8192; - config->max_url_size = 2048; config->max_file_size = 100 * 1024 * 1024; - + int result = uvhttp_config_validate(config); EXPECT_EQ(result, UVHTTP_OK); } TEST_F(UvhttpConfigTest, ConfigAllSecurityFields) { - config->max_requests_per_connection = 100; - config->rate_limit_window = 60; - + config->trust_proxy_headers = 1; + int result = uvhttp_config_validate(config); EXPECT_EQ(result, UVHTTP_OK); } @@ -479,7 +317,7 @@ TEST_F(UvhttpConfigTest, ConfigAllWebSocketFields) { config->websocket_max_message_size = 64 * 1024 * 1024; config->websocket_ping_interval = 30; config->websocket_ping_timeout = 10; - + int result = uvhttp_config_validate(config); EXPECT_EQ(result, UVHTTP_OK); } @@ -488,25 +326,7 @@ TEST_F(UvhttpConfigTest, ConfigAllNetworkFields) { config->tcp_keepalive_timeout = 60; config->sendfile_timeout_ms = 5000; config->sendfile_max_retry = 3; - - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_OK); -} - -TEST_F(UvhttpConfigTest, ConfigAllCacheFields) { - config->cache_default_max_entries = 1000; - config->cache_default_ttl = 3600; - config->lru_cache_batch_eviction_size = 10; - - int result = uvhttp_config_validate(config); - EXPECT_EQ(result, UVHTTP_OK); -} -TEST_F(UvhttpConfigTest, ConfigAllRateLimitFields) { - config->rate_limit_max_requests = 100; - config->rate_limit_max_window_seconds = 60; - config->rate_limit_min_timeout_seconds = 10; - int result = uvhttp_config_validate(config); EXPECT_EQ(result, UVHTTP_OK); } @@ -514,16 +334,9 @@ TEST_F(UvhttpConfigTest, ConfigAllRateLimitFields) { // Multiple updates test TEST_F(UvhttpConfigTest, ConfigMultipleUpdates) { uvhttp_config_set_current(context, config); - + uvhttp_config_update_max_connections(context, 500); EXPECT_EQ(config->max_connections, 500); - - uvhttp_config_update_read_buffer_size(context, 16384); - EXPECT_EQ(config->read_buffer_size, 16384); - - uvhttp_config_update_size_limits(context, 20 * 1024 * 1024, 16384); - EXPECT_EQ(config->max_body_size, 20 * 1024 * 1024); - EXPECT_EQ(config->max_header_size, 16384); } // Complete workflow test @@ -533,37 +346,32 @@ TEST_F(UvhttpConfigTest, ConfigCompleteWorkflow) { uvhttp_error_t err = uvhttp_config_new(&workflow_config); ASSERT_EQ(err, UVHTTP_OK); ASSERT_NE(workflow_config, nullptr); - + // Set defaults uvhttp_config_set_defaults(workflow_config); - + // Validate int result = uvhttp_config_validate(workflow_config); EXPECT_EQ(result, UVHTTP_OK); - + // Set to context uvhttp_config_set_current(context, workflow_config); - + // Get current const uvhttp_config_t* current = uvhttp_config_get_current(context); EXPECT_EQ(current, workflow_config); - + // Update values uvhttp_config_update_max_connections(context, 800); - uvhttp_config_update_read_buffer_size(context, 16384); - uvhttp_config_update_size_limits(context, 15 * 1024 * 1024, 12288); - + // Verify updates EXPECT_EQ(workflow_config->max_connections, 800); - EXPECT_EQ(workflow_config->read_buffer_size, 16384); - EXPECT_EQ(workflow_config->max_body_size, 15 * 1024 * 1024); - EXPECT_EQ(workflow_config->max_header_size, 12288); - + // Clean up uvhttp_config_free(workflow_config); } -int main(int argc, char **argv) { +int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/test/unit/test_server_api_coverage.cpp b/test/unit/test_server_api_coverage.cpp index e8d3a49e..1e2c8355 100644 --- a/test/unit/test_server_api_coverage.cpp +++ b/test/unit/test_server_api_coverage.cpp @@ -361,12 +361,6 @@ TEST_F(UvhttpServerApiTest, ServerBuilderMethods) { result2 = uvhttp_set_max_connections(builder, 100); EXPECT_NE(result2, nullptr); - result2 = uvhttp_set_timeout(builder, 30); - EXPECT_NE(result2, nullptr); - - result2 = uvhttp_set_max_body_size(builder, 1024 * 1024); - EXPECT_NE(result2, nullptr); - /* 释放服务器 */ uvhttp_server_simple_free(builder); } @@ -389,12 +383,6 @@ TEST_F(UvhttpServerApiTest, ServerBuilderMethodsNull) { result = uvhttp_set_max_connections(NULL, 100); EXPECT_EQ(result, nullptr); - - result = uvhttp_set_timeout(NULL, 30); - EXPECT_EQ(result, nullptr); - - result = uvhttp_set_max_body_size(NULL, 1024 * 1024); - EXPECT_EQ(result, nullptr); } /* 测试服务器停止简单模式 */ diff --git a/test/unit/test_server_boost_coverage.cpp b/test/unit/test_server_boost_coverage.cpp index c1186a94..8aabaa78 100644 --- a/test/unit/test_server_boost_coverage.cpp +++ b/test/unit/test_server_boost_coverage.cpp @@ -298,33 +298,6 @@ TEST_F(BuilderAPITest, SetMaxConnections_Valid) { EXPECT_EQ(builder->config->max_connections, 500); } -TEST_F(BuilderAPITest, SetTimeout_NullServer) { - uvhttp_server_builder_t* result = uvhttp_set_timeout(nullptr, 30); - EXPECT_EQ(result, nullptr); -} - -TEST_F(BuilderAPITest, SetTimeout_Valid) { - if (!builder) - GTEST_SKIP(); - uvhttp_server_builder_t* result = uvhttp_set_timeout(builder, 60); - EXPECT_EQ(result, builder); - EXPECT_EQ(builder->config->request_timeout, 60); - EXPECT_EQ(builder->config->keepalive_timeout, 60); -} - -TEST_F(BuilderAPITest, SetMaxBodySize_NullServer) { - uvhttp_server_builder_t* result = uvhttp_set_max_body_size(nullptr, 1024); - EXPECT_EQ(result, nullptr); -} - -TEST_F(BuilderAPITest, SetMaxBodySize_Valid) { - if (!builder) - GTEST_SKIP(); - uvhttp_server_builder_t* result = uvhttp_set_max_body_size(builder, 2048); - EXPECT_EQ(result, builder); - EXPECT_EQ(builder->config->max_body_size, (size_t)2048); -} - // --- Convenient request parameter access --- TEST_F(BuilderAPITest, GetParam_NullRequest) { diff --git a/test/unit/test_server_simple_handlers_coverage.cpp b/test/unit/test_server_simple_handlers_coverage.cpp index 34ef2bb3..1d98d53d 100644 --- a/test/unit/test_server_simple_handlers_coverage.cpp +++ b/test/unit/test_server_simple_handlers_coverage.cpp @@ -70,6 +70,11 @@ TEST(UvhttpServerSimpleHandlersTest, GetHeader) { const char* header = uvhttp_request_get_header(&request, "Content-Type"); ASSERT_NE(header, nullptr); EXPECT_STREQ(header, "application/json"); + + /* add_header 溢出内联表时会堆分配 headers_extra;request 本身在栈上, + * 不会有人替你调用析构。不清理即为 ASan 报告的泄漏(#455 改用 add_header + * 构造可查询的 header 时引入)。 */ + uvhttp_request_cleanup(&request); } /* 测试获取请求头 NULL 请求 */