Azure / Azure/azure-sdk-for-rust
Consider moving Azure header allowlists to azure_core
- Dominant language
- Rust
- Stars
- 884
- Forks
- 365
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 109
Description
## Summary
We should consider moving Azure-specific default allowed header ownership out of `sdk/core/typespec` and into `sdk/core/azure_core`, while keeping logging/debug behavior coherent across the core crate stack.
A recent change for `azure-deprecating` exposed that `typespec`, `typespec_client_core`, and `azure_core` currently split responsibility for Azure headers in a way that is conceptually inconsistent even though it works today.
## Current state
- `typespec::http::DEFAULT_ALLOWED_HEADER_NAMES` currently includes Azure-specific names such as:
- `x-ms-request-id`
- `x-ms-client-request-id`
- `x-ms-return-client-request-id`
- `ms-cv`
- `typespec::http::Headers::Debug` uses that shared allowlist directly.
- `typespec_client_core::http::policies::LoggingPolicy` clones the same shared allowlist and extends it with `LoggingOptions.additional_allowed_header_names`.
- `azure_core` owns Azure header constants and Azure-specific policy behavior such as request-id handling, instrumentation attributes, and Azure retry-header selection.
## Ideas tried / analyzed
### 1. Keep Azure-only deltas in `azure_core` and merge them in `ClientOptions::deconstruct()`
This worked for `LoggingPolicy` because `azure_core` can inject additional allowed headers into `LoggingOptions` before handing options to `typespec_client_core`.
What did **not** work: this does not affect `typespec::http::Headers::Debug` or lower-crate request/transport sanitization paths, because those use lower-crate statics directly.
### 2. Shadow `DEFAULT_ALLOWED_HEADER_NAMES` / `DEFAULT_ALLOWED_QUERY_PARAMETERS` in `azure_core`
This would let `azure_core::http` present Azure-shaped defaults publicly, similar to how `azure_core` shadows `ClientOptions`.
What did **not** work: this only changes what callers importing those names from `azure_core::http` see. It does not override lower-crate internal use sites such as `typespec::http::Headers::Debug` or `typespec_client_core::LoggingPolicy`.
### 3. Mutate the existing `LazyLock>` defaults at runtime
This was rejected.
Why it did **not** work well:
- the current public type is immutable after init;
- changing it to a mutable global would worsen API clarity;
- it would allow mutation patterns we do not want customers to rely on;
- it introduces global synchronization and mutation complexity for little benefit.
### 4. Add lower-crate extensibility while keeping Azure-defined deltas in `azure_core`
This could work as a longer-term design:
- add additive lower-crate formatting/sanitization hooks or wrappers;
- let `azure_core` provide Azure-specific deltas internally;
- keep caller-supplied `LoggingOptions.additional_*` semantics unchanged.
Tradeoff: more design and migration work, but conceptually cleaner if we want strict Azure-only ownership.
### 5. Add `azure_core`-owned formatting wrappers only
This could also work for Azure SDK-controlled diagnostics while leaving existing lower-crate `Debug` behavior alone.
Tradeoff: two formatting paths would exist, and plain lower-crate `Debug` would remain inconsistent.
## What worked best for the current change
For `azure-deprecating`, simply adding the header to the existing shared `typespec` allowlist is the smallest, lowest-impact, and most performant fix because it immediately covers:
- `Headers::Debug`
- `LoggingPolicy`
- other lower-crate sanitization paths already using the shared static
## Recommendation
Keep low-impact shared defaults like `azure-deprecating` in the existing `typespec` allowlist for now, but track a future design pass to decide whether we want to:
1. keep the current pragmatic shared-default model, or
2. add a real extensibility mechanism so Azure-specific default ownership can move to `azure_core` without fragmenting debug/logging behavior.
Any future redesign should preserve the existing contract that caller-provided `LoggingOptions.additional_allowed_header_names` and `additional_allowed_query_params` remain explicit caller additions, while SDK-defined deltas are merged internally.
Contributor guide
Research direction
Start by tracing the shared defaults in sdk/core/typespec, especially typespec::http::Headers::Debug, and the Azure integration through typespec_client_core::http::policies::LoggingPolicy and azure_core::ClientOptions::deconstruct(). Review the listed ownership and extensibility approaches, then define a design that keeps debug and logging behavior coherent while preserving caller-provided additional header and query-parameter semantics.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, backend
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100