Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions packages/common/http/src/headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export class HttpHeaders {
};
} else {
this.lazyInit = () => {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
assertValidHeaders(headers);
}
this.headers = new Map<string, string[]>();
Object.keys(headers).forEach(name => {
let values: string|string[] = headers[name];
Expand Down Expand Up @@ -258,3 +261,19 @@ export class HttpHeaders {
.forEach(key => fn(this.normalizedNames.get(key)!, this.headers.get(key)!));
}
}

/**
* Verifies that the headers object has the right shape: the values
* must be either strings or arrays. Throws an error if an invalid
* header value is present.
*/
function assertValidHeaders(headers: Record<string, unknown>):
asserts headers is Record<string, string|string[]> {
for (const [key, value] of Object.entries(headers)) {
if (typeof value !== 'string' && !Array.isArray(value)) {
throw new Error(
`Unexpected value of the \`${key}\` header provided. ` +
`Expecting either a string or an array, but got: \`${value}\`.`);
}
}
}
9 changes: 9 additions & 0 deletions packages/common/http/test/client_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,5 +218,14 @@ import {toArray} from 'rxjs/operators';
{status: HttpStatusCode.InternalServerError, statusText: 'Server error'});
});
});
describe('throws an error', () => {
it('for a request with nullish header', () => {
client.request('GET', '/test', {headers: {foo: null!}}).subscribe();
expect(() => backend.expectOne('/test').request.headers.has('random-header'))
.toThrowError(
'Unexpected value of the `foo` header provided. ' +
'Expecting either a string or an array, but got: `null`.');
});
});
});
}
20 changes: 20 additions & 0 deletions packages/common/http/test/headers_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,26 @@ import {HttpHeaders} from '@angular/common/http/src/headers';

expect(headers.getAll('foo')).toEqual(['second']);
});

it('should throw an error when null is passed as header', () => {
// Note: the `strictNullChecks` set to `false` in TS config would make `null`
// valid value within the headers object, thus this test verifies this scenario.
const headers = new HttpHeaders({foo: null!});
Comment thread
markostanimirovic marked this conversation as resolved.
Outdated
expect(() => headers.get('foo'))
.toThrowError(
'Unexpected value of the `foo` header provided. ' +
'Expecting either a string or an array, but got: `null`.');
});

it('should throw an error when undefined is passed as header', () => {
// Note: the `strictNullChecks` set to `false` in TS config would make `undefined`
// valid value within the headers object, thus this test verifies this scenario.
const headers = new HttpHeaders({bar: undefined!});
expect(() => headers.get('bar'))
.toThrowError(
'Unexpected value of the `bar` header provided. ' +
'Expecting either a string or an array, but got: `undefined`.');
});
});

describe('.set()', () => {
Expand Down