fix(libhttp): WebSocket 单条消息大小限制防 OOM (P1-3)
- 新增 setMaxWsMessageSize/getMaxWsMessageSize(默认 16MB,与 Beast 默认一致) - 服务端 doWsUpgrade/doWssUpgrade 与代理流 onProxyConnect/onProxySslHandshake 创建后调用 read_message_max - 超限消息由 Beast 在分配内存前拒绝并关闭连接 - 更新审计文档 P1-3 状态、README v3.4.1
This commit is contained in:
1 parent
85e0d0740b
commit
507054c4b2
4 files changed
+26
-4
No files matched your search
@@ -13,6 +13,7 @@ C++20 network library for the UniServe microservice framework, providing unified
|
||||
- **Static Files**: `setStaticDirectory()` for serving static files
|
||||
- **Thread Pool**: Multi-threaded I/O with `asio::strand` for thread safety
|
||||
- **Client Management**: WebSocket client tracking, broadcast, and targeted send
|
||||
- **WS Message Size Limit**: `setMaxWsMessageSize()` caps single WebSocket message (default 16MB, aligned with Beast; applies to server and proxy streams) to prevent OOM
|
||||
|
||||
### HttpClient
|
||||
- **HTTP Client**: Synchronous HTTP requests via libcurl (GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS)
|
||||
@@ -167,6 +168,10 @@ void use(MiddlewareHandler middleware);
|
||||
void setStaticDirectory(const std::string& path);
|
||||
```
|
||||
|
||||
// WebSocket 单条消息大小上限(字节)。默认 16MB,与 Beast 默认一致;超限由 Beast 拒绝并关闭连接(防 OOM)。
|
||||
void setMaxWsMessageSize(std::size_t bytes);
|
||||
std::size_t getMaxWsMessageSize() const;
|
||||
|
||||
**WebSocket Routes**
|
||||
```cpp
|
||||
void ws(const std::string& path, WebSocketMessageHandler handler);
|
||||
@@ -283,6 +288,7 @@ using WebSocketClientBase = HttpClient;
|
||||
|
||||
## Version History
|
||||
|
||||
- **v3.4.1**: WebSocket 单条消息大小限制(P1-3)。新增 `setMaxWsMessageSize()`/`getMaxWsMessageSize()`(默认 16MB,与 Beast 默认一致),服务端 `doWsUpgrade`/`doWssUpgrade` 与代理 `onProxyConnect`/`onProxySslHandshake` 创建流后调用 `read_message_max()`,超限消息由 Beast 在分配内存前拒绝并关闭连接,防 OOM。
|
||||
- **v3.4.0**: HttpClient 响应大小限制(防 OOM)。`request_stream_sync` 改为真流式(按块回调,不二次缓冲);新增 `set_max_response_size()`/`get_max_response_size()`(默认 10MB,对齐 WAF,0 表示不限制),超限时 `write_callback` 返回 0 中止传输并抛异常。
|
||||
- **v3.3.0**: Split HttpServer into 6 modular translation units by functional area (core/lifecycle, listener, routes, request dispatch, WS management, WS session/proxy) for dramatically faster incremental builds. Added internal detail header `inc/us/detail/HttpServerImpl.hpp` for shared definitions across TU boundaries.
|
||||
- **v3.2.0**: Split into two shared libraries — `libus_http.so` (server only, no curl) and `libus_httpclient.so` (HttpClient, depends on curl). HttpClient implementation moved to `src/HttpClient.cpp`; `HttpClient.hpp` is declaration-only.
|
||||
|
||||
@@ -119,6 +119,11 @@ public:
|
||||
void setMaxBodySize(std::size_t bytes) { max_body_size_ = bytes; }
|
||||
std::size_t getMaxBodySize() const { return max_body_size_; }
|
||||
|
||||
// WebSocket 单条消息大小上限(字节)。默认 16MB,与 Beast 默认一致(防 OOM)。
|
||||
// 超限时 Beast 拒绝该消息并关闭连接(P1-3)。
|
||||
void setMaxWsMessageSize(std::size_t bytes) { max_ws_message_size_ = bytes; }
|
||||
std::size_t getMaxWsMessageSize() const { return max_ws_message_size_; }
|
||||
|
||||
class debug {
|
||||
public:
|
||||
static void print_all_header_fields(const http::request<http::string_body>& req);
|
||||
@@ -134,6 +139,7 @@ private:
|
||||
std::atomic<bool> running_{false};
|
||||
|
||||
std::size_t max_body_size_ = 10 * 1024 * 1024; // 默认 10MB,与 WAF 对齐
|
||||
std::size_t max_ws_message_size_ = 16 * 1024 * 1024; // 默认 16MB,与 Beast 默认一致
|
||||
|
||||
bool ssl_enabled_{false};
|
||||
std::string cert_file_;
|
||||
|
||||
@@ -19,6 +19,8 @@ void HttpServer::Session::doWsUpgrade() {
|
||||
auto self = shared_from_this();
|
||||
ws_stream_ = std::make_unique<ws_stream>(stream_);
|
||||
ws_stream_->text(true);
|
||||
// P1-3:限制单条 WS 消息大小,超限由 Beast 拒绝并关闭连接(防 OOM)
|
||||
ws_stream_->read_message_max(server_->getMaxWsMessageSize());
|
||||
|
||||
ws_stream_->async_accept(
|
||||
request_,
|
||||
@@ -31,6 +33,8 @@ void HttpServer::Session::doWssUpgrade() {
|
||||
auto self = shared_from_this();
|
||||
wss_stream_ = std::make_unique<wss_stream>(*ssl_stream_);
|
||||
wss_stream_->text(true);
|
||||
// P1-3:限制单条 WS 消息大小,超限由 Beast 拒绝并关闭连接(防 OOM)
|
||||
wss_stream_->read_message_max(server_->getMaxWsMessageSize());
|
||||
|
||||
wss_stream_->async_accept(
|
||||
request_,
|
||||
@@ -261,6 +265,9 @@ void HttpServer::Session::onProxyConnect(beast::error_code ec, tcp::endpoint /*e
|
||||
proxy_ws_stream_ = std::make_unique<proxy_ws_stream>(proxy_tcp_stream_->socket());
|
||||
proxy_tcp_stream_->expires_never();
|
||||
|
||||
// P1-3:限制代理方向单条 WS 消息大小(防 OOM)
|
||||
proxy_ws_stream_->read_message_max(server_->getMaxWsMessageSize());
|
||||
|
||||
proxy_ws_stream_->set_option(websocket::stream_base::decorator(
|
||||
[](websocket::request_type& req) {
|
||||
req.set(http::field::user_agent, "UniServe-WsProxy");
|
||||
@@ -286,6 +293,9 @@ void HttpServer::Session::onProxySslHandshake(beast::error_code ec) {
|
||||
proxy_wss_stream_ = std::make_unique<proxy_wss_stream>(*proxy_ssl_stream_);
|
||||
proxy_tcp_stream_->expires_never();
|
||||
|
||||
// P1-3:限制代理方向单条 WS 消息大小(防 OOM)
|
||||
proxy_wss_stream_->read_message_max(server_->getMaxWsMessageSize());
|
||||
|
||||
proxy_wss_stream_->set_option(websocket::stream_base::decorator(
|
||||
[](websocket::request_type& req) {
|
||||
req.set(http::field::user_agent, "UniServe-WsProxy");
|
||||
|
||||
Reference in new issue
Block a user