Skip to content

Latest commit

 

History

History
56 lines (37 loc) · 2.47 KB

File metadata and controls

56 lines (37 loc) · 2.47 KB

HCR062

Prefer per-request headers over mutating DefaultRequestHeaders.

Why

HttpClient.DefaultRequestHeaders applies to every request sent by that client. Mutating it for per-request data can leak tenant, user, authorization, correlation, or feature headers across requests when the client is reused.

Bad

client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", accessToken);

return client.GetAsync("/orders", cancellationToken);
client.DefaultRequestHeaders.Add("X-Tenant", tenantId);
return client.PostAsync("/orders", content, cancellationToken);

Better

using var request = new HttpRequestMessage(HttpMethod.Get, "/orders");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

return client.SendAsync(request, cancellationToken);
using var request = new HttpRequestMessage(HttpMethod.Post, "/orders")
{
    Content = content
};
request.Headers.Add("X-Tenant", tenantId);

return client.SendAsync(request, cancellationToken);

Current Detection

The implementation reports visible mutations under a real System.Net.Http.HttpClient.DefaultRequestHeaders receiver. It catches direct header mutations such as Add(...), TryAddWithoutValidation(...), Remove(...), Clear(...), and ParseAdd(...), nested collection mutations such as client.DefaultRequestHeaders.Accept.Add(...), and assignments such as client.DefaultRequestHeaders.Authorization = ....

The receiver is validated with Roslyn type information when available, with syntactic fallback for unresolved snippets that visibly declare an HttpClient receiver. Reads such as client.DefaultRequestHeaders.Contains(...) are skipped, request-scoped HttpRequestMessage.Headers mutations are skipped, and resolved custom HttpClient lookalikes are skipped.

Suppression

Suppress only for process-wide static headers that are intentionally constant for the entire lifetime of the client, such as a fixed product header. Prefer setting those once during client construction or typed-client initialization.

References