Dart Documentationangular.core.domHttp

Http class

The Http service facilitates communication with the remote HTTP servers. It uses dart:html's HttpRequest and provides a number of features on top of the core Dart library.

For unit testing, applications should use the MockHttpBackend service.

General usage

The call method takes a number of named parameters and returns a [Future].

 http(method: 'GET', url: '/someUrl')
   .then((HttpResponse response) { .. },
          onError: (HttpRequest request) { .. });

A response status code between 200 and 299 is considered a success status and will result in the 'then' being called. Note that if the response is a redirect, Dart's HttpRequest will transparently follow it, meaning that the error callback will not be called for such responses.

Shortcut methods

The Http service also defines a number of shortcuts:

 http.get('/someUrl') is the same as http(method: 'GET', url: '/someUrl')

See the method definitions below.

Setting HTTP Headers

The Http service will add certain HTTP headers to requests. These defaults can be configured using the HttpDefaultHeaders object. The defaults are:

  • For all requests: Accept: application/json, text/plain, * / *
  • For POST, PUT, PATCH requests: Content-Type: application/json

Caching

To enable caching, pass a Cache object into the call method. The Http service will store responses in the cache and return the response for any matching requests.

Note that data is returned through a Future, regardless of whether it came from the Cache or the server.

If there are multiple GET requests for the same not-yet-in-cache URL while a cache is in use, only one request to the server will be made.

Interceptors

Http uses the interceptors from HttpInterceptors. You can also include interceptors in the call method.

Security Considerations

NOTE: < not yet documented >

class Http {
 Map<String, async.Future<HttpResponse>> _pendingRequests = <String, async.Future<HttpResponse>>{};
 UrlRewriter _rewriter;
 HttpBackend _backend;
 HttpInterceptors _interceptors;

 /**
  * The defaults for [Http]
  */
 HttpDefaults defaults;

 /**
  * Constructor, useful for DI.
  */
 Http(UrlRewriter this._rewriter,
      HttpBackend this._backend,
      HttpDefaults this.defaults,
      HttpInterceptors this._interceptors);

 /**
  * DEPRECATED
  */
 async.Future<String> getString(String url,
     {bool withCredentials, void onProgress(dom.ProgressEvent e), Cache cache}) {
   return request(url,
       withCredentials: withCredentials,
       onProgress: onProgress,
       cache: cache).then((HttpResponse xhr) => xhr.responseText);
 }

/**
 * Returns a [Future<HttpResponse>] when the request is fulfilled.
 *
 * Named Parameters:
 * - method: HTTP method (e.g. 'GET', 'POST', etc)
 * - url: Absolute or relative URL of the resource being requested.
 * - data: Data to be sent as the request message data.
 * - params: Map of strings or objects which will be turned to
 *          `?key1=value1&key2=value2` after the url. If the values are
 *           not strings, they will be JSONified.
 * - headers: Map of strings or functions which return strings representing
 *      HTTP headers to send to the server. If the return value of a function
 *      is null, the header will not be sent.
 * - xsrfHeaderName: TBI
 * - xsrfCookieName: TBI
 * - interceptors: Either a [HttpInterceptor] or a [HttpInterceptors]
 * - cache: Boolean or [Cache].  If true, the default cache will be used.
 * - timeout: deprecated
*/
 async.Future<HttpResponse> call({
   String url,
   String method,
   data,
   Map<String, dynamic> params,
   Map<String, String> headers,
   xsrfHeaderName,
   xsrfCookieName,
   interceptors,
   cache,
   timeout
 }) {
   if (xsrfHeaderName != null || xsrfCookieName != null ||
       timeout != null) {
     throw ['not implemented'];
   }

   method = method.toUpperCase();

   if (headers == null) { headers = {}; }
   defaults.headers.setHeaders(headers, method);

   // Check for functions in headers
   headers.forEach((k,v) {
     if (v is Function) {
       headers[k] = v();
     }
   });

   var serverRequest = (HttpResponseConfig config) {
     assert(config.data == null || config.data is String || config.data is dom.File);

     // Strip content-type if data is undefined
     if (config.data == null) {
       List<String> toRemove = [];
       headers.forEach((h, _) {
         if (h.toUpperCase() == 'CONTENT-TYPE') {
           toRemove.add(h);
         };
       });
       toRemove.forEach((x) => headers.remove(x));
     }


     return request(
         null,
         config: config,
         method: method,
         sendData: config.data,
         requestHeaders: config.headers,
         cache: cache);
   };

   var chain = [[serverRequest, null]];

   var future = new async.Future.value(new HttpResponseConfig(
       url: url,
       params: params,
       headers: headers,
       data: data));

   _interceptors.constructChain(chain);

   if (interceptors != null) {
     if (interceptors is HttpInterceptor) {
       interceptors = new HttpInterceptors.of([interceptors]);
     }
     assert(interceptors is HttpInterceptors);
     interceptors.constructChain(chain);
   }

   chain.forEach((chainFns) {
     future = future.then(chainFns[0], onError: chainFns[1]);
   });

   return future;
 }

 /**
  * Shortcut method for GET requests.  See [call] for a complete description
  * of parameters.
  */
 async.Future<HttpResponse> get(String url, {
   String data,
   Map<String, dynamic> params,
   Map<String, String> headers,
   xsrfHeaderName,
   xsrfCookieName,
   interceptors,
   cache,
   timeout
 }) => call(method: 'GET', url: url, data: data, params: params, headers: headers,
            xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
            interceptors: interceptors,
            cache: cache, timeout: timeout);

 /**
  * Shortcut method for DELETE requests.  See [call] for a complete description
  * of parameters.
  */
 async.Future<HttpResponse> delete(String url, {
   String data,
   Map<String, dynamic> params,
   Map<String, String> headers,
   xsrfHeaderName,
   xsrfCookieName,
   interceptors,
   cache,
   timeout
 }) => call(method: 'DELETE', url: url, data: data, params: params, headers: headers,
            xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
            interceptors: interceptors,
            cache: cache, timeout: timeout);

 /**
  * Shortcut method for HEAD requests.  See [call] for a complete description
  * of parameters.
  */
 async.Future<HttpResponse> head(String url, {
   String data,
   Map<String, dynamic> params,
   Map<String, String> headers,
   xsrfHeaderName,
   xsrfCookieName,
   interceptors,
   cache,
   timeout
 }) => call(method: 'HEAD', url: url, data: data, params: params, headers: headers,
            xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
            interceptors: interceptors,
            cache: cache, timeout: timeout);

 /**
  * Shortcut method for PUT requests.  See [call] for a complete description
  * of parameters.
  */
 async.Future<HttpResponse> put(String url, String data, {
   Map<String, dynamic> params,
   Map<String, String> headers,
   xsrfHeaderName,
   xsrfCookieName,
   interceptors,
   cache,
   timeout
 }) => call(method: 'PUT', url: url, data: data, params: params, headers: headers,
            xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
            interceptors: interceptors,
            cache: cache, timeout: timeout);

 /**
  * Shortcut method for POST requests.  See [call] for a complete description
  * of parameters.
  */
 async.Future<HttpResponse> post(String url, String data, {
   Map<String, dynamic> params,
   Map<String, String> headers,
   xsrfHeaderName,
   xsrfCookieName,
   interceptors,
   cache,
   timeout
 }) => call(method: 'POST', url: url, data: data, params: params, headers: headers,
            xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
            interceptors: interceptors,
            cache: cache, timeout: timeout);

 /**
  * Shortcut method for JSONP requests.  See [call] for a complete description
  * of parameters.
  */
 async.Future<HttpResponse> jsonp(String url, {
   String data,
   Map<String, dynamic> params,
   Map<String, String> headers,
   xsrfHeaderName,
   xsrfCookieName,
   interceptors,
   cache,
   timeout
 }) => call(method: 'JSONP', url: url, data: data, params: params, headers: headers,
            xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
            interceptors: interceptors,
            cache: cache, timeout: timeout);

 /**
  * Parse raw headers into key-value object
  */
 static Map<String, String> parseHeaders(dom.HttpRequest value) {
   var headers = value.getAllResponseHeaders();

   var parsed = {}, key, val, i;

   if (headers == null) return parsed;

   headers.split('\n').forEach((line) {
     i = line.indexOf(':');
     if (i == -1) return;
     key = line.substring(0, i).trim().toLowerCase();
     val = line.substring(i + 1).trim();

     if (key != '') {
       if (parsed.containsKey(key)) {
         parsed[key] += ', ' + val;
       } else {
         parsed[key] = val;
       }
     }
   });
   return parsed;
 }

 /**
  * Returns an [Iterable] of [Future] [HttpResponse]s for the requests
  * that the [Http] service is currently waiting for.
  */
 Iterable<async.Future<HttpResponse> > get pendingRequests {
   return _pendingRequests.values;
 }

 /**
  * DEPRECATED
  */
 async.Future<HttpResponse> request(String rawUrl,
     { HttpResponseConfig config,
       String method: 'GET',
       bool withCredentials: false,
       String responseType,
       String mimeType,
       Map<String, String> requestHeaders,
       sendData,
       void onProgress(dom.ProgressEvent e),
       /*Cache<String, HttpResponse> or false*/ cache }) {
   String url;

   if (config == null) {
     url = _rewriter(rawUrl);
     config = new HttpResponseConfig(url: url);
   } else {
     url = _buildUrl(config.url, config.params);
   }

   if (cache is bool && cache == false) {
     cache = null;
   } else if (cache == null) {
     cache = defaults.cache;
   }
   // We return a pending request only if caching is enabled.
   if (cache != null && _pendingRequests.containsKey(url)) {
     return _pendingRequests[url];
   }
   var cachedValue = (cache != null && method == 'GET') ? cache.get(url) : null;
   if (cachedValue != null) {
     return new async.Future.value(new HttpResponse.copy(cachedValue));
   }

   var result = _backend.request(url,
       method: method,
       withCredentials: withCredentials,
       responseType: responseType,
       mimeType: mimeType,
       requestHeaders: requestHeaders,
       sendData: sendData,
       onProgress: onProgress).then((dom.HttpRequest value) {
     // TODO: Uncomment after apps migrate off of this class.
     // assert(value.status >= 200 && value.status < 300);

     var response = new HttpResponse(
         value.status, value.responseText, parseHeaders(value),
         config);

     if (cache != null) {
       cache.put(url, response);
     }
     _pendingRequests.remove(url);
     return response;
   }, onError: (error) {
     if (error is! dom.ProgressEvent) {
       throw error;
     }
     dom.ProgressEvent event = error;
     _pendingRequests.remove(url);
     dom.HttpRequest request = event.currentTarget;
     return new async.Future.error(
         new HttpResponse(request.status, request.response,
             parseHeaders(request), config));
   });
   _pendingRequests[url] = result;
   return result;
 }

 _buildUrl(String url, Map<String, dynamic> params) {
   if (params == null) return url;
   var parts = [];

   new List.from(params.keys)..sort()..forEach((String key) {
     var value = params[key];
     if (value == null) return;
     if (value is! List) value = [value];

     value.forEach((v) {
       if (v is Map) {
         v = json.stringify(v);
       }
       parts.add(_encodeUriQuery(key) + '=' +
       _encodeUriQuery("$v"));
     });
   });
   return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
 }

 _encodeUriQuery(val, {bool pctEncodeSpaces: false}) =>
   Uri.encodeComponent(val)
     .replaceAll('%40', '@')
     .replaceAll('%3A', ':')
     .replaceAll('%24', r'$')
     .replaceAll('%2C', ',')
     .replaceAll('%20', pctEncodeSpaces ? '%20' : '+');
}

Static Methods

Map<String, String> parseHeaders(HttpRequest value) #

Parse raw headers into key-value object

static Map<String, String> parseHeaders(dom.HttpRequest value) {
 var headers = value.getAllResponseHeaders();

 var parsed = {}, key, val, i;

 if (headers == null) return parsed;

 headers.split('\n').forEach((line) {
   i = line.indexOf(':');
   if (i == -1) return;
   key = line.substring(0, i).trim().toLowerCase();
   val = line.substring(i + 1).trim();

   if (key != '') {
     if (parsed.containsKey(key)) {
       parsed[key] += ', ' + val;
     } else {
       parsed[key] = val;
     }
   }
 });
 return parsed;
}

Constructors

new Http(UrlRewriter _rewriter, HttpBackend _backend, HttpDefaults defaults, HttpInterceptors _interceptors) #

Constructor, useful for DI.

Http(UrlRewriter this._rewriter,
    HttpBackend this._backend,
    HttpDefaults this.defaults,
    HttpInterceptors this._interceptors);

Properties

HttpDefaults defaults #

The defaults for Http

HttpDefaults defaults

final Iterable<Future<HttpResponse>> pendingRequests #

Returns an Iterable of [Future] [HttpResponse]s for the requests that the Http service is currently waiting for.

Iterable<async.Future<HttpResponse> > get pendingRequests {
 return _pendingRequests.values;
}

Methods

Future<HttpResponse> call({String url, String method, data, Map<String, dynamic> params, Map<String, String> headers, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout}) #

Returns a [Future] when the request is fulfilled.

Named Parameters: - method: HTTP method (e.g. 'GET', 'POST', etc) - url: Absolute or relative URL of the resource being requested. - data: Data to be sent as the request message data. - params: Map of strings or objects which will be turned to

     `?key1=value1&key2=value2` after the url. If the values are
      not strings, they will be JSONified.
  • headers: Map of strings or functions which return strings representing HTTP headers to send to the server. If the return value of a function is null, the header will not be sent.

  • xsrfHeaderName: TBI
  • xsrfCookieName: TBI
  • interceptors: Either a HttpInterceptor or a HttpInterceptors
  • cache: Boolean or Cache. If true, the default cache will be used.
  • timeout: deprecated
async.Future<HttpResponse> call({
 String url,
 String method,
 data,
 Map<String, dynamic> params,
 Map<String, String> headers,
 xsrfHeaderName,
 xsrfCookieName,
 interceptors,
 cache,
 timeout
}) {
 if (xsrfHeaderName != null || xsrfCookieName != null ||
     timeout != null) {
   throw ['not implemented'];
 }

 method = method.toUpperCase();

 if (headers == null) { headers = {}; }
 defaults.headers.setHeaders(headers, method);

 // Check for functions in headers
 headers.forEach((k,v) {
   if (v is Function) {
     headers[k] = v();
   }
 });

 var serverRequest = (HttpResponseConfig config) {
   assert(config.data == null || config.data is String || config.data is dom.File);

   // Strip content-type if data is undefined
   if (config.data == null) {
     List<String> toRemove = [];
     headers.forEach((h, _) {
       if (h.toUpperCase() == 'CONTENT-TYPE') {
         toRemove.add(h);
       };
     });
     toRemove.forEach((x) => headers.remove(x));
   }


   return request(
       null,
       config: config,
       method: method,
       sendData: config.data,
       requestHeaders: config.headers,
       cache: cache);
 };

 var chain = [[serverRequest, null]];

 var future = new async.Future.value(new HttpResponseConfig(
     url: url,
     params: params,
     headers: headers,
     data: data));

 _interceptors.constructChain(chain);

 if (interceptors != null) {
   if (interceptors is HttpInterceptor) {
     interceptors = new HttpInterceptors.of([interceptors]);
   }
   assert(interceptors is HttpInterceptors);
   interceptors.constructChain(chain);
 }

 chain.forEach((chainFns) {
   future = future.then(chainFns[0], onError: chainFns[1]);
 });

 return future;
}

Future<HttpResponse> delete(String url, {String data, Map<String, dynamic> params, Map<String, String> headers, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout}) #

Shortcut method for DELETE requests. See call for a complete description of parameters.

async.Future<HttpResponse> delete(String url, {
 String data,
 Map<String, dynamic> params,
 Map<String, String> headers,
 xsrfHeaderName,
 xsrfCookieName,
 interceptors,
 cache,
 timeout
}) => call(method: 'DELETE', url: url, data: data, params: params, headers: headers,
          xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
          interceptors: interceptors,
          cache: cache, timeout: timeout);

Future<HttpResponse> get(String url, {String data, Map<String, dynamic> params, Map<String, String> headers, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout}) #

Shortcut method for GET requests. See call for a complete description of parameters.

async.Future<HttpResponse> get(String url, {
 String data,
 Map<String, dynamic> params,
 Map<String, String> headers,
 xsrfHeaderName,
 xsrfCookieName,
 interceptors,
 cache,
 timeout
}) => call(method: 'GET', url: url, data: data, params: params, headers: headers,
          xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
          interceptors: interceptors,
          cache: cache, timeout: timeout);

Future<String> getString(String url, {bool withCredentials, void onProgress(ProgressEvent e), Cache cache}) #

DEPRECATED

async.Future<String> getString(String url,
   {bool withCredentials, void onProgress(dom.ProgressEvent e), Cache cache}) {
 return request(url,
     withCredentials: withCredentials,
     onProgress: onProgress,
     cache: cache).then((HttpResponse xhr) => xhr.responseText);
}

Shortcut method for HEAD requests. See call for a complete description of parameters.

async.Future<HttpResponse> head(String url, {
 String data,
 Map<String, dynamic> params,
 Map<String, String> headers,
 xsrfHeaderName,
 xsrfCookieName,
 interceptors,
 cache,
 timeout
}) => call(method: 'HEAD', url: url, data: data, params: params, headers: headers,
          xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
          interceptors: interceptors,
          cache: cache, timeout: timeout);

Future<HttpResponse> jsonp(String url, {String data, Map<String, dynamic> params, Map<String, String> headers, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout}) #

Shortcut method for JSONP requests. See call for a complete description of parameters.

async.Future<HttpResponse> jsonp(String url, {
 String data,
 Map<String, dynamic> params,
 Map<String, String> headers,
 xsrfHeaderName,
 xsrfCookieName,
 interceptors,
 cache,
 timeout
}) => call(method: 'JSONP', url: url, data: data, params: params, headers: headers,
          xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
          interceptors: interceptors,
          cache: cache, timeout: timeout);

Future<HttpResponse> post(String url, String data, {Map<String, dynamic> params, Map<String, String> headers, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout}) #

Shortcut method for POST requests. See call for a complete description of parameters.

async.Future<HttpResponse> post(String url, String data, {
 Map<String, dynamic> params,
 Map<String, String> headers,
 xsrfHeaderName,
 xsrfCookieName,
 interceptors,
 cache,
 timeout
}) => call(method: 'POST', url: url, data: data, params: params, headers: headers,
          xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
          interceptors: interceptors,
          cache: cache, timeout: timeout);

Future<HttpResponse> put(String url, String data, {Map<String, dynamic> params, Map<String, String> headers, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout}) #

Shortcut method for PUT requests. See call for a complete description of parameters.

async.Future<HttpResponse> put(String url, String data, {
 Map<String, dynamic> params,
 Map<String, String> headers,
 xsrfHeaderName,
 xsrfCookieName,
 interceptors,
 cache,
 timeout
}) => call(method: 'PUT', url: url, data: data, params: params, headers: headers,
          xsrfHeaderName: xsrfHeaderName, xsrfCookieName: xsrfCookieName,
          interceptors: interceptors,
          cache: cache, timeout: timeout);

Future<HttpResponse> request(String rawUrl, {HttpResponseConfig config, String method: 'GET', bool withCredentials: false, String responseType, String mimeType, Map<String, String> requestHeaders, sendData, void onProgress(ProgressEvent e), cache}) #

DEPRECATED

async.Future<HttpResponse> request(String rawUrl,
   { HttpResponseConfig config,
     String method: 'GET',
     bool withCredentials: false,
     String responseType,
     String mimeType,
     Map<String, String> requestHeaders,
     sendData,
     void onProgress(dom.ProgressEvent e),
     /*Cache<String, HttpResponse> or false*/ cache }) {
 String url;

 if (config == null) {
   url = _rewriter(rawUrl);
   config = new HttpResponseConfig(url: url);
 } else {
   url = _buildUrl(config.url, config.params);
 }

 if (cache is bool && cache == false) {
   cache = null;
 } else if (cache == null) {
   cache = defaults.cache;
 }
 // We return a pending request only if caching is enabled.
 if (cache != null && _pendingRequests.containsKey(url)) {
   return _pendingRequests[url];
 }
 var cachedValue = (cache != null && method == 'GET') ? cache.get(url) : null;
 if (cachedValue != null) {
   return new async.Future.value(new HttpResponse.copy(cachedValue));
 }

 var result = _backend.request(url,
     method: method,
     withCredentials: withCredentials,
     responseType: responseType,
     mimeType: mimeType,
     requestHeaders: requestHeaders,
     sendData: sendData,
     onProgress: onProgress).then((dom.HttpRequest value) {
   // TODO: Uncomment after apps migrate off of this class.
   // assert(value.status >= 200 && value.status < 300);

   var response = new HttpResponse(
       value.status, value.responseText, parseHeaders(value),
       config);

   if (cache != null) {
     cache.put(url, response);
   }
   _pendingRequests.remove(url);
   return response;
 }, onError: (error) {
   if (error is! dom.ProgressEvent) {
     throw error;
   }
   dom.ProgressEvent event = error;
   _pendingRequests.remove(url);
   dom.HttpRequest request = event.currentTarget;
   return new async.Future.error(
       new HttpResponse(request.status, request.response,
           parseHeaders(request), config));
 });
 _pendingRequests[url] = result;
 return result;
}