| 94 | } |
| 95 | |
| 96 | std::tuple<bool, std::string, HttpRequestPtr> Http::parseRequest( |
| 97 | std::unique_ptr<Socket>& socket, int timeoutSecs) |
| 98 | { |
| 99 | HttpRequestPtr httpRequest; |
| 100 | |
| 101 | std::atomic<bool> requestInitCancellation(false); |
| 102 | |
| 103 | auto isCancellationRequested = |
| 104 | makeCancellationRequestWithTimeout(timeoutSecs, requestInitCancellation); |
| 105 | |
| 106 | // Read first line |
| 107 | auto lineResult = socket->readLine(isCancellationRequested); |
| 108 | auto lineValid = lineResult.first; |
| 109 | auto line = lineResult.second; |
| 110 | |
| 111 | if (!lineValid) |
| 112 | { |
| 113 | return std::make_tuple(false, "Error reading HTTP request line", httpRequest); |
| 114 | } |
| 115 | |
| 116 | // Parse request line (GET /foo HTTP/1.1\r\n) |
| 117 | auto requestLine = Http::parseRequestLine(line); |
| 118 | auto method = std::get<0>(requestLine); |
| 119 | auto uri = std::get<1>(requestLine); |
| 120 | auto httpVersion = std::get<2>(requestLine); |
| 121 | |
| 122 | // Retrieve and validate HTTP headers |
| 123 | auto result = parseHttpHeaders(socket, isCancellationRequested); |
| 124 | auto headersValid = result.first; |
| 125 | auto headers = result.second; |
| 126 | |
| 127 | if (!headersValid) |
| 128 | { |
| 129 | return std::make_tuple(false, "Error parsing HTTP headers", httpRequest); |
| 130 | } |
| 131 | |
| 132 | std::string body; |
| 133 | if (headers.find("Content-Length") != headers.end()) |
| 134 | { |
| 135 | int contentLength = 0; |
| 136 | { |
| 137 | const char* p = headers["Content-Length"].c_str(); |
| 138 | char* p_end {}; |
| 139 | errno = 0; |
| 140 | long val = std::strtol(p, &p_end, 10); |
| 141 | if (p_end == p // invalid argument |
| 142 | || errno == ERANGE // out of range |
| 143 | ) |
| 144 | { |
| 145 | return std::make_tuple( |
| 146 | false, "Error parsing HTTP Header 'Content-Length'", httpRequest); |
| 147 | } |
| 148 | if (val > std::numeric_limits<int>::max()) |
| 149 | { |
| 150 | return std::make_tuple( |
| 151 | false, "Error: 'Content-Length' value was above max", httpRequest); |
| 152 | } |
| 153 | if (val < std::numeric_limits<int>::min()) |
nothing calls this directly
no test coverage detected