Fix OHTTP test client status checks This CL makes sure the chunked mode checks the status, and removes a redundant status check for the gateway status. This CL also logs the body on unexpected encapsulated status codes. PiperOrigin-RevId: 923512873
diff --git a/quiche/quic/masque/masque_ohttp_client.cc b/quiche/quic/masque/masque_ohttp_client.cc index 0c3e4e9..367ad63 100644 --- a/quiche/quic/masque/masque_ohttp_client.cc +++ b/quiche/quic/masque/masque_ohttp_client.cc
@@ -20,7 +20,6 @@ #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" #include "absl/strings/match.h" -#include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_replace.h" #include "absl/strings/str_split.h" @@ -535,21 +534,12 @@ absl::Status MasqueOhttpClient::CheckStatusAndContentType( const Message& response, const std::string& content_type, std::optional<uint16_t> expected_status_code) { - auto status_it = response.headers.find(":status"); - if (status_it == response.headers.end()) { - return absl::InvalidArgumentError( - absl::StrCat("No :status header in ", content_type, " response.")); - } - int status_code; - if (!absl::SimpleAtoi(status_it->second, &status_code)) { - return absl::InvalidArgumentError( - absl::StrCat("Failed to parse ", content_type, " status code.")); - } + int16_t status_code = MasqueConnectionPool::GetStatusCode(response); if (expected_status_code.has_value()) { if (status_code != *expected_status_code) { return absl::InvalidArgumentError(absl::StrCat( - "Unexpected status in ", content_type, " response: ", status_code, - " (expected ", *expected_status_code, ")")); + "Unexpected status code in ", content_type, + " response: ", status_code, ", expected: ", *expected_status_code)); } if (*expected_status_code < 200 || *expected_status_code >= 300) { // If we expect a failure status code, skip the content-type check. @@ -557,9 +547,8 @@ } } else { if (status_code < 200 || status_code >= 300) { - return absl::InvalidArgumentError( - absl::StrCat("Unexpected status in ", content_type, - " response: ", status_it->second)); + return absl::InvalidArgumentError(absl::StrCat( + "Bad status code in ", content_type, " response: ", status_code)); } } auto content_type_it = response.headers.find("content-type"); @@ -580,6 +569,28 @@ return absl::OkStatus(); } +absl::Status MasqueOhttpClient::CheckEncapsulatedStatus( + const Message& response, std::optional<uint16_t> expected_status_code) { + int16_t encapsulated_status_code = + MasqueConnectionPool::GetStatusCode(response); + absl::Status status = absl::OkStatus(); + if (expected_status_code.has_value()) { + if (encapsulated_status_code != *expected_status_code) { + status = absl::InvalidArgumentError(absl::StrCat( + "Unexpected encapsulated status code: ", encapsulated_status_code, + ", expected: ", *expected_status_code)); + } + } else if (encapsulated_status_code < 200 || + encapsulated_status_code >= 300) { + status = absl::InvalidArgumentError(absl::StrCat( + "Bad encapsulated status code: ", encapsulated_status_code)); + } + if (!status.ok() && !response.body.empty()) { + QUICHE_LOG(INFO) << ENDPOINT << "Body:" << std::endl << response.body; + } + return status; +} + absl::Status MasqueOhttpClient::HandleKeyResponse( const absl::StatusOr<Message>& response) { key_fetch_request_id_ = std::nullopt; @@ -915,19 +926,6 @@ return ProcessEncapsulatedResponse(request_id, *response, it->second.per_request_config); } - int16_t gateway_status_code = MasqueConnectionPool::GetStatusCode(*response); - if (it->second.per_request_config.expected_gateway_status_code() - .has_value()) { - if (gateway_status_code != - *it->second.per_request_config.expected_gateway_status_code()) { - return absl::InvalidArgumentError(absl::StrCat( - "Unexpected gateway status code: ", gateway_status_code, " != ", - *it->second.per_request_config.expected_gateway_status_code())); - } - } else if (gateway_status_code < 200 || gateway_status_code >= 300) { - return absl::InvalidArgumentError( - absl::StrCat("Bad gateway status code: ", gateway_status_code)); - } std::string content_type = it->second.per_request_config.num_ohttp_chunks() > 0 ? "message/ohttp-chunked-res" @@ -1018,20 +1016,8 @@ response.body[response.body.size() - 1] != '\n') { std::cout << std::endl; } - int16_t encapsulated_status_code = - MasqueConnectionPool::GetStatusCode(response); - if (per_request_config.expected_encapsulated_status_code().has_value()) { - if (encapsulated_status_code != - *per_request_config.expected_encapsulated_status_code()) { - return absl::InvalidArgumentError(absl::StrCat( - "Unexpected encapsulated status code: ", encapsulated_status_code, - " != ", *per_request_config.expected_encapsulated_status_code())); - } - } else if (encapsulated_status_code < 200 || - encapsulated_status_code >= 300) { - return absl::InvalidArgumentError(absl::StrCat( - "Bad encapsulated status code: ", encapsulated_status_code)); - } + QUICHE_RETURN_IF_ERROR(CheckEncapsulatedStatus( + response, per_request_config.expected_encapsulated_status_code())); if (const auto& callback = per_request_config.encapsulated_response_body_callback(); callback) { @@ -1108,6 +1094,17 @@ if (end_stream) { Message response = std::move(*pending_request.chunk_handler).ExtractResponse(); + status = CheckEncapsulatedStatus( + response, + pending_request.per_request_config.expected_encapsulated_status_code()); + if (!status.ok()) { + Abort(status); + if (response_visitor_) { + response_visitor_->OnError(request_id, status); + } + return; + } + if (const auto& callback = pending_request.per_request_config .encapsulated_response_body_callback(); callback) { @@ -1268,8 +1265,7 @@ return absl::OkStatus(); } absl::Status MasqueOhttpClient::ChunkHandler::OnFinalResponseHeadersDone() { - QUICHE_LOG(INFO) << ENDPOINT - << "Received incremental OHTTP response headers: " + QUICHE_LOG(INFO) << ENDPOINT << "Received chunked OHTTP response headers: " << response_.headers.DebugString(); if (handle_gzip_response_) { auto it = response_.headers.find("content-encoding");
diff --git a/quiche/quic/masque/masque_ohttp_client.h b/quiche/quic/masque/masque_ohttp_client.h index 78497d3..d84dc75 100644 --- a/quiche/quic/masque/masque_ohttp_client.h +++ b/quiche/quic/masque/masque_ohttp_client.h
@@ -393,6 +393,8 @@ absl::Status CheckStatusAndContentType( const Message& response, const std::string& content_type, std::optional<uint16_t> expected_status_code); + absl::Status CheckEncapsulatedStatus( + const Message& response, std::optional<uint16_t> expected_status_code); Config config_; const std::string info_;