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

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

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

Powered by Google App Engine
This is Rietveld 408576698