diff --git a/Config.h b/Config.h index 6f46700..c99a205 100644 --- a/Config.h +++ b/Config.h @@ -19,6 +19,9 @@ public: // 缓冲区大小 static const int BUFFER_SIZE = 4096; + // HTTP请求限制 + static const int MAX_REQUEST_SIZE = 1048576; // 1MB maximum request size + // Creo配置 static const int CREO_CHECK_INTERVAL_MS = 100; // 检查间隔 diff --git a/HttpServer.cpp b/HttpServer.cpp index 32941d7..4ab6ffc 100644 --- a/HttpServer.cpp +++ b/HttpServer.cpp @@ -108,28 +108,13 @@ DWORD WINAPI HttpServer::ServerThread(LPVOID lpParam) { } void HttpServer::HandleClient(SOCKET client_socket) { - char buffer[Config::BUFFER_SIZE]; - int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0); - - // 检查recv错误和超时情况 - if (bytes_received == SOCKET_ERROR) { - int error = WSAGetLastError(); - if (error == WSAETIMEDOUT) { - // 接收超时,直接返回避免阻塞 - return; - } - // 其他网络错误,直接返回 + // 读取完整的HTTP请求 + std::string raw_request = ReadCompleteRequest(client_socket); + if (raw_request.empty()) { + // 读取失败或超时,直接返回 return; } - if (bytes_received <= 0) { - // 连接关闭或无数据,直接返回 - return; - } - - buffer[bytes_received] = '\0'; - std::string raw_request(buffer); - HttpRequest request = ParseRequest(raw_request); HttpResponse response; @@ -199,6 +184,110 @@ HttpRequest HttpServer::ParseRequest(const std::string& raw_request) { return request; } +std::string HttpServer::ReadCompleteRequest(SOCKET client_socket) { + std::string complete_request; + char buffer[Config::BUFFER_SIZE]; + int total_received = 0; + int content_length = -1; + bool headers_complete = false; + size_t header_end_pos = 0; + + try { + // First, read headers to determine Content-Length + while (!headers_complete && total_received < Config::MAX_REQUEST_SIZE) { + int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0); + + // Check for recv errors and timeout + if (bytes_received == SOCKET_ERROR) { + int error = WSAGetLastError(); + if (error == WSAETIMEDOUT) { + return ""; // Timeout, return empty + } + return ""; // Other network error, return empty + } + + if (bytes_received <= 0) { + return ""; // Connection closed or no data + } + + buffer[bytes_received] = '\0'; + complete_request.append(buffer, bytes_received); + total_received += bytes_received; + + // Check if headers are complete (look for \r\n\r\n) + size_t header_separator = complete_request.find("\r\n\r\n"); + if (header_separator != std::string::npos) { + headers_complete = true; + header_end_pos = header_separator + 4; + + // Parse Content-Length from headers + std::string headers_part = complete_request.substr(0, header_end_pos); + size_t cl_pos = headers_part.find("Content-Length:"); + if (cl_pos != std::string::npos) { + size_t cl_start = cl_pos + 15; // Length of "Content-Length:" + size_t cl_end = headers_part.find("\r\n", cl_start); + if (cl_end != std::string::npos) { + std::string cl_str = headers_part.substr(cl_start, cl_end - cl_start); + // Remove leading/trailing whitespace + cl_str.erase(0, cl_str.find_first_not_of(" \t")); + cl_str.erase(cl_str.find_last_not_of(" \t") + 1); + try { + content_length = std::stoi(cl_str); + } catch (...) { + content_length = 0; + } + } + } + break; + } + } + + // If no Content-Length header found, assume no body or return what we have + if (content_length < 0) { + return complete_request; + } + + // Check if request size exceeds limit + if (content_length > Config::MAX_REQUEST_SIZE) { + return ""; // Request too large + } + + // Calculate how much body data we already have + int current_body_length = complete_request.length() - header_end_pos; + + // Read remaining body data if needed + while (current_body_length < content_length && total_received < Config::MAX_REQUEST_SIZE) { + int bytes_needed = content_length - current_body_length; + int bytes_to_read = min(bytes_needed, sizeof(buffer) - 1); + + int bytes_received = recv(client_socket, buffer, bytes_to_read, 0); + + if (bytes_received == SOCKET_ERROR) { + int error = WSAGetLastError(); + if (error == WSAETIMEDOUT) { + break; // Timeout, return what we have + } + break; // Other error, return what we have + } + + if (bytes_received <= 0) { + break; // Connection closed + } + + buffer[bytes_received] = '\0'; + complete_request.append(buffer, bytes_received); + current_body_length += bytes_received; + total_received += bytes_received; + } + + } catch (...) { + // Any exception during reading, return empty + return ""; + } + + return complete_request; +} + void HttpServer::SendResponse(SOCKET client_socket, const HttpResponse& response) { std::ostringstream response_stream; diff --git a/HttpServer.h b/HttpServer.h index c97b49c..844f30c 100644 --- a/HttpServer.h +++ b/HttpServer.h @@ -47,6 +47,7 @@ public: private: static DWORD WINAPI ServerThread(LPVOID lpParam); void HandleClient(SOCKET client_socket); + std::string ReadCompleteRequest(SOCKET client_socket); HttpRequest ParseRequest(const std::string& raw_request); void SendResponse(SOCKET client_socket, const HttpResponse& response);