Azure / Azure/azure-sdk-for-rust

Consider moving Azure header allowlists to azure_core

Open
#4,899 1 comment 1 reaction 0 assignees View on GitHub
Azure.Core Client
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.