feat(storage): global custom header configuration - #6458
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for global custom headers across both HTTP and gRPC clients in the GAX internal library and the Storage client. It adds a with_custom_header builder method to configure client-wide default headers, which are sanitized to prevent overwriting reserved system headers. The review feedback highlights an issue in make_headers where iterating and inserting request-level custom headers individually discards multi-valued headers, and suggests a fix to correctly overwrite global headers while preserving multi-valued request-level headers.
- Add global custom header configuration via ClientBuilder::with_custom_header - Align HTTP custom header sanitization keys with gRPC to fully protect reserved system headers - Refactor gax-internal gRPC and HTTP layers to consistently handle extension-based configuration - Add comprehensive integration and unit tests covering global vs request-level precedence and system header protections
4aa8fc2 to
8198dfd
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6458 +/- ##
==========================================
- Coverage 96.39% 96.38% -0.01%
==========================================
Files 299 300 +1
Lines 84462 84585 +123
==========================================
+ Hits 81414 81525 +111
- Misses 3048 3060 +12 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| fn sanitize_custom_headers(headers: &mut http::HeaderMap) { | ||
| for key in [ | ||
| http::header::USER_AGENT, | ||
| http::header::AUTHORIZATION, | ||
| X_GOOG_API_KEY, | ||
| X_GOOG_USER_PROJECT, | ||
| X_GOOG_REQUEST_PARAMS, | ||
| X_GOOG_API_CLIENT, | ||
| ] { | ||
| headers.remove(key); | ||
| } | ||
| } |
There was a problem hiding this comment.
Can this be refactored with grpc_helpers.rs:91-100?
There was a problem hiding this comment.
Done.
This function is now shared between http and grpc. It is in a new module called "src/gax-internal/src/headers.rs".
…tants across transports
…e_custom_headers and drop redundant test
… doc comment in options.rs
DD: go/rust-sdk-custom-header
Part of #5997
This PR introduces client-level (global) custom header configuration for Google Cloud Storage, while ensuring strict behavioral and architectural parity between HTTP/gRPC transports and global/request-level configuration.
1. Storage Client API
ClientBuilder::with_custom_header(mut self, key: K, value: V) -> Selfto configure client-wide custom headers applied to every outgoing request.authorization,user-agent,x-goog-user-project,x-goog-request-params,x-goog-api-client,x-goog-api-key) always take precedence and strip conflicting custom header keys at both global and request scopes.2. Parity between HTTP and gRPC
ReqwestClient) or gRPC (grpc_helpers::make_headers).3. Parity between Global-level and Request-level Custom Headers
ClientBuilder::with_custom_headershares the identical function signature, generic bounds, and error ergonomics as the existingRequestOptionsBuilder::with_custom_header.ExtensionsArchitecture: Both layers use the sharedExtensionscontainer holding anhttp::HeaderMap(ClientConfig.extensionsfor global,RequestOptions.extensionsfor request-level). This enables transport layers to extract and unpack configuration uniformly without requiring dedicated struct fields.4. Testing
make_headers_precedence_request_over_global).ClientBuilder::with_custom_headervalidating public documentation, usage patterns, and compiler checks.