# request method

Future<HttpRequest> request (String url, { String method, bool withCredentials, String responseType, String mimeType, Map<String, String> requestHeaders, dynamic sendData, void onProgress(ProgressEvent e) })

Creates and sends a URL request for the specified `url`.

By default `request` will perform an HTTP GET request, but a different method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the `method` parameter. (See also HttpRequest.postFormData for `POST` requests only.

The Future is completed when the response is available.

If specified, `sendData` will send data in the form of a ByteBuffer, Blob, Document, String, or FormData along with the HttpRequest.

If specified, `responseType` sets the desired response format for the request. By default it is String, but can also be 'arraybuffer', 'blob', 'document', 'json', or 'text'. See also HttpRequest.responseType for more information.

The `withCredentials` parameter specified that credentials such as a cookie (already) set in the header or authorization headers should be specified for the request. Details to keep in mind when using credentials:

- Using credentials is only useful for cross-origin requests.
- The `Access-Control-Allow-Origin` header of `url` cannot contain a wildcard (*).
- The `Access-Control-Allow-Credentials` header of `url` must be set to true.
- If `Access-Control-Expose-Headers` has not been set to true, only a subset of all the response headers will be returned when calling `getAllRequestHeaders`.

The following is equivalent to the getString sample above:

    var name = Uri.encodeQueryComponent('John');
    var id = Uri.encodeQueryComponent('42');
    HttpRequest.request('users.json?name=$name&id=$id')
      .then((HttpRequest resp) {
        // Do something with the response.
    });

Here's an example of submitting an entire form with FormData.

    var myForm = querySelector('form#myForm');
    var data = new FormData(myForm);
    HttpRequest.request('/submit', method: 'POST', sendData: data)
      .then((HttpRequest resp) {
        // Do something with the response.
    });

Note that requests for file:// URIs are only supported by Chrome extensions with appropriate permissions in their manifest. Requests to file:// URIs will also never fail- the Future will always complete successfully, even when the file cannot be found.

See also: authorization headers.

## Implementation

    static Future<HttpRequest> request(String url,
        {String method,
        bool withCredentials,
        String responseType,
        String mimeType,
        Map<String, String> requestHeaders,
        sendData,
        void onProgress(ProgressEvent e)}) {
      var completer = new Completer<HttpRequest>();

      var xhr = new HttpRequest();
      if (method == null) {
        method = 'GET';
      }
      xhr.open(method, url, async: true);

      if (withCredentials != null) {
        xhr.withCredentials = withCredentials;
      }

      if (responseType != null) {
        xhr.responseType = responseType;
      }

      if (mimeType != null) {
        xhr.overrideMimeType(mimeType);
      }

      if (requestHeaders != null) {
        requestHeaders.forEach((header, value) {
          xhr.setRequestHeader(header, value);
        });
      }

      if (onProgress != null) {
        xhr.onProgress.listen(onProgress);
      }

      xhr.onLoad.listen((e) {
        var accepted = xhr.status >= 200 && xhr.status < 300;
        var fileUri = xhr.status == 0; // file:// URIs have status of 0.
        var notModified = xhr.status == 304;
        // Redirect status is specified up to 307, but others have been used in
        // practice. Notably Google Drive uses 308 Resume Incomplete for
        // resumable uploads, and it's also been used as a redirect. The
        // redirect case will be handled by the browser before it gets to us,
        // so if we see it we should pass it through to the user.
        var unknownRedirect = xhr.status > 307 && xhr.status < 400;

        if (accepted || fileUri || notModified || unknownRedirect) {
          completer.complete(xhr);
        } else {
          completer.completeError(e);
        }
      });

      xhr.onError.listen(completer.completeError);

      if (sendData != null) {
        xhr.send(sendData);
      } else {
        xhr.send();
      }

      return completer.future;
    }