OHTTP toy client: Allow passing in the key config as hex

This was helpful for creating encrypted test vectors.

PiperOrigin-RevId: 896670728
diff --git a/quiche/quic/masque/masque_ohttp_client.cc b/quiche/quic/masque/masque_ohttp_client.cc
index 48bc60f..540c7a7 100644
--- a/quiche/quic/masque/masque_ohttp_client.cc
+++ b/quiche/quic/masque/masque_ohttp_client.cc
@@ -238,6 +238,11 @@
 }
 
 absl::Status MasqueOhttpClient::StartKeyFetch(const std::string& url_string) {
+  std::string decoded_key_data;
+  if (absl::HexStringToBytes(url_string, &decoded_key_data) &&
+      !decoded_key_data.empty()) {
+    return HandleKeyData(decoded_key_data);
+  }
   QuicUrl url(url_string, "https");
   if (url.host().empty() && !absl::StrContains(url_string, "://")) {
     url = QuicUrl(absl::StrCat("https://", url_string));
@@ -328,8 +333,13 @@
                    << response->headers.DebugString();
   QUICHE_RETURN_IF_ERROR(CheckStatusAndContentType(
       *response, "application/ohttp-keys", std::nullopt));
+
+  return HandleKeyData(response->body);
+}
+
+absl::Status MasqueOhttpClient::HandleKeyData(const std::string& key_data) {
   absl::StatusOr<ObliviousHttpKeyConfigs> key_configs =
-      ObliviousHttpKeyConfigs::ParseConcatenatedKeys(response->body);
+      ObliviousHttpKeyConfigs::ParseConcatenatedKeys(key_data);
   if (!key_configs.ok()) {
     return absl::FailedPreconditionError(absl::StrCat(
         "Failed to parse OHTTP keys: ", key_configs.status().message()));
@@ -485,6 +495,8 @@
        per_request_config.outer_headers()) {
     request.headers[header.first] = header.second;
   }
+  QUICHE_VLOG(1) << "Sending encrypted request: "
+                 << absl::BytesToHexString(encrypted_data);
   request.body = encrypted_data;
   absl::StatusOr<RequestId> request_id =
       connection_pool_.SendRequest(request, /*mtls=*/true);
diff --git a/quiche/quic/masque/masque_ohttp_client.h b/quiche/quic/masque/masque_ohttp_client.h
index 6286ef0..6f4db6a 100644
--- a/quiche/quic/masque/masque_ohttp_client.h
+++ b/quiche/quic/masque/masque_ohttp_client.h
@@ -180,18 +180,21 @@
   // requests are complete or aborted.
   static absl::Status Run(Config config);
 
- protected:
   // From quic::MasqueConnectionPool::Visitor.
   void OnPoolResponse(quic::MasqueConnectionPool* /*pool*/,
                       RequestId request_id,
                       absl::StatusOr<Message>&& response) override;
 
+ private:
   // Fetch key from the key URL.
   absl::Status StartKeyFetch(const std::string& url_string);
 
-  // Handles the key response and starts the OHTTP request.
+  // Handles the key response.
   absl::Status HandleKeyResponse(const absl::StatusOr<Message>& response);
 
+  // Handles the key data and starts the OHTTP request.
+  absl::Status HandleKeyData(const std::string& key_data);
+
   // Sends the OHTTP request for the given URL.
   absl::Status SendOhttpRequest(
       const Config::PerRequestConfig& per_request_config);
@@ -199,7 +202,6 @@
   // Signals the client to abort.
   void Abort(absl::Status status);
 
- private:
   class QUICHE_NO_EXPORT ChunkHandler
       : public quiche::ObliviousHttpChunkHandler,
         public quiche::BinaryHttpResponse::IndeterminateLengthDecoder::