Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: third_party/pkg/angular/lib/core_dom/http.dart

Issue 176943008: Update the Angular/DI tests to latest from github. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 part of angular.core.dom; 1 part of angular.core.dom;
2 2
3 @NgInjectableService() 3 @NgInjectableService()
4 class UrlRewriter { 4 class UrlRewriter {
5 String call(url) => url; 5 String call(url) => url;
6 } 6 }
7 7
8 /** 8 /**
9 * HTTP backend used by the [Http] service that delegates to dart:html's 9 * HTTP backend used by the [Http] service that delegates to dart:html's
10 * [HttpRequest] and deals with Dart bugs. 10 * [HttpRequest] and deals with Dart bugs.
11 * 11 *
12 * Never use this service directly, instead use the higher-level [Http]. 12 * Never use this service directly, instead use the higher-level [Http].
13 * 13 *
14 * During testing this implementation is swapped with [MockHttpBackend] which 14 * During testing this implementation is swapped with [MockHttpBackend] which
15 * can be trained with responses. 15 * can be trained with responses.
16 */ 16 */
17 @NgInjectableService() 17 @NgInjectableService()
18 class HttpBackend { 18 class HttpBackend {
19 /** 19 /**
20 * Wrapper around dart:html's [HttpRequest.request] 20 * Wrapper around dart:html's [HttpRequest.request]
21 */ 21 */
22 async.Future request(String url, 22 async.Future request(String url,
23 {String method, bool withCredentials, String responseType, 23 {String method, bool withCredentials, String responseType,
24 String mimeType, Map<String, String> requestHeaders, sendData, 24 String mimeType, Map<String, String> requestHeaders, sendData,
25 void onProgress(dom.ProgressEvent e)}) { 25 void onProgress(dom.ProgressEvent e)}) =>
26 // Complete inside a then to work-around dartbug.com/13051 26 dom.HttpRequest.request(url, method: method,
27 var c = new async.Completer(); 27 withCredentials: withCredentials, responseType: responseType,
28 28 mimeType: mimeType, requestHeaders: requestHeaders,
29 dom.HttpRequest.request(url, 29 sendData: sendData, onProgress: onProgress);
30 method: method,
31 withCredentials: withCredentials,
32 responseType: responseType,
33 mimeType: mimeType,
34 requestHeaders: requestHeaders,
35 sendData: sendData,
36 onProgress: onProgress).then((x) => c.complete(x),
37 onError: (e, stackTrace) => c.completeError(e, stackTrace));
38 return c.future;
39 }
40 } 30 }
41 31
42 @NgInjectableService() 32 @NgInjectableService()
43 class LocationWrapper { 33 class LocationWrapper {
44 get location => dom.window.location; 34 get location => dom.window.location;
45 } 35 }
46 36
47 typedef RequestInterceptor(HttpResponseConfig); 37 typedef RequestInterceptor(HttpResponseConfig);
48 typedef RequestErrorInterceptor(dynamic); 38 typedef RequestErrorInterceptor(dynamic);
49 typedef Response(HttpResponse); 39 typedef Response(HttpResponse);
50 typedef ResponseError(dynamic); 40 typedef ResponseError(dynamic);
51 41
52 /** 42 /**
53 * HttpInterceptors are used to modify the Http request. They can be added to 43 * HttpInterceptors are used to modify the Http request. They can be added to
54 * [HttpInterceptors] or passed into [Http.call]. 44 * [HttpInterceptors] or passed into [Http.call].
55 */ 45 */
56 class HttpInterceptor { 46 class HttpInterceptor {
57 RequestInterceptor request; 47 RequestInterceptor request;
58 Response response; 48 Response response;
59 RequestErrorInterceptor requestError; 49 RequestErrorInterceptor requestError;
60 ResponseError responseError; 50 ResponseError responseError;
61 51
62 /** 52 /**
63 * All parameters are optional. 53 * All parameters are optional.
64 */ 54 */
65 HttpInterceptor({ 55 HttpInterceptor({this.request, this.response, this.requestError,
66 this.request, this.response, 56 this.responseError});
67 this.requestError, this.responseError});
68 } 57 }
69 58
70 59
71 /** 60 /**
72 * The default transform data interceptor.abstract 61 * The default transform data interceptor.abstract
73 * 62 *
74 * For requests, this interceptor will 63 * For requests, this interceptor will
75 * automatically stringify any non-string non-file objects. 64 * automatically stringify any non-string non-file objects.
76 * 65 *
77 * For responses, this interceptor will unwrap JSON objects and 66 * For responses, this interceptor will unwrap JSON objects and
78 * parse them into [Map]s. 67 * parse them into [Map]s.
79 */ 68 */
80 class DefaultTransformDataHttpInterceptor implements HttpInterceptor { 69 class DefaultTransformDataHttpInterceptor implements HttpInterceptor {
81 Function request = (HttpResponseConfig config) { 70 Function request = (HttpResponseConfig config) {
82 if (config.data != null && config.data is! String && config.data is! dom.Fil e) { 71 if (config.data != null && config.data is! String &&
72 config.data is! dom.File) {
83 config.data = JSON.encode(config.data); 73 config.data = JSON.encode(config.data);
84 } 74 }
85 return config; 75 return config;
86 }; 76 };
87 77
88 static var _JSON_START = new RegExp(r'^\s*(\[|\{[^\{])'); 78 static var _JSON_START = new RegExp(r'^\s*(\[|\{[^\{])');
89 static var _JSON_END = new RegExp(r'[\}\]]\s*$'); 79 static var _JSON_END = new RegExp(r'[\}\]]\s*$');
90 static var _PROTECTION_PREFIX = new RegExp('^\\)\\]\\}\',?\\n'); 80 static var _PROTECTION_PREFIX = new RegExp('^\\)\\]\\}\',?\\n');
91 Function response = (HttpResponse r) { 81 Function response = (HttpResponse r) {
92 if (r.data is String) { 82 if (r.data is String) {
93 var d = r.data; 83 var d = r.data.replaceFirst(_PROTECTION_PREFIX, '');
94 d = d.replaceFirst(_PROTECTION_PREFIX, '');
95 if (d.contains(_JSON_START) && d.contains(_JSON_END)) { 84 if (d.contains(_JSON_START) && d.contains(_JSON_END)) {
96 d = JSON.decode(d); 85 d = JSON.decode(d);
97 } 86 }
98 return new HttpResponse.copy(r, data: d); 87 return new HttpResponse.copy(r, data: d);
99 } 88 }
100 return r; 89 return r;
101 }; 90 };
102 91
103 Function requestError, responseError; 92 Function requestError, responseError;
104 } 93 }
105 94
106 /** 95 /**
107 * A list of [HttpInterceptor]s. 96 * A list of [HttpInterceptor]s.
108 */ 97 */
109 @NgInjectableService() 98 @NgInjectableService()
110 class HttpInterceptors { 99 class HttpInterceptors {
111 List<HttpInterceptor> _interceptors = [new DefaultTransformDataHttpInterceptor ()]; 100 List<HttpInterceptor> _interceptors =
101 [new DefaultTransformDataHttpInterceptor()];
112 102
113 add(HttpInterceptor x) => _interceptors.add(x); 103 add(HttpInterceptor x) => _interceptors.add(x);
114 addAll(List<HttpInterceptor> x) => _interceptors.addAll(x); 104 addAll(List<HttpInterceptor> x) => _interceptors.addAll(x);
115 105
116 /** 106 /**
117 * Called from [Http] to construct a [Future] chain. 107 * Called from [Http] to construct a [Future] chain.
118 */ 108 */
119 constructChain(List chain) { 109 constructChain(List chain) {
120 _interceptors.reversed.forEach((HttpInterceptor i) { 110 _interceptors.reversed.forEach((HttpInterceptor i) {
121 // AngularJS has an optimization of not including null interceptors. 111 // AngularJS has an optimization of not including null interceptors.
122 chain.insert(0, [ 112 chain
123 i.request == null ? (x) => x : i.request, 113 ..insert(0, [
124 i.requestError]); 114 i.request == null ? (x) => x : i.request,
125 chain.add([ 115 i.requestError])
126 i.response == null ? (x) => x : i.response, 116 ..add([
127 i.responseError]); 117 i.response == null ? (x) => x : i.response,
118 i.responseError]);
128 }); 119 });
129 } 120 }
130 121
131 /** 122 /**
132 * Default constructor. 123 * Default constructor.
133 */ 124 */
134 HttpInterceptors() { 125 HttpInterceptors() {
135 _interceptors = [new DefaultTransformDataHttpInterceptor()]; 126 _interceptors = [new DefaultTransformDataHttpInterceptor()];
136 } 127 }
137 128
138 /** 129 /**
139 * Creates a [HttpInterceptors] from a [List]. Does not include the default i nterceptors. 130 * Creates a [HttpInterceptors] from a [List]. Does not include the default
131 * interceptors.
140 */ 132 */
141 HttpInterceptors.of([List interceptors]) { 133 HttpInterceptors.of([List interceptors]) {
142 _interceptors = interceptors; 134 _interceptors = interceptors;
143 } 135 }
144 } 136 }
145 137
146 /** 138 /**
147 * The request configuration of the request associated with this response. 139 * The request configuration of the request associated with this response.
148 */ 140 */
149 class HttpResponseConfig { 141 class HttpResponseConfig {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 config = r.config; 213 config = r.config;
222 } 214 }
223 215
224 /** 216 /**
225 * The response's data. Either a string or a transformed object. 217 * The response's data. Either a string or a transformed object.
226 */ 218 */
227 get data => responseText; 219 get data => responseText;
228 220
229 /** 221 /**
230 * The response's headers. Without parameters, this method will return the 222 * The response's headers. Without parameters, this method will return the
231 * [Map] of headers. With [key] parameter, this method will return the specif ic 223 * [Map] of headers. With [key] parameter, this method will return the
232 * header. 224 * specific header.
233 */ 225 */
234 headers([String key]) { 226 headers([String key]) => key == null ? _headers : _headers[key];
235 return key == null ? _headers : _headers[key];
236 }
237 227
238 /** 228 /**
239 * Useful for debugging. 229 * Useful for debugging.
240 */ 230 */
241 toString() => 'HTTP $status: $data'; 231 toString() => 'HTTP $status: $data';
242 } 232 }
243 233
244 /** 234 /**
245 * Default header configuration. 235 * Default header configuration.
246 */ 236 */
247 @NgInjectableService() 237 @NgInjectableService()
248 class HttpDefaultHeaders { 238 class HttpDefaultHeaders {
249 static String _defaultContentType = 'application/json;charset=utf-8'; 239 static var _defaultContentType = 'application/json;charset=utf-8';
250 Map _headers = { 240 var _headers = {
251 'COMMON': { 241 'COMMON': {'Accept': 'application/json, text/plain, */*'},
252 'Accept': 'application/json, text/plain, */*' 242 'POST' : {'Content-Type': _defaultContentType},
253 }, 243 'PUT' : {'Content-Type': _defaultContentType },
254 'POST' : { 244 'PATCH' : {'Content-Type': _defaultContentType}
255 'Content-Type': _defaultContentType
256 },
257 'PUT' : {
258 'Content-Type': _defaultContentType
259 },
260 'PATCH' : {
261 'Content-Type': _defaultContentType
262 }
263 }; 245 };
264 246
265 _applyHeaders(method, ucHeaders, headers) { 247 _applyHeaders(method, ucHeaders, headers) {
266 if (!_headers.containsKey(method)) return; 248 if (!_headers.containsKey(method)) return;
267 _headers[method].forEach((k, v) { 249 _headers[method].forEach((k, v) {
268 if (!ucHeaders.contains(k.toUpperCase())) { 250 if (!ucHeaders.contains(k.toUpperCase())) {
269 headers[k] = v; 251 headers[k] = v;
270 } 252 }
271 }); 253 });
272 } 254 }
273 255
274 /** 256 /**
275 * Called from [Http], this method sets default headers on [headers] 257 * Called from [Http], this method sets default headers on [headers]
276 */ 258 */
277 setHeaders(Map<String, String> headers, String method) { 259 setHeaders(Map<String, String> headers, String method) {
278 assert(headers != null); 260 assert(headers != null);
279 var ucHeaders = headers.keys.map((x) => x.toUpperCase()).toSet(); 261 var ucHeaders = headers.keys.map((x) => x.toUpperCase()).toSet();
280 _applyHeaders('COMMON', ucHeaders, headers); 262 _applyHeaders('COMMON', ucHeaders, headers);
281 _applyHeaders(method.toUpperCase(), ucHeaders, headers); 263 _applyHeaders(method.toUpperCase(), ucHeaders, headers);
282 } 264 }
283 265
284 /** 266 /**
285 * Returns the default header [Map] for a method. You can then modify 267 * Returns the default header [Map] for a method. You can then modify
286 * the map. 268 * the map.
287 * 269 *
288 * Passing 'common' as [method] will return a Map that contains headers 270 * Passing 'common' as [method] will return a Map that contains headers
289 * common to all operations. 271 * common to all operations.
290 */ 272 */
291 operator[](method) { 273 operator[](method) => _headers[method.toUpperCase()];
292 return _headers[method.toUpperCase()];
293 }
294 } 274 }
295 275
296 /** 276 /**
297 * Injected into the [Http] service. This class contains application-wide 277 * Injected into the [Http] service. This class contains application-wide
298 * HTTP defaults. 278 * HTTP defaults.
299 * 279 *
300 * The default implementation provides headers which the 280 * The default implementation provides headers which the
301 * Angular team believes to be useful. 281 * Angular team believes to be useful.
302 */ 282 */
303 @NgInjectableService() 283 @NgInjectableService()
(...skipping 20 matching lines...) Expand all
324 */ 304 */
325 String xsrfHeaderName = 'X-XSRF-TOKEN'; 305 String xsrfHeaderName = 'X-XSRF-TOKEN';
326 306
327 /** 307 /**
328 * Constructor intended for DI. 308 * Constructor intended for DI.
329 */ 309 */
330 HttpDefaults(this.headers); 310 HttpDefaults(this.headers);
331 } 311 }
332 312
333 /** 313 /**
334 * The [Http] service facilitates communication with the remote HTTP servers. I t 314 * The [Http] service facilitates communication with the remote HTTP servers.
335 * uses dart:html's [HttpRequest] and provides a number of features on top 315 * It uses dart:html's [HttpRequest] and provides a number of features on top
336 * of the core Dart library. 316 * of the core Dart library.
337 * 317 *
338 * For unit testing, applications should use the [MockHttpBackend] service. 318 * For unit testing, applications should use the [MockHttpBackend] service.
339 * 319 *
340 * # General usage 320 * # General usage
341 * The [call] method takes a number of named parameters and returns a 321 * The [call] method takes a number of named parameters and returns a
342 * [Future<HttpResponse>]. 322 * [Future<HttpResponse>].
343 * 323 *
344 * http(method: 'GET', url: '/someUrl') 324 * http(method: 'GET', url: '/someUrl')
345 * .then((HttpResponse response) { .. }, 325 * .then((HttpResponse response) { .. },
346 * onError: (HttpRequest request) { .. }); 326 * onError: (HttpRequest request) { .. });
347 * 327 *
348 * A response status code between 200 and 299 is considered a success status and 328 * A response status code between 200 and 299 is considered a success status and
349 * will result in the 'then' being called. Note that if the response is a redire ct, 329 * will result in the 'then' being called. Note that if the response is a
350 * Dart's [HttpRequest] will transparently follow it, meaning that the error cal lback will not be 330 * redirect, Dart's [HttpRequest] will transparently follow it, meaning that the
351 * called for such responses. 331 * error callback will not be called for such responses.
352 * 332 *
353 * # Shortcut methods 333 * # Shortcut methods
354 * 334 *
355 * The Http service also defines a number of shortcuts: 335 * The Http service also defines a number of shortcuts:
356 * 336 *
357 * http.get('/someUrl') is the same as http(method: 'GET', url: '/someUrl') 337 * http.get('/someUrl') is the same as http(method: 'GET', url: '/someUrl')
358 * 338 *
359 * See the method definitions below. 339 * See the method definitions below.
360 * 340 *
361 * # Setting HTTP Headers 341 * # Setting HTTP Headers
(...skipping 20 matching lines...) Expand all
382 * 362 *
383 * Http uses the interceptors from [HttpInterceptors]. You can also include 363 * Http uses the interceptors from [HttpInterceptors]. You can also include
384 * interceptors in the [call] method. 364 * interceptors in the [call] method.
385 * 365 *
386 * # Security Considerations 366 * # Security Considerations
387 * 367 *
388 * NOTE: < not yet documented > 368 * NOTE: < not yet documented >
389 */ 369 */
390 @NgInjectableService() 370 @NgInjectableService()
391 class Http { 371 class Http {
392 Map<String, async.Future<HttpResponse>> _pendingRequests = <String, async.Futu re<HttpResponse>>{}; 372 var _pendingRequests = <String, async.Future<HttpResponse>>{};
393 BrowserCookies _cookies; 373 BrowserCookies _cookies;
394 LocationWrapper _location; 374 LocationWrapper _location;
395 UrlRewriter _rewriter; 375 UrlRewriter _rewriter;
396 HttpBackend _backend; 376 HttpBackend _backend;
397 HttpInterceptors _interceptors; 377 HttpInterceptors _interceptors;
398 378
399 /** 379 /**
400 * The defaults for [Http] 380 * The defaults for [Http]
401 */ 381 */
402 HttpDefaults defaults; 382 HttpDefaults defaults;
403 383
404 /** 384 /**
405 * Constructor, useful for DI. 385 * Constructor, useful for DI.
406 */ 386 */
407 Http(this._cookies, this._location, this._rewriter, this._backend, this.defaul ts, this._interceptors); 387 Http(this._cookies, this._location, this._rewriter, this._backend,
388 this.defaults, this._interceptors);
408 389
409 /** 390 /**
410 * DEPRECATED 391 * DEPRECATED
411 */ 392 */
412 async.Future<String> getString(String url, 393 async.Future<String> getString(String url, {bool withCredentials,
413 {bool withCredentials, void onProgress(dom.ProgressEvent e), Cache cache}) { 394 void onProgress(dom.ProgressEvent e), Cache cache}) =>
414 return request(url, 395 request(url,
415 withCredentials: withCredentials, 396 withCredentials: withCredentials,
416 onProgress: onProgress, 397 onProgress: onProgress,
417 cache: cache).then((HttpResponse xhr) => xhr.responseText); 398 cache: cache).then((HttpResponse xhr) => xhr.responseText);
418 }
419 399
420 /** 400 /**
421 * Parse a request URL and determine whether this is a same-origin request as the application document. 401 * Parse a [requestUrl] and determine whether this is a same-origin request as
422 * 402 * the application document.
423 * @param {string|Uri} requestUrl The url of the request as a string that will be resolved
424 * or a parsed URL object.
425 * @returns {boolean} Whether the request is for the same origin as the applic ation document.
426 */ 403 */
427 _urlIsSameOrigin(String requestUrl) { 404 bool _urlIsSameOrigin(String requestUrl) {
428 Uri originUrl = Uri.parse(_location.location.toString()); 405 Uri originUrl = Uri.parse(_location.location.toString());
429 Uri parsed = originUrl.resolve(requestUrl); 406 Uri parsed = originUrl.resolve(requestUrl);
430 return (parsed.scheme == originUrl.scheme && 407 return (parsed.scheme == originUrl.scheme && parsed.host == originUrl.host);
431 parsed.host == originUrl.host);
432 } 408 }
433 409
434 /** 410 /**
435 * Returns a [Future<HttpResponse>] when the request is fulfilled. 411 * Returns a [Future<HttpResponse>] when the request is fulfilled.
436 * 412 *
437 * Named Parameters: 413 * Named Parameters:
438 * - method: HTTP method (e.g. 'GET', 'POST', etc) 414 * - method: HTTP method (e.g. 'GET', 'POST', etc)
439 * - url: Absolute or relative URL of the resource being requested. 415 * - url: Absolute or relative URL of the resource being requested.
440 * - data: Data to be sent as the request message data. 416 * - data: Data to be sent as the request message data.
441 * - params: Map of strings or objects which will be turned to 417 * - params: Map of strings or objects which will be turned to
(...skipping 19 matching lines...) Expand all
461 interceptors, 437 interceptors,
462 cache, 438 cache,
463 timeout 439 timeout
464 }) { 440 }) {
465 if (timeout != null) { 441 if (timeout != null) {
466 throw ['timeout not implemented']; 442 throw ['timeout not implemented'];
467 } 443 }
468 444
469 method = method.toUpperCase(); 445 method = method.toUpperCase();
470 446
471 if (headers == null) { headers = {}; } 447 if (headers == null) headers = {};
472 defaults.headers.setHeaders(headers, method); 448 defaults.headers.setHeaders(headers, method);
473 449
474 var xsrfValue = _urlIsSameOrigin(url) ? 450 var xsrfValue = _urlIsSameOrigin(url) ?
475 _cookies[xsrfCookieName != null ? xsrfCookieName : defaults.xsrfCookieNa me] : null; 451 _cookies[xsrfCookieName != null ? xsrfCookieName : defaults.xsrfCookieNa me] :
452 null;
476 if (xsrfValue != null) { 453 if (xsrfValue != null) {
477 headers[xsrfHeaderName != null ? xsrfHeaderName : defaults.xsrfHeaderName] = xsrfValue; 454 headers[xsrfHeaderName != null ? xsrfHeaderName : defaults.xsrfHeaderName]
455 = xsrfValue;
478 } 456 }
479 457
480 // Check for functions in headers 458 // Check for functions in headers
481 headers.forEach((k,v) { 459 headers.forEach((k, v) {
482 if (v is Function) { 460 if (v is Function) headers[k] = v();
483 headers[k] = v();
484 }
485 }); 461 });
486 462
487 var serverRequest = (HttpResponseConfig config) { 463 var serverRequest = (HttpResponseConfig config) {
488 assert(config.data == null || config.data is String || config.data is dom. File); 464 assert(config.data == null || config.data is String ||
465 config.data is dom.File);
489 466
490 // Strip content-type if data is undefined 467 // Strip content-type if data is undefined
491 if (config.data == null) { 468 if (config.data == null) {
492 new List.from(headers.keys) 469 new List.from(headers.keys)
493 .where((h) => h.toUpperCase() == 'CONTENT-TYPE') 470 .where((h) => h.toUpperCase() == 'CONTENT-TYPE')
494 .forEach((h) => headers.remove(h)); 471 .forEach((h) => headers.remove(h));
495 } 472 }
496 473
497 return request( 474 return request(null,
498 null, 475 config: config,
499 config: config, 476 method: method,
500 method: method, 477 sendData: config.data,
501 sendData: config.data, 478 requestHeaders: config.headers,
502 requestHeaders: config.headers, 479 cache: cache);
503 cache: cache);
504 }; 480 };
505 481
506 var chain = [[serverRequest, null]]; 482 var chain = [[serverRequest, null]];
507 483
508 var future = new async.Future.value(new HttpResponseConfig( 484 var future = new async.Future.value(new HttpResponseConfig(
509 url: url, 485 url: url,
510 params: params, 486 params: params,
511 headers: headers, 487 headers: headers,
512 data: data)); 488 data: data));
513 489
(...skipping 20 matching lines...) Expand all
534 */ 510 */
535 async.Future<HttpResponse> get(String url, { 511 async.Future<HttpResponse> get(String url, {
536 String data, 512 String data,
537 Map<String, dynamic> params, 513 Map<String, dynamic> params,
538 Map<String, String> headers, 514 Map<String, String> headers,
539 xsrfHeaderName, 515 xsrfHeaderName,
540 xsrfCookieName, 516 xsrfCookieName,
541 interceptors, 517 interceptors,
542 cache, 518 cache,
543 timeout 519 timeout
544 }) => call(method: 'GET', url: url, data: data, params: params, headers: heade rs, 520 }) => call(method: 'GET', url: url, data: data, params: params,
545 xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName, 521 headers: headers, xsrfHeaderName: xsrfHeaderName,
546 interceptors: interceptors, 522 xsrfCookieName: xsrfCookieName, interceptors: interceptors,
547 cache: cache, timeout: timeout); 523 cache: cache, timeout: timeout);
548 524
549 /** 525 /**
550 * Shortcut method for DELETE requests. See [call] for a complete description 526 * Shortcut method for DELETE requests. See [call] for a complete description
551 * of parameters. 527 * of parameters.
552 */ 528 */
553 async.Future<HttpResponse> delete(String url, { 529 async.Future<HttpResponse> delete(String url, {
554 String data, 530 String data,
555 Map<String, dynamic> params, 531 Map<String, dynamic> params,
556 Map<String, String> headers, 532 Map<String, String> headers,
557 xsrfHeaderName, 533 xsrfHeaderName,
558 xsrfCookieName, 534 xsrfCookieName,
559 interceptors, 535 interceptors,
560 cache, 536 cache,
561 timeout 537 timeout
562 }) => call(method: 'DELETE', url: url, data: data, params: params, headers: he aders, 538 }) => call(method: 'DELETE', url: url, data: data, params: params,
563 xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName, 539 headers: headers, xsrfHeaderName: xsrfHeaderName,
564 interceptors: interceptors, 540 xsrfCookieName: xsrfCookieName, interceptors: interceptors,
565 cache: cache, timeout: timeout); 541 cache: cache, timeout: timeout);
566 542
567 /** 543 /**
568 * Shortcut method for HEAD requests. See [call] for a complete description 544 * Shortcut method for HEAD requests. See [call] for a complete description
569 * of parameters. 545 * of parameters.
570 */ 546 */
571 async.Future<HttpResponse> head(String url, { 547 async.Future<HttpResponse> head(String url, {
572 String data, 548 String data,
573 Map<String, dynamic> params, 549 Map<String, dynamic> params,
574 Map<String, String> headers, 550 Map<String, String> headers,
575 xsrfHeaderName, 551 xsrfHeaderName,
576 xsrfCookieName, 552 xsrfCookieName,
577 interceptors, 553 interceptors,
578 cache, 554 cache,
579 timeout 555 timeout
580 }) => call(method: 'HEAD', url: url, data: data, params: params, headers: head ers, 556 }) => call(method: 'HEAD', url: url, data: data, params: params,
581 xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName, 557 headers: headers, xsrfHeaderName: xsrfHeaderName,
582 interceptors: interceptors, 558 xsrfCookieName: xsrfCookieName, interceptors: interceptors,
583 cache: cache, timeout: timeout); 559 cache: cache, timeout: timeout);
584 560
585 /** 561 /**
586 * Shortcut method for PUT requests. See [call] for a complete description 562 * Shortcut method for PUT requests. See [call] for a complete description
587 * of parameters. 563 * of parameters.
588 */ 564 */
589 async.Future<HttpResponse> put(String url, String data, { 565 async.Future<HttpResponse> put(String url, String data, {
590 Map<String, dynamic> params, 566 Map<String, dynamic> params,
591 Map<String, String> headers, 567 Map<String, String> headers,
592 xsrfHeaderName, 568 xsrfHeaderName,
593 xsrfCookieName, 569 xsrfCookieName,
594 interceptors, 570 interceptors,
595 cache, 571 cache,
596 timeout 572 timeout
597 }) => call(method: 'PUT', url: url, data: data, params: params, headers: heade rs, 573 }) => call(method: 'PUT', url: url, data: data, params: params,
598 xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName, 574 headers: headers, xsrfHeaderName: xsrfHeaderName,
599 interceptors: interceptors, 575 xsrfCookieName: xsrfCookieName, interceptors: interceptors,
600 cache: cache, timeout: timeout); 576 cache: cache, timeout: timeout);
601 577
602 /** 578 /**
603 * Shortcut method for POST requests. See [call] for a complete description 579 * Shortcut method for POST requests. See [call] for a complete description
604 * of parameters. 580 * of parameters.
605 */ 581 */
606 async.Future<HttpResponse> post(String url, String data, { 582 async.Future<HttpResponse> post(String url, String data, {
607 Map<String, dynamic> params, 583 Map<String, dynamic> params,
608 Map<String, String> headers, 584 Map<String, String> headers,
609 xsrfHeaderName, 585 xsrfHeaderName,
610 xsrfCookieName, 586 xsrfCookieName,
611 interceptors, 587 interceptors,
612 cache, 588 cache,
613 timeout 589 timeout
614 }) => call(method: 'POST', url: url, data: data, params: params, headers: head ers, 590 }) => call(method: 'POST', url: url, data: data, params: params,
615 xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName, 591 headers: headers, xsrfHeaderName: xsrfHeaderName,
616 interceptors: interceptors, 592 xsrfCookieName: xsrfCookieName, interceptors: interceptors,
617 cache: cache, timeout: timeout); 593 cache: cache, timeout: timeout);
618 594
619 /** 595 /**
620 * Shortcut method for JSONP requests. See [call] for a complete description 596 * Shortcut method for JSONP requests. See [call] for a complete description
621 * of parameters. 597 * of parameters.
622 */ 598 */
623 async.Future<HttpResponse> jsonp(String url, { 599 async.Future<HttpResponse> jsonp(String url, {
624 String data, 600 String data,
625 Map<String, dynamic> params, 601 Map<String, dynamic> params,
626 Map<String, String> headers, 602 Map<String, String> headers,
627 xsrfHeaderName, 603 xsrfHeaderName,
628 xsrfCookieName, 604 xsrfCookieName,
629 interceptors, 605 interceptors,
630 cache, 606 cache,
631 timeout 607 timeout
632 }) => call(method: 'JSONP', url: url, data: data, params: params, headers: hea ders, 608 }) => call(method: 'JSONP', url: url, data: data, params: params,
633 xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName, 609 headers: headers, xsrfHeaderName: xsrfHeaderName,
634 interceptors: interceptors, 610 xsrfCookieName: xsrfCookieName, interceptors: interceptors,
635 cache: cache, timeout: timeout); 611 cache: cache, timeout: timeout);
636 612
637 /** 613 /**
638 * Parse raw headers into key-value object 614 * Parse raw headers into key-value object
639 */ 615 */
640 static Map<String, String> parseHeaders(dom.HttpRequest value) { 616 static Map<String, String> parseHeaders(dom.HttpRequest value) {
641 var headers = value.getAllResponseHeaders(); 617 var headers = value.getAllResponseHeaders();
642 618
643 var parsed = {}; 619 var parsed = {};
644 620
645 if (headers == null) return parsed; 621 if (headers == null) return parsed;
646 622
647 headers.split('\n').forEach((line) { 623 headers.split('\n').forEach((line) {
648 var i = line.indexOf(':'); 624 var i = line.indexOf(':');
649 if (i == -1) return; 625 if (i == -1) return;
650 var key = line.substring(0, i).trim().toLowerCase(); 626 var key = line.substring(0, i).trim().toLowerCase();
651 var val = line.substring(i + 1).trim();
652 627
653 if (key != '') { 628 if (key.isNotEmpty) {
654 if (parsed.containsKey(key)) { 629 var val = line.substring(i + 1).trim();
655 parsed[key] += ', ' + val; 630 parsed[key] = parsed.containsKey(key) ? "${parsed[key]}, $val" : val;
656 } else {
657 parsed[key] = val;
658 }
659 } 631 }
660 }); 632 });
661 return parsed; 633 return parsed;
662 } 634 }
663 635
664 /** 636 /**
665 * Returns an [Iterable] of [Future] [HttpResponse]s for the requests 637 * Returns an [Iterable] of [Future] [HttpResponse]s for the requests
666 * that the [Http] service is currently waiting for. 638 * that the [Http] service is currently waiting for.
667 */ 639 */
668 Iterable<async.Future<HttpResponse> > get pendingRequests => 640 Iterable<async.Future<HttpResponse> > get pendingRequests =>
669 _pendingRequests.values; 641 _pendingRequests.values;
670 642
671 /** 643 /**
672 * DEPRECATED 644 * DEPRECATED
673 */ 645 */
674 async.Future<HttpResponse> request(String rawUrl, 646 async.Future<HttpResponse> request(String rawUrl,
675 { HttpResponseConfig config, 647 { HttpResponseConfig config,
676 String method: 'GET', 648 String method: 'GET',
677 bool withCredentials: false, 649 bool withCredentials: false,
678 String responseType, 650 String responseType,
679 String mimeType, 651 String mimeType,
680 Map<String, String> requestHeaders, 652 Map<String, String> requestHeaders,
681 sendData, 653 sendData,
682 void onProgress(dom.ProgressEvent e), 654 void onProgress(dom.ProgressEvent e),
683 /*Cache<String, HttpResponse> or false*/ cache }) { 655 /*Cache<String, HttpResponse> or false*/ cache }) {
684 String url; 656 String url;
685 657
686 if (config == null) { 658 if (config == null) {
687 url = _rewriter(rawUrl); 659 url = _rewriter(rawUrl);
688 config = new HttpResponseConfig(url: url); 660 config = new HttpResponseConfig(url: url);
689 } else { 661 } else {
690 url = _buildUrl(config.url, config.params); 662 url = _buildUrl(config.url, config.params);
691 } 663 }
692 664
693 if (cache is bool && cache == false) { 665 if (cache == false) {
694 cache = null; 666 cache = null;
695 } else if (cache == null) { 667 } else if (cache == null) {
696 cache = defaults.cache; 668 cache = defaults.cache;
697 } 669 }
698 // We return a pending request only if caching is enabled. 670 // We return a pending request only if caching is enabled.
699 if (cache != null && _pendingRequests.containsKey(url)) { 671 if (cache != null && _pendingRequests.containsKey(url)) {
700 return _pendingRequests[url]; 672 return _pendingRequests[url];
701 } 673 }
702 var cachedValue = (cache != null && method == 'GET') ? cache.get(url) : null ; 674 var cachedResponse = (cache != null && method == 'GET')
703 if (cachedValue != null) { 675 ? cache.get(url)
704 return new async.Future.value(new HttpResponse.copy(cachedValue)); 676 : null;
677 if (cachedResponse != null) {
678 return new async.Future.value(new HttpResponse.copy(cachedResponse));
705 } 679 }
706 680
707 var result = _backend.request(url, 681 var result = _backend.request(url,
708 method: method, 682 method: method,
709 withCredentials: withCredentials, 683 withCredentials: withCredentials,
710 responseType: responseType, 684 responseType: responseType,
711 mimeType: mimeType, 685 mimeType: mimeType,
712 requestHeaders: requestHeaders, 686 requestHeaders: requestHeaders,
713 sendData: sendData, 687 sendData: sendData,
714 onProgress: onProgress).then((dom.HttpRequest value) { 688 onProgress: onProgress).then((dom.HttpRequest value) {
715 // TODO: Uncomment after apps migrate off of this class. 689 // TODO: Uncomment after apps migrate off of this class.
716 // assert(value.status >= 200 && value.status < 300); 690 // assert(value.status >= 200 && value.status < 300);
717 691
718 var response = new HttpResponse( 692 var response = new HttpResponse(value.status, value.responseText,
719 value.status, value.responseText, parseHeaders(value), 693 parseHeaders(value), config);
720 config);
721 694
722 if (cache != null) { 695 if (cache != null) cache.put(url, response);
723 cache.put(url, response);
724 }
725 _pendingRequests.remove(url); 696 _pendingRequests.remove(url);
726 return response; 697 return response;
727 }, onError: (error) { 698 }, onError: (error) {
728 if (error is! dom.ProgressEvent) { 699 if (error is! dom.ProgressEvent) throw error;
729 throw error;
730 }
731 dom.ProgressEvent event = error; 700 dom.ProgressEvent event = error;
732 _pendingRequests.remove(url); 701 _pendingRequests.remove(url);
733 dom.HttpRequest request = event.currentTarget; 702 dom.HttpRequest request = event.currentTarget;
734 return new async.Future.error( 703 return new async.Future.error(
735 new HttpResponse(request.status, request.response, 704 new HttpResponse(request.status, request.response,
736 parseHeaders(request), config)); 705 parseHeaders(request), config));
737 }); 706 });
738 _pendingRequests[url] = result; 707 return _pendingRequests[url] = result;
739 return result;
740 } 708 }
741 709
742 _buildUrl(String url, Map<String, dynamic> params) { 710 _buildUrl(String url, Map<String, dynamic> params) {
743 if (params == null) return url; 711 if (params == null) return url;
744 var parts = []; 712 var parts = [];
745 713
746 new List.from(params.keys)..sort()..forEach((String key) { 714 new List.from(params.keys)..sort()..forEach((String key) {
747 var value = params[key]; 715 var value = params[key];
748 if (value == null) return; 716 if (value == null) return;
749 if (value is! List) value = [value]; 717 if (value is! List) value = [value];
750 718
751 value.forEach((v) { 719 value.forEach((v) {
752 if (v is Map) { 720 if (v is Map) v = JSON.encode(v);
753 v = JSON.encode(v); 721 parts.add(_encodeUriQuery(key) + '=' + _encodeUriQuery("$v"));
754 }
755 parts.add(_encodeUriQuery(key) + '=' +
756 _encodeUriQuery("$v"));
757 }); 722 });
758 }); 723 });
759 return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); 724 return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
760 } 725 }
761 726
762 _encodeUriQuery(val, {bool pctEncodeSpaces: false}) => 727 _encodeUriQuery(val, {bool pctEncodeSpaces: false}) =>
763 Uri.encodeComponent(val) 728 Uri.encodeComponent(val)
764 .replaceAll('%40', '@') 729 .replaceAll('%40', '@')
765 .replaceAll('%3A', ':') 730 .replaceAll('%3A', ':')
766 .replaceAll('%24', r'$') 731 .replaceAll('%24', r'$')
767 .replaceAll('%2C', ',') 732 .replaceAll('%2C', ',')
768 .replaceAll('%20', pctEncodeSpaces ? '%20' : '+'); 733 .replaceAll('%20', pctEncodeSpaces ? '%20' : '+');
769 } 734 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698