6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
- import { ListWrapper , MapWrapper , StringMapWrapper , isListLikeIterable , iterateListLike } from '../src/facade/collection' ;
9
+ import { MapWrapper } from '../src/facade/collection' ;
10
10
11
11
/**
12
12
* Polyfill for [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers/Headers), as
@@ -15,7 +15,7 @@ import {ListWrapper, MapWrapper, StringMapWrapper, isListLikeIterable, iterateLi
15
15
* The only known difference between this `Headers` implementation and the spec is the
16
16
* lack of an `entries` method.
17
17
*
18
- * ### Example ([live demo](http://plnkr.co/edit/MTdwT6?p=preview))
18
+ * ### Example
19
19
*
20
20
* ```
21
21
* import {Headers} from '@angular/http';
@@ -37,38 +37,46 @@ import {ListWrapper, MapWrapper, StringMapWrapper, isListLikeIterable, iterateLi
37
37
* @experimental
38
38
*/
39
39
export class Headers {
40
- /** @internal */
41
- _headersMap : Map < string , string [ ] > ;
42
- constructor ( headers ?: Headers | { [ key : string ] : any } ) {
43
- if ( headers instanceof Headers ) {
44
- this . _headersMap = new Map < string , string [ ] > ( ( < Headers > headers ) . _headersMap ) ;
40
+ /** @internal header names are lower case */
41
+ _headers : Map < string , string [ ] > = new Map ( ) ;
42
+ /** @internal map lower case names to actual names */
43
+ _normalizedNames : Map < string , string > = new Map ( ) ;
44
+
45
+ // TODO(vicb): any -> string|string[]
46
+ constructor ( headers ?: Headers | { [ name : string ] : any } ) {
47
+ if ( ! headers ) {
45
48
return ;
46
49
}
47
50
48
- this . _headersMap = new Map < string , string [ ] > ( ) ;
49
-
50
- if ( ! headers ) {
51
+ if ( headers instanceof Headers ) {
52
+ headers . _headers . forEach ( ( value : string [ ] , name : string ) => {
53
+ const lcName = name . toLowerCase ( ) ;
54
+ this . _headers . set ( lcName , value ) ;
55
+ this . mayBeSetNormalizedName ( name ) ;
56
+ } ) ;
51
57
return ;
52
58
}
53
59
54
- // headers instanceof StringMap
55
- StringMapWrapper . forEach ( headers , ( v : any , k : string ) => {
56
- this . _headersMap . set ( normalize ( k ) , isListLikeIterable ( v ) ? v : [ v ] ) ;
60
+ Object . keys ( headers ) . forEach ( ( name : string ) => {
61
+ const value = headers [ name ] ;
62
+ const lcName = name . toLowerCase ( ) ;
63
+ this . _headers . set ( lcName , Array . isArray ( value ) ? value : [ value ] ) ;
64
+ this . mayBeSetNormalizedName ( name ) ;
57
65
} ) ;
58
66
}
59
67
60
68
/**
61
69
* Returns a new Headers instance from the given DOMString of Response Headers
62
70
*/
63
71
static fromResponseHeaderString ( headersString : string ) : Headers {
64
- let headers = new Headers ( ) ;
72
+ const headers = new Headers ( ) ;
65
73
66
74
headersString . split ( '\n' ) . forEach ( line => {
67
75
const index = line . indexOf ( ':' ) ;
68
76
if ( index > 0 ) {
69
- const key = line . substring ( 0 , index ) ;
70
- const value = line . substring ( index + 1 ) . trim ( ) ;
71
- headers . set ( key , value ) ;
77
+ const name = line . slice ( 0 , index ) ;
78
+ const value = line . slice ( index + 1 ) . trim ( ) ;
79
+ headers . set ( name , value ) ;
72
80
}
73
81
} ) ;
74
82
@@ -79,92 +87,94 @@ export class Headers {
79
87
* Appends a header to existing list of header values for a given header name.
80
88
*/
81
89
append ( name : string , value : string ) : void {
82
- name = normalize ( name ) ;
83
- var mapName = this . _headersMap . get ( name ) ;
84
- var list = isListLikeIterable ( mapName ) ? mapName : [ ] ;
85
- list . push ( value ) ;
86
- this . _headersMap . set ( name , list ) ;
90
+ const values = this . getAll ( name ) ;
91
+ this . set ( name , values === null ? [ value ] : [ ...values , value ] ) ;
87
92
}
88
93
89
94
/**
90
95
* Deletes all header values for the given name.
91
96
*/
92
- delete ( name : string ) : void { this . _headersMap . delete ( normalize ( name ) ) ; }
97
+ delete ( name : string ) : void {
98
+ const lcName = name . toLowerCase ( ) ;
99
+ this . _normalizedNames . delete ( lcName ) ;
100
+ this . _headers . delete ( lcName ) ;
101
+ }
93
102
94
103
forEach ( fn : ( values : string [ ] , name : string , headers : Map < string , string [ ] > ) => void ) : void {
95
- this . _headersMap . forEach ( fn ) ;
104
+ this . _headers . forEach (
105
+ ( values , lcName ) => fn ( values , this . _normalizedNames . get ( lcName ) , this . _headers ) ) ;
96
106
}
97
107
98
108
/**
99
109
* Returns first header that matches given name.
100
110
*/
101
- get ( header : string ) : string { return ListWrapper . first ( this . _headersMap . get ( normalize ( header ) ) ) ; }
111
+ get ( name : string ) : string {
112
+ const values = this . getAll ( name ) ;
113
+
114
+ if ( values === null ) {
115
+ return null ;
116
+ }
117
+
118
+ return values . length > 0 ? values [ 0 ] : null ;
119
+ }
102
120
103
121
/**
104
- * Check for existence of header by given name.
122
+ * Checks for existence of header by given name.
105
123
*/
106
- has ( header : string ) : boolean { return this . _headersMap . has ( normalize ( header ) ) ; }
124
+ has ( name : string ) : boolean { return this . _headers . has ( name . toLowerCase ( ) ) ; }
107
125
108
126
/**
109
- * Provides names of set headers
127
+ * Returns the names of the headers
110
128
*/
111
- keys ( ) : string [ ] { return MapWrapper . keys ( this . _headersMap ) ; }
129
+ keys ( ) : string [ ] { return MapWrapper . values ( this . _normalizedNames ) ; }
112
130
113
131
/**
114
132
* Sets or overrides header value for given name.
115
133
*/
116
- set ( header : string , value : string | string [ ] ) : void {
117
- var list : string [ ] = [ ] ;
118
-
119
- if ( isListLikeIterable ( value ) ) {
120
- var pushValue = ( < string [ ] > value ) . join ( ',' ) ;
121
- list . push ( pushValue ) ;
122
- } else {
123
- list . push ( < string > value ) ;
124
- }
125
-
126
- this . _headersMap . set ( normalize ( header ) , list ) ;
134
+ set ( name : string , value : string | string [ ] ) : void {
135
+ const strValue = Array . isArray ( value ) ? value . join ( ',' ) : value ;
136
+ this . _headers . set ( name . toLowerCase ( ) , [ strValue ] ) ;
137
+ this . mayBeSetNormalizedName ( name ) ;
127
138
}
128
139
129
140
/**
130
141
* Returns values of all headers.
131
142
*/
132
- values ( ) : string [ ] [ ] { return MapWrapper . values ( this . _headersMap ) ; }
143
+ values ( ) : string [ ] [ ] { return MapWrapper . values ( this . _headers ) ; }
133
144
134
145
/**
135
146
* Returns string of all headers.
136
147
*/
137
- toJSON ( ) : { [ key : string ] : any } {
138
- let serializableHeaders = { } ;
139
- this . _headersMap . forEach ( ( values : string [ ] , name : string ) => {
140
- let list : any [ ] /** TODO #9100 */ = [ ] ;
141
-
142
- iterateListLike (
143
- values , ( val : any /** TODO #9100 */ ) => list = ListWrapper . concat ( list , val . split ( ',' ) ) ) ;
144
-
145
- ( serializableHeaders as any /** TODO #9100 */ ) [ normalize ( name ) ] = list ;
148
+ // TODO(vicb): returns {[name: string]: string[]}
149
+ toJSON ( ) : { [ name : string ] : any } {
150
+ const serialized : { [ name : string ] : string [ ] } = { } ;
151
+
152
+ this . _headers . forEach ( ( values : string [ ] , name : string ) => {
153
+ const split : string [ ] = [ ] ;
154
+ values . forEach ( v => split . push ( ...v . split ( ',' ) ) ) ;
155
+ serialized [ this . _normalizedNames . get ( name ) ] = split ;
146
156
} ) ;
147
- return serializableHeaders ;
157
+
158
+ return serialized ;
148
159
}
149
160
150
161
/**
151
162
* Returns list of header values for a given name.
152
163
*/
153
- getAll ( header : string ) : string [ ] {
154
- var headers = this . _headersMap . get ( normalize ( header ) ) ;
155
- return isListLikeIterable ( headers ) ? headers : [ ] ;
164
+ getAll ( name : string ) : string [ ] {
165
+ return this . has ( name ) ? this . _headers . get ( name . toLowerCase ( ) ) : null ;
156
166
}
157
167
158
168
/**
159
169
* This method is not implemented.
160
170
*/
161
171
entries ( ) { throw new Error ( '"entries" method is not implemented on Headers class' ) ; }
162
- }
163
172
164
- // "HTTP character sets are identified by case-insensitive tokens"
165
- // Spec at https://tools.ietf.org/html/rfc2616
166
- // This implementation is same as NodeJS.
167
- // see https://nodejs.org/dist/latest-v6.x/docs/api/http.html#http_message_headers
168
- function normalize ( name : string ) : string {
169
- return name . toLowerCase ( ) ;
173
+ private mayBeSetNormalizedName ( name : string ) : void {
174
+ const lcName = name . toLowerCase ( ) ;
175
+
176
+ if ( ! this . _normalizedNames . has ( lcName ) ) {
177
+ this . _normalizedNames . set ( lcName , name ) ;
178
+ }
179
+ }
170
180
}
0 commit comments