| 
									
										
										
										
											2016-06-23 09:47:54 -07: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-06-08 16:38:52 -07:00
										 |  |  | import {ListWrapper, Map, isListLikeIterable} from '../src/facade/collection'; | 
					
						
							| 
									
										
										
										
											2016-04-28 17:50:03 -07:00
										 |  |  | import {isPresent} from '../src/facade/lang'; | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-28 11:29:19 -07:00
										 |  |  | function paramParser(rawParams: string = ''): Map<string, string[]> { | 
					
						
							| 
									
										
										
										
											2015-09-29 11:11:06 -07:00
										 |  |  |   var map = new Map<string, string[]>(); | 
					
						
							| 
									
										
										
										
											2015-07-13 14:47:10 -04:00
										 |  |  |   if (rawParams.length > 0) { | 
					
						
							| 
									
										
										
										
											2015-10-31 13:04:26 -07:00
										 |  |  |     var params: string[] = rawParams.split('&'); | 
					
						
							| 
									
										
										
										
											2015-10-07 09:09:43 -07:00
										 |  |  |     params.forEach((param: string) => { | 
					
						
							| 
									
										
										
										
											2016-06-28 11:31:35 -07:00
										 |  |  |       var split: string[] = param.split('=', 2); | 
					
						
							| 
									
										
										
										
											2015-08-28 11:29:19 -07:00
										 |  |  |       var key = split[0]; | 
					
						
							|  |  |  |       var val = split[1]; | 
					
						
							| 
									
										
										
										
											2015-07-13 14:47:10 -04:00
										 |  |  |       var list = isPresent(map.get(key)) ? map.get(key) : []; | 
					
						
							|  |  |  |       list.push(val); | 
					
						
							|  |  |  |       map.set(key, list); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  |   return map; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-06-28 11:31:35 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @experimental | 
					
						
							|  |  |  |  **/ | 
					
						
							|  |  |  | export class QueryEncoder { | 
					
						
							|  |  |  |   encodeKey(k: string): string { return standardEncoding(k); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   encodeValue(v: string): string { return standardEncoding(v); } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function standardEncoding(v: string): string { | 
					
						
							|  |  |  |   return encodeURIComponent(v) | 
					
						
							|  |  |  |       .replace(/%40/gi, '@') | 
					
						
							|  |  |  |       .replace(/%3A/gi, ':') | 
					
						
							|  |  |  |       .replace(/%24/gi, '$') | 
					
						
							|  |  |  |       .replace(/%2C/gi, ',') | 
					
						
							|  |  |  |       .replace(/%3B/gi, ';') | 
					
						
							|  |  |  |       .replace(/%2B/gi, '+') | 
					
						
							|  |  |  |       .replace(/%3D/gi, ';') | 
					
						
							|  |  |  |       .replace(/%3F/gi, '?') | 
					
						
							|  |  |  |       .replace(/%2F/gi, '/'); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-24 00:27:07 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Map-like representation of url search parameters, based on | 
					
						
							| 
									
										
										
										
											2015-07-13 14:47:10 -04:00
										 |  |  |  * [URLSearchParams](https://url.spec.whatwg.org/#urlsearchparams) in the url living standard,
 | 
					
						
							|  |  |  |  * with several extensions for merging URLSearchParams objects: | 
					
						
							|  |  |  |  *   - setAll() | 
					
						
							|  |  |  |  *   - appendAll() | 
					
						
							|  |  |  |  *   - replaceAll() | 
					
						
							| 
									
										
										
										
											2016-06-27 12:27:23 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-06-28 11:31:35 -07:00
										 |  |  |  * This class accepts an optional second parameter of ${@link QueryEncoder}, | 
					
						
							|  |  |  |  * which is used to serialize parameters before making a request. By default, | 
					
						
							|  |  |  |  * `QueryEncoder` encodes keys and values of parameters using `encodeURIComponent`, | 
					
						
							|  |  |  |  * and then un-encodes certain characters that are allowed to be part of the query | 
					
						
							|  |  |  |  * according to IETF RFC 3986: https://tools.ietf.org/html/rfc3986.
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * These are the characters that are not encoded: `! $ \' ( ) * + , ; A 9 - . _ ~ ? /` | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * If the set of allowed query characters is not acceptable for a particular backend, | 
					
						
							|  |  |  |  * `QueryEncoder` can be subclassed and provided as the 2nd argument to URLSearchParams. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * import {URLSearchParams, QueryEncoder} from '@angular/http'; | 
					
						
							|  |  |  |  * class MyQueryEncoder extends QueryEncoder { | 
					
						
							|  |  |  |  *   encodeKey(k: string): string { | 
					
						
							|  |  |  |  *     return myEncodingFunction(k); | 
					
						
							|  |  |  |  *   } | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   encodeValue(v: string): string { | 
					
						
							|  |  |  |  *     return myEncodingFunction(v); | 
					
						
							|  |  |  |  *   } | 
					
						
							|  |  |  |  * } | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * let params = new URLSearchParams('', new MyQueryEncoder()); | 
					
						
							|  |  |  |  * ```
 | 
					
						
							| 
									
										
										
										
											2016-06-27 12:27:23 -07:00
										 |  |  |  * @experimental | 
					
						
							| 
									
										
										
										
											2015-06-24 00:27:07 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  | export class URLSearchParams { | 
					
						
							| 
									
										
										
										
											2015-08-28 11:29:19 -07:00
										 |  |  |   paramsMap: Map<string, string[]>; | 
					
						
							| 
									
										
										
										
											2016-06-28 11:31:35 -07:00
										 |  |  |   constructor( | 
					
						
							|  |  |  |       public rawParams: string = '', private queryEncoder: QueryEncoder = new QueryEncoder()) { | 
					
						
							|  |  |  |     this.paramsMap = paramParser(rawParams); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-07-13 14:47:10 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   clone(): URLSearchParams { | 
					
						
							|  |  |  |     var clone = new URLSearchParams(); | 
					
						
							|  |  |  |     clone.appendAll(this); | 
					
						
							|  |  |  |     return clone; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-17 21:42:56 -07:00
										 |  |  |   has(param: string): boolean { return this.paramsMap.has(param); } | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-19 12:14:12 -07:00
										 |  |  |   get(param: string): string { | 
					
						
							|  |  |  |     var storedParam = this.paramsMap.get(param); | 
					
						
							|  |  |  |     if (isListLikeIterable(storedParam)) { | 
					
						
							|  |  |  |       return ListWrapper.first(storedParam); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-28 11:29:19 -07:00
										 |  |  |   getAll(param: string): string[] { | 
					
						
							| 
									
										
										
										
											2015-06-19 12:14:12 -07:00
										 |  |  |     var mapParam = this.paramsMap.get(param); | 
					
						
							|  |  |  |     return isPresent(mapParam) ? mapParam : []; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-13 14:47:10 -04:00
										 |  |  |   set(param: string, val: string) { | 
					
						
							|  |  |  |     var mapParam = this.paramsMap.get(param); | 
					
						
							|  |  |  |     var list = isPresent(mapParam) ? mapParam : []; | 
					
						
							|  |  |  |     ListWrapper.clear(list); | 
					
						
							|  |  |  |     list.push(val); | 
					
						
							|  |  |  |     this.paramsMap.set(param, list); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // A merge operation
 | 
					
						
							|  |  |  |   // For each name-values pair in `searchParams`, perform `set(name, values[0])`
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // E.g: "a=[1,2,3], c=[8]" + "a=[4,5,6], b=[7]" = "a=[4], c=[8], b=[7]"
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // TODO(@caitp): document this better
 | 
					
						
							|  |  |  |   setAll(searchParams: URLSearchParams) { | 
					
						
							| 
									
										
										
										
											2015-10-08 16:01:18 -07:00
										 |  |  |     searchParams.paramsMap.forEach((value, param) => { | 
					
						
							| 
									
										
										
										
											2015-07-13 14:47:10 -04:00
										 |  |  |       var mapParam = this.paramsMap.get(param); | 
					
						
							|  |  |  |       var list = isPresent(mapParam) ? mapParam : []; | 
					
						
							|  |  |  |       ListWrapper.clear(list); | 
					
						
							|  |  |  |       list.push(value[0]); | 
					
						
							|  |  |  |       this.paramsMap.set(param, list); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  |   append(param: string, val: string): void { | 
					
						
							| 
									
										
										
										
											2015-06-19 12:14:12 -07:00
										 |  |  |     var mapParam = this.paramsMap.get(param); | 
					
						
							|  |  |  |     var list = isPresent(mapParam) ? mapParam : []; | 
					
						
							| 
									
										
										
										
											2015-06-17 11:17:21 -07:00
										 |  |  |     list.push(val); | 
					
						
							| 
									
										
										
										
											2015-06-17 16:21:40 -07:00
										 |  |  |     this.paramsMap.set(param, list); | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-13 14:47:10 -04:00
										 |  |  |   // A merge operation
 | 
					
						
							|  |  |  |   // For each name-values pair in `searchParams`, perform `append(name, value)`
 | 
					
						
							|  |  |  |   // for each value in `values`.
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // E.g: "a=[1,2], c=[8]" + "a=[3,4], b=[7]" = "a=[1,2,3,4], c=[8], b=[7]"
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // TODO(@caitp): document this better
 | 
					
						
							|  |  |  |   appendAll(searchParams: URLSearchParams) { | 
					
						
							| 
									
										
										
										
											2015-10-08 16:01:18 -07:00
										 |  |  |     searchParams.paramsMap.forEach((value, param) => { | 
					
						
							| 
									
										
										
										
											2015-07-13 14:47:10 -04:00
										 |  |  |       var mapParam = this.paramsMap.get(param); | 
					
						
							|  |  |  |       var list = isPresent(mapParam) ? mapParam : []; | 
					
						
							|  |  |  |       for (var i = 0; i < value.length; ++i) { | 
					
						
							|  |  |  |         list.push(value[i]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       this.paramsMap.set(param, list); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // A merge operation
 | 
					
						
							|  |  |  |   // For each name-values pair in `searchParams`, perform `delete(name)`,
 | 
					
						
							|  |  |  |   // followed by `set(name, values)`
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // E.g: "a=[1,2,3], c=[8]" + "a=[4,5,6], b=[7]" = "a=[4,5,6], c=[8], b=[7]"
 | 
					
						
							|  |  |  |   //
 | 
					
						
							|  |  |  |   // TODO(@caitp): document this better
 | 
					
						
							|  |  |  |   replaceAll(searchParams: URLSearchParams) { | 
					
						
							| 
									
										
										
										
											2015-10-08 16:01:18 -07:00
										 |  |  |     searchParams.paramsMap.forEach((value, param) => { | 
					
						
							| 
									
										
										
										
											2015-07-13 14:47:10 -04:00
										 |  |  |       var mapParam = this.paramsMap.get(param); | 
					
						
							|  |  |  |       var list = isPresent(mapParam) ? mapParam : []; | 
					
						
							|  |  |  |       ListWrapper.clear(list); | 
					
						
							|  |  |  |       for (var i = 0; i < value.length; ++i) { | 
					
						
							|  |  |  |         list.push(value[i]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       this.paramsMap.set(param, list); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  |   toString(): string { | 
					
						
							| 
									
										
										
										
											2016-02-01 17:05:50 -08:00
										 |  |  |     var paramsList: string[] = []; | 
					
						
							| 
									
										
										
										
											2016-06-23 04:23:15 +03:00
										 |  |  |     this.paramsMap.forEach((values, k) => { | 
					
						
							| 
									
										
										
										
											2016-06-28 11:31:35 -07:00
										 |  |  |       values.forEach( | 
					
						
							|  |  |  |           v => paramsList.push( | 
					
						
							|  |  |  |               this.queryEncoder.encodeKey(k) + '=' + this.queryEncoder.encodeValue(v))); | 
					
						
							| 
									
										
										
										
											2016-06-23 04:23:15 +03:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-06 17:11:10 -07:00
										 |  |  |     return paramsList.join('&'); | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-08 16:01:18 -07:00
										 |  |  |   delete (param: string): void { this.paramsMap.delete(param); } | 
					
						
							| 
									
										
										
										
											2015-04-28 23:07:55 -07:00
										 |  |  | } |