Skip to content

feat(storage): global custom header configuration - #6458

Merged
xlai20 merged 12 commits into
googleapis:mainfrom
xlai20:custom-headers-global
Aug 21, 2026
Merged

feat(storage): global custom header configuration#6458
xlai20 merged 12 commits into
googleapis:mainfrom
xlai20:custom-headers-global

Conversation

@xlai20

@xlai20 xlai20 commented Aug 19, 2026

Copy link
Copy Markdown
Member

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

  • Public API Added: Introduced ClientBuilder::with_custom_header(mut self, key: K, value: V) -> Self to configure client-wide custom headers applied to every outgoing request.
  • Precedence Rules:
    • Request-level overrides Global-level: When the same header key is configured at both levels, the request-specific header explicitly overwrites the global header.
    • System-level overrides Custom: Reserved system headers (e.g., 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

  • Aligned Sanitization: Harmonized HTTP and gRPC transport sanitization to scrub the reserved system keys.
  • Uniform Behavior: Ensured identical merging order and sanitization rules are enforced whether a request executes via HTTP (ReqwestClient) or gRPC (grpc_helpers::make_headers).

3. Parity between Global-level and Request-level Custom Headers

  • Public API Parity: ClientBuilder::with_custom_header shares the identical function signature, generic bounds, and error ergonomics as the existing RequestOptionsBuilder::with_custom_header.
  • Internal Extensions Architecture: Both layers use the shared Extensions container holding an http::HeaderMap (ClientConfig.extensions for global, RequestOptions.extensions for request-level). This enables transport layers to extract and unpack configuration uniformly without requiring dedicated struct fields.

4. Testing

  • Isolated & Integration Tests: Added unit tests verifying isolated global headers, isolated request-level headers, and global vs. request precedence (make_headers_precedence_request_over_global).
  • System Precedence Tests: Added unit tests verifying that system keys strip conflicting custom keys across both populated and empty parameter states.
  • Documentation Tests: Included full doctests for ClientBuilder::with_custom_header validating public documentation, usage patterns, and compiler checks.

@product-auto-label product-auto-label Bot added the api: storage Issues related to the Cloud Storage API. label Aug 19, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/gax-internal/src/grpc/grpc_helpers.rs
xlai20 added 4 commits August 19, 2026 03:42
- 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
@xlai20
xlai20 force-pushed the custom-headers-global branch from 4aa8fc2 to 8198dfd Compare August 19, 2026 03:44
@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.73684% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.38%. Comparing base (9858309) to head (b3c9bce).

Files with missing lines Patch % Lines
src/gax-internal/src/grpc/grpc_helpers.rs 94.50% 5 Missing ⚠️
src/gax-internal/src/grpc.rs 84.21% 3 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@xlai20
xlai20 marked this pull request as ready for review August 19, 2026 04:04
@xlai20
xlai20 requested review from a team as code owners August 19, 2026 04:04
Comment thread src/gax-internal/src/http.rs Outdated
Comment on lines +68 to +79
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);
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be refactored with grpc_helpers.rs:91-100?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

This function is now shared between http and grpc. It is in a new module called "src/gax-internal/src/headers.rs".

Comment thread src/storage/src/storage/client.rs
Comment thread src/gax-internal/src/grpc/grpc_helpers.rs Outdated
Comment thread src/gax-internal/src/options.rs
@xlai20
xlai20 merged commit 1da1b78 into googleapis:main Aug 21, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: storage Issues related to the Cloud Storage API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants