2016-06-23 12:47:54 -04:00
|
|
|
/**
|
|
|
|
* @license
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
|
|
|
|
2016-10-03 18:27:56 -04:00
|
|
|
import {MapWrapper} from '../src/facade/collection';
|
2016-06-08 19:38:52 -04:00
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Polyfill for [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers/Headers), as
|
2015-09-17 18:36:38 -04:00
|
|
|
* specified in the [Fetch Spec](https://fetch.spec.whatwg.org/#headers-class).
|
|
|
|
*
|
|
|
|
* The only known difference between this `Headers` implementation and the spec is the
|
|
|
|
* lack of an `entries` method.
|
|
|
|
*
|
2016-10-03 18:27:56 -04:00
|
|
|
* ### Example
|
2015-09-17 18:36:38 -04:00
|
|
|
*
|
|
|
|
* ```
|
2016-04-28 20:50:03 -04:00
|
|
|
* import {Headers} from '@angular/http';
|
2015-09-17 18:36:38 -04:00
|
|
|
*
|
|
|
|
* var firstHeaders = new Headers();
|
|
|
|
* firstHeaders.append('Content-Type', 'image/jpeg');
|
|
|
|
* console.log(firstHeaders.get('Content-Type')) //'image/jpeg'
|
|
|
|
*
|
|
|
|
* // Create headers from Plain Old JavaScript Object
|
|
|
|
* var secondHeaders = new Headers({
|
|
|
|
* 'X-My-Custom-Header': 'Angular'
|
|
|
|
* });
|
|
|
|
* console.log(secondHeaders.get('X-My-Custom-Header')); //'Angular'
|
|
|
|
*
|
|
|
|
* var thirdHeaders = new Headers(secondHeaders);
|
|
|
|
* console.log(thirdHeaders.get('X-My-Custom-Header')); //'Angular'
|
|
|
|
* ```
|
2016-06-27 15:27:23 -04:00
|
|
|
*
|
|
|
|
* @experimental
|
2015-06-09 18:18:57 -04:00
|
|
|
*/
|
2015-04-29 02:07:55 -04:00
|
|
|
export class Headers {
|
2016-10-03 18:27:56 -04:00
|
|
|
/** @internal header names are lower case */
|
|
|
|
_headers: Map<string, string[]> = new Map();
|
|
|
|
/** @internal map lower case names to actual names */
|
|
|
|
_normalizedNames: Map<string, string> = new Map();
|
|
|
|
|
|
|
|
// TODO(vicb): any -> string|string[]
|
|
|
|
constructor(headers?: Headers|{[name: string]: any}) {
|
|
|
|
if (!headers) {
|
2015-04-29 02:07:55 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-03 18:27:56 -04:00
|
|
|
if (headers instanceof Headers) {
|
2016-10-05 20:05:50 -04:00
|
|
|
headers._headers.forEach((values: string[], name: string) => {
|
|
|
|
values.forEach(value => this.append(name, value));
|
2016-10-03 18:27:56 -04:00
|
|
|
});
|
2015-10-08 19:01:18 -04:00
|
|
|
return;
|
2015-04-29 02:07:55 -04:00
|
|
|
}
|
2015-10-08 19:01:18 -04:00
|
|
|
|
2016-10-03 18:27:56 -04:00
|
|
|
Object.keys(headers).forEach((name: string) => {
|
2016-10-05 20:05:50 -04:00
|
|
|
const values: string[] = Array.isArray(headers[name]) ? headers[name] : [headers[name]];
|
|
|
|
this.delete(name);
|
|
|
|
values.forEach(value => this.append(name, value));
|
2016-02-01 20:05:50 -05:00
|
|
|
});
|
2015-04-29 02:07:55 -04:00
|
|
|
}
|
|
|
|
|
2015-11-19 20:51:00 -05:00
|
|
|
/**
|
|
|
|
* Returns a new Headers instance from the given DOMString of Response Headers
|
|
|
|
*/
|
|
|
|
static fromResponseHeaderString(headersString: string): Headers {
|
2016-10-03 18:27:56 -04:00
|
|
|
const headers = new Headers();
|
2016-07-29 01:19:49 -04:00
|
|
|
|
|
|
|
headersString.split('\n').forEach(line => {
|
|
|
|
const index = line.indexOf(':');
|
|
|
|
if (index > 0) {
|
2016-10-03 18:27:56 -04:00
|
|
|
const name = line.slice(0, index);
|
|
|
|
const value = line.slice(index + 1).trim();
|
|
|
|
headers.set(name, value);
|
2016-07-29 01:19:49 -04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return headers;
|
2015-11-19 20:51:00 -05:00
|
|
|
}
|
|
|
|
|
2015-06-24 03:27:07 -04:00
|
|
|
/**
|
|
|
|
* Appends a header to existing list of header values for a given header name.
|
|
|
|
*/
|
2015-04-29 02:07:55 -04:00
|
|
|
append(name: string, value: string): void {
|
2016-10-03 18:27:56 -04:00
|
|
|
const values = this.getAll(name);
|
2016-10-05 19:36:42 -04:00
|
|
|
|
|
|
|
if (values === null) {
|
|
|
|
this.set(name, value);
|
|
|
|
} else {
|
|
|
|
values.push(value);
|
|
|
|
}
|
2015-04-29 02:07:55 -04:00
|
|
|
}
|
|
|
|
|
2015-06-24 03:27:07 -04:00
|
|
|
/**
|
|
|
|
* Deletes all header values for the given name.
|
|
|
|
*/
|
2016-10-03 18:27:56 -04:00
|
|
|
delete (name: string): void {
|
|
|
|
const lcName = name.toLowerCase();
|
|
|
|
this._normalizedNames.delete(lcName);
|
|
|
|
this._headers.delete(lcName);
|
|
|
|
}
|
2015-04-29 02:07:55 -04:00
|
|
|
|
2015-10-07 17:56:18 -04:00
|
|
|
forEach(fn: (values: string[], name: string, headers: Map<string, string[]>) => void): void {
|
2016-10-03 18:27:56 -04:00
|
|
|
this._headers.forEach(
|
|
|
|
(values, lcName) => fn(values, this._normalizedNames.get(lcName), this._headers));
|
2015-09-17 18:36:38 -04:00
|
|
|
}
|
2015-04-29 02:07:55 -04:00
|
|
|
|
2015-06-24 03:27:07 -04:00
|
|
|
/**
|
|
|
|
* Returns first header that matches given name.
|
|
|
|
*/
|
2016-10-03 18:27:56 -04:00
|
|
|
get(name: string): string {
|
|
|
|
const values = this.getAll(name);
|
|
|
|
|
|
|
|
if (values === null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return values.length > 0 ? values[0] : null;
|
|
|
|
}
|
2015-04-29 02:07:55 -04:00
|
|
|
|
2015-06-24 03:27:07 -04:00
|
|
|
/**
|
2016-10-03 18:27:56 -04:00
|
|
|
* Checks for existence of header by given name.
|
2015-06-24 03:27:07 -04:00
|
|
|
*/
|
2016-10-03 18:27:56 -04:00
|
|
|
has(name: string): boolean { return this._headers.has(name.toLowerCase()); }
|
2015-04-29 02:07:55 -04:00
|
|
|
|
2015-06-24 03:27:07 -04:00
|
|
|
/**
|
2016-10-03 18:27:56 -04:00
|
|
|
* Returns the names of the headers
|
2015-06-24 03:27:07 -04:00
|
|
|
*/
|
2016-10-03 18:27:56 -04:00
|
|
|
keys(): string[] { return MapWrapper.values(this._normalizedNames); }
|
2015-04-29 02:07:55 -04:00
|
|
|
|
2015-06-24 03:27:07 -04:00
|
|
|
/**
|
|
|
|
* Sets or overrides header value for given name.
|
|
|
|
*/
|
2016-10-03 18:27:56 -04:00
|
|
|
set(name: string, value: string|string[]): void {
|
2016-10-05 20:05:50 -04:00
|
|
|
if (Array.isArray(value)) {
|
|
|
|
if (value.length) {
|
|
|
|
this._headers.set(name.toLowerCase(), [value.join(',')]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this._headers.set(name.toLowerCase(), [value]);
|
|
|
|
}
|
2016-10-03 18:27:56 -04:00
|
|
|
this.mayBeSetNormalizedName(name);
|
2015-04-29 02:07:55 -04:00
|
|
|
}
|
|
|
|
|
2015-06-24 03:27:07 -04:00
|
|
|
/**
|
|
|
|
* Returns values of all headers.
|
|
|
|
*/
|
2016-10-03 18:27:56 -04:00
|
|
|
values(): string[][] { return MapWrapper.values(this._headers); }
|
2015-04-29 02:07:55 -04:00
|
|
|
|
2015-12-09 23:56:32 -05:00
|
|
|
/**
|
|
|
|
* Returns string of all headers.
|
|
|
|
*/
|
2016-10-03 18:27:56 -04:00
|
|
|
// TODO(vicb): returns {[name: string]: string[]}
|
|
|
|
toJSON(): {[name: string]: any} {
|
|
|
|
const serialized: {[name: string]: string[]} = {};
|
|
|
|
|
|
|
|
this._headers.forEach((values: string[], name: string) => {
|
|
|
|
const split: string[] = [];
|
|
|
|
values.forEach(v => split.push(...v.split(',')));
|
|
|
|
serialized[this._normalizedNames.get(name)] = split;
|
2016-01-27 02:24:50 -05:00
|
|
|
});
|
2016-10-03 18:27:56 -04:00
|
|
|
|
|
|
|
return serialized;
|
2016-01-27 02:24:50 -05:00
|
|
|
}
|
2015-12-09 23:56:32 -05:00
|
|
|
|
2015-06-24 03:27:07 -04:00
|
|
|
/**
|
|
|
|
* Returns list of header values for a given name.
|
|
|
|
*/
|
2016-10-03 18:27:56 -04:00
|
|
|
getAll(name: string): string[] {
|
|
|
|
return this.has(name) ? this._headers.get(name.toLowerCase()) : null;
|
2015-06-19 15:14:12 -04:00
|
|
|
}
|
2015-04-29 02:07:55 -04:00
|
|
|
|
2015-06-24 03:27:07 -04:00
|
|
|
/**
|
|
|
|
* This method is not implemented.
|
|
|
|
*/
|
2016-08-25 03:50:16 -04:00
|
|
|
entries() { throw new Error('"entries" method is not implemented on Headers class'); }
|
2016-07-26 00:30:43 -04:00
|
|
|
|
2016-10-03 18:27:56 -04:00
|
|
|
private mayBeSetNormalizedName(name: string): void {
|
|
|
|
const lcName = name.toLowerCase();
|
|
|
|
|
|
|
|
if (!this._normalizedNames.has(lcName)) {
|
|
|
|
this._normalizedNames.set(lcName, name);
|
|
|
|
}
|
|
|
|
}
|
2016-07-26 00:30:43 -04:00
|
|
|
}
|