docs: add docs for header case presevation (#10654)

* docs: update readme with documented work around

* docs: update docs site with documented work around
This commit is contained in:
Jay 2026-04-05 21:00:34 +02:00 committed by GitHub
parent 173efa3b8d
commit e52994ff40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 85 additions and 9 deletions

View File

@ -1580,6 +1580,38 @@ for (const [header, value] of headers) {
// baz 3
```
### Preserving a specific header case
Header names are case-insensitive, but `AxiosHeaders` keeps the case of the first matching key it sees.
If you need a specific case for non-standard case-sensitive servers, define a case preset with `undefined` and then set the value later:
```js
const api = axios.create();
api.defaults.headers.common = {
'content-type': undefined,
accept: undefined,
};
await api.put(url, data, {
headers: {
'Content-Type': 'application/octet-stream',
Accept: 'application/json',
},
});
```
You can also compose the same behavior with `AxiosHeaders.concat`:
```js
const headers = axios.AxiosHeaders.concat(
{ 'content-type': undefined },
{ 'Content-Type': 'application/octet-stream' }
);
await axios.put(url, data, { headers });
```
### new AxiosHeaders(headers?)
Constructs a new `AxiosHeaders` instance.

View File

@ -45,6 +45,8 @@ The rewrite argument controls the overwriting behaviour:
The option can also accept a user-defined function that determines whether the value should be overwritten or not. The function receives the current value, header name, and the headers object as arguments.
`AxiosHeaders` keeps the case of the first matching key it sees. You can use this to preserve specific header casing by seeding a key with `undefined` and then setting values later. See [Preserving a specific header case](/pages/advanced/headers#preserving-a-specific-header-case).
## Get
The `get` method is used to retrieve the value of a header. The method can be called with a single header name, an optional matcher, or a parser. The matcher is defaulted to `true`. The parser can be a regular expression that is used to extract the value from the header.
@ -58,26 +60,26 @@ An example of some of the possible usages of the `get` method is shown below:
```js
const headers = new AxiosHeaders({
"Content-Type": "multipart/form-data; boundary=Asrf456BGe4h",
'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h',
});
console.log(headers.get("Content-Type"));
console.log(headers.get('Content-Type'));
// multipart/form-data; boundary=Asrf456BGe4h
console.log(headers.get("Content-Type", true)); // parse key-value pairs from a string separated with \s,;= delimiters:
console.log(headers.get('Content-Type', true)); // parse key-value pairs from a string separated with \s,;= delimiters:
// [Object: null prototype] {
// 'multipart/form-data': undefined,
// boundary: 'Asrf456BGe4h'
// }
console.log(
headers.get("Content-Type", (value, name, headers) => {
return String(value).replace(/a/g, "ZZZ");
headers.get('Content-Type', (value, name, headers) => {
return String(value).replace(/a/g, 'ZZZ');
})
);
// multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h
console.log(headers.get("Content-Type", /boundary=(\w+)/)?.[0]);
console.log(headers.get('Content-Type', /boundary=(\w+)/)?.[0]);
// boundary=Asrf456BGe4h
```
@ -123,11 +125,11 @@ If the headers object was changed directly, it can cause duplicates with the sam
```js
const headers = new AxiosHeaders({
foo: "1",
foo: '1',
});
headers.Foo = "2";
headers.FOO = "3";
headers.Foo = '2';
headers.FOO = '3';
console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' }
console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' }
@ -142,6 +144,15 @@ Returns `this` for chaining.
Merges the instance with targets into a new AxiosHeaders instance. If the target is a string, it will be parsed as RAW HTTP headers. If the target is an AxiosHeaders instance, it will be merged with the current instance.
This is useful for case presets when composing headers. For example:
```js
const headers = AxiosHeaders.concat(
{ 'content-type': undefined },
{ 'Content-Type': 'application/octet-stream' }
);
```
```js
concat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;
```

View File

@ -79,6 +79,39 @@ const api = axios.create({
});
```
## Preserving a specific header case
Axios header names are case-insensitive, but `AxiosHeaders` keeps the case of the first matching key it sees. If you need a specific case for a server with non-standard case-sensitive behavior, define a case preset in defaults and then set values as usual.
```js
const api = axios.create();
api.defaults.headers.common = {
'content-type': undefined,
accept: undefined,
};
await api.put(url, data, {
headers: {
'Content-Type': 'application/octet-stream',
Accept: 'application/json',
},
});
```
You can also do this with `AxiosHeaders` directly when composing headers:
```js
import axios, { AxiosHeaders } from 'axios';
const headers = AxiosHeaders.concat(
{ 'content-type': undefined },
{ 'Content-Type': 'application/octet-stream' }
);
await axios.put(url, data, { headers });
```
## Setting headers in an interceptor
Interceptors are the right place to attach dynamic headers like auth tokens, because the token may not be available when the instance is first created: