Skip to content

Commit 95bc7e2

Browse files
danilobassi8thePunderWoman
authored andcommitted
fix(http): prevent headers from throwing an error when initializing numerical values (#49379)
Some libraries could use numbers in headers. this fix prevents Angular from throwing an error by casting those numerical values into strings. Fixes #49353 PR Close #49379
1 parent 4721c48 commit 95bc7e2

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

goldens/public-api/common/http/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1782,7 +1782,7 @@ export class HttpHeaderResponse extends HttpResponseBase {
17821782
// @public
17831783
export class HttpHeaders {
17841784
constructor(headers?: string | {
1785-
[name: string]: string | string[];
1785+
[name: string]: string | number | (string | number)[];
17861786
});
17871787
append(name: string, value: string | string[]): HttpHeaders;
17881788
delete(name: string, value?: string | string[]): HttpHeaders;

packages/common/http/src/headers.ts

100755100644
Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class HttpHeaders {
4545

4646
/** Constructs a new HTTP header object with the given values.*/
4747

48-
constructor(headers?: string|{[name: string]: string | string[]}) {
48+
constructor(headers?: string|{[name: string]: string | number | (string | number)[]}) {
4949
if (!headers) {
5050
this.headers = new Map<string, string[]>();
5151
} else if (typeof headers === 'string') {
@@ -72,14 +72,20 @@ export class HttpHeaders {
7272
assertValidHeaders(headers);
7373
}
7474
this.headers = new Map<string, string[]>();
75-
Object.keys(headers).forEach(name => {
76-
let values: string|string[] = headers[name];
77-
const key = name.toLowerCase();
75+
Object.entries(headers).forEach(([name, values]) => {
76+
let headerValues: string[];
77+
7878
if (typeof values === 'string') {
79-
values = [values];
79+
headerValues = [values];
80+
} else if (typeof values === 'number') {
81+
headerValues = [values.toString()];
82+
} else {
83+
headerValues = values.map((value) => value.toString());
8084
}
81-
if (values.length > 0) {
82-
this.headers.set(key, values);
85+
86+
if (headerValues.length > 0) {
87+
const key = name.toLowerCase();
88+
this.headers.set(key, headerValues);
8389
this.maybeSetNormalizedName(name, key);
8490
}
8591
});
@@ -264,16 +270,16 @@ export class HttpHeaders {
264270

265271
/**
266272
* Verifies that the headers object has the right shape: the values
267-
* must be either strings or arrays. Throws an error if an invalid
273+
* must be either strings, numbers or arrays. Throws an error if an invalid
268274
* header value is present.
269275
*/
270276
function assertValidHeaders(headers: Record<string, unknown>):
271-
asserts headers is Record<string, string|string[]> {
277+
asserts headers is Record<string, string|string[]|number|number[]> {
272278
for (const [key, value] of Object.entries(headers)) {
273-
if (typeof value !== 'string' && !Array.isArray(value)) {
279+
if (!(typeof value === 'string' || typeof value === 'number') && !Array.isArray(value)) {
274280
throw new Error(
275281
`Unexpected value of the \`${key}\` header provided. ` +
276-
`Expecting either a string or an array, but got: \`${value}\`.`);
282+
`Expecting either a string, a number or an array, but got: \`${value}\`.`);
277283
}
278284
}
279285
}

packages/common/http/test/client_spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ import {toArray} from 'rxjs/operators';
224224
expect(() => backend.expectOne('/test').request.headers.has('random-header'))
225225
.toThrowError(
226226
'Unexpected value of the `foo` header provided. ' +
227-
'Expecting either a string or an array, but got: `null`.');
227+
'Expecting either a string, a number or an array, but got: `null`.');
228228
});
229229
});
230230
});

packages/common/http/test/headers_spec.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import {HttpHeaders} from '@angular/common/http/src/headers';
5454
expect(() => headers.get('foo'))
5555
.toThrowError(
5656
'Unexpected value of the `foo` header provided. ' +
57-
'Expecting either a string or an array, but got: `null`.');
57+
'Expecting either a string, a number or an array, but got: `null`.');
5858
});
5959

6060
it('should throw an error when undefined is passed as header', () => {
@@ -64,7 +64,25 @@ import {HttpHeaders} from '@angular/common/http/src/headers';
6464
expect(() => headers.get('bar'))
6565
.toThrowError(
6666
'Unexpected value of the `bar` header provided. ' +
67-
'Expecting either a string or an array, but got: `undefined`.');
67+
'Expecting either a string, a number or an array, but got: `undefined`.');
68+
});
69+
70+
it('should not throw an error when a number is passed as header', () => {
71+
const headers = new HttpHeaders({'Content-Length': 100});
72+
const value = headers.get('Content-Length');
73+
expect(value).toEqual('100');
74+
});
75+
76+
it('should not throw an error when a numerical array is passed as header', () => {
77+
const headers = new HttpHeaders({'some-key': [123]});
78+
const value = headers.get('some-key');
79+
expect(value).toEqual('123');
80+
});
81+
82+
it('should not throw an error when an array of strings is passed as header', () => {
83+
const headers = new HttpHeaders({'some-key': ['myValue']});
84+
const value = headers.get('some-key');
85+
expect(value).toEqual('myValue');
6886
});
6987
});
7088

0 commit comments

Comments
 (0)