get(ConfigKey::STORAGE_LIMIT_BYTES) * 2; $body = file_get_contents('php://input', length: $limit + 1); if ($body === false) { return new ApiError(500, "Failed to read request body."); } if (strlen($body) > $limit) { return new ApiError(413, "Request body exceeds maximum allowed size."); } $encodingHeader = $_SERVER['HTTP_CONTENT_ENCODING'] ?? ''; if ($encodingHeader) { $encodingSteps = explode(',', $encodingHeader); if (count($encodingSteps) > static::MAX_ENCODING_STEPS) { return new ApiError(400, "Too many Content-Encoding steps."); } foreach (array_reverse($encodingSteps) as $step) { switch (trim(strtolower($step))) { case "deflate": $body = @gzinflate($body, $limit); break; case "x-gzip": case "gzip": $body = @gzdecode($body, $limit); break; default: return new ApiError(415, "Unsupported Content-Encoding: " . htmlspecialchars($step)); } if ($body === false) { return new ApiError(400, "Failed to decode request body with encoding: " . htmlspecialchars($step)); } } } $contentTypeHeader = $_SERVER['CONTENT_TYPE'] ?? ''; if ($pos = strpos($contentTypeHeader, ';')) { $contentTypeHeader = substr($contentTypeHeader, 0, $pos); } switch ($contentTypeHeader) { case "application/x-www-form-urlencoded": parse_str($body, $data); break; case "application/json": $data = @json_decode($body, true); if (!is_array($data)) { return new ApiError(400, "Failed to parse JSON body."); } break; default: return new ApiError(415, "Unsupported Content-Type: " . htmlspecialchars($contentTypeHeader)); } return $data; } }