all files / scripts/utils/ http.js

94.2% Statements 65/69
86.96% Branches 40/46
92.86% Functions 13/14
94.2% Lines 65/69
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150      51×     33×     32×     107× 101× 101× 100× 100×   100×   100×     100× 75×     100× 75×                   75×           75×       75×     75×       75×     75×   75×             100× 100×   100×   100×       107×     104×     102×               12×       80×   73× 29×   44×       73×       73× 72×       72×                  
'use strict';
 
var urlUtils = require('./urlUtils');
var utilities = require('./utilityFunctions');
 
function HttpRequestError(message) {
  this.message = 'HttpRequest Error: ' + (message || '');
}
HttpRequestError.prototype = new Error();
HttpRequestError.prototype.name = "HttpRequest Error";
 
function HttpRequest(createXhr) {
  if (!utilities.isFunction(createXhr)) {
    throw new HttpRequestError('Missing XMLHttpRequest factory method');
  }
 
  this.createXhr = createXhr;
}
 
HttpRequest.prototype.run = function (method, url, callback, options) {
  sanityCheck(url, callback, options);
  var timeout, timeoutId;
  var xhr = this.createXhr();
  options = options || {};
  timeout = utilities.isNumber(options.timeout) ? options.timeout : 0;
 
  xhr.open(method, urlUtils.urlParts(url).href, true);
 
  if (options.headers) {
    setHeaders(xhr, options.headers);
  }
 
  if (options.withCredentials) {
    xhr.withCredentials = true;
  }
 
  xhr.onload = function () {
    var statusText, response, status;
 
    /**
     * The only way to do a secure request on IE8 and IE9 is with the XDomainRequest object. Unfortunately, microsoft is
     * so nice that decided that the status property and the 'getAllResponseHeaders' method where not needed so we have to
     * fake them. If the request gets done with an XDomainRequest instance, we will assume that there are no headers and
     * the status will always be 200. If you don't like it, DO NOT USE ANCIENT BROWSERS!!!
     *
     * For mor info go to: https://msdn.microsoft.com/en-us/library/cc288060(v=vs.85).aspx
     */
    Iif (!xhr.getAllResponseHeaders) {
      xhr.getAllResponseHeaders = function () {
        return null;
      };
    }
 
    Iif (!xhr.status) {
      xhr.status = 200;
    }
 
    if (utilities.isDefined(timeoutId)) {
      clearTimeout(timeoutId);
      timeoutId = undefined;
    }
 
    statusText = xhr.statusText || '';
 
    // responseText is the old-school way of retrieving response (supported by IE8 & 9)
    // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
    response = ('response' in xhr) ? xhr.response : xhr.responseText;
 
    // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
    status = xhr.status === 1223 ? 204 : xhr.status;
 
    callback(
      status,
      response,
      xhr.getAllResponseHeaders(),
      statusText);
  };
 
  xhr.onerror = requestError;
  xhr.onabort = requestError;
 
  xhr.send();
 
  if (timeout > 0) {
    timeoutId = setTimeout(function () {
      xhr && xhr.abort();
    }, timeout);
  }
 
  function sanityCheck(url, callback, options) {
    if (!utilities.isString(url) || utilities.isEmptyString(url)) {
      throw new HttpRequestError("Invalid url '" + url + "'");
    }
 
    if (!utilities.isFunction(callback)) {
      throw new HttpRequestError("Invalid handler '" + callback + "' for the http request");
    }
 
    if (utilities.isDefined(options) && !utilities.isObject(options)) {
      throw new HttpRequestError("Invalid options map '" + options + "'");
    }
  }
 
  function setHeaders(xhr, headers) {
    utilities.forEach(headers, function (value, key) {
      Eif (utilities.isDefined(value)) {
        xhr.setRequestHeader(key, value);
      }
    });
  }
 
  function requestError() {
    callback(-1, null, null, '');
  }
};
 
HttpRequest.prototype.get = function (url, callback, options) {
  this.run('GET', url, processResponse, options);
 
  function processResponse(status, response, headersString, statusText) {
    if (isSuccess(status)) {
      callback(null, response, status, headersString, statusText);
    } else {
      callback(new HttpRequestError(statusText), response, status, headersString, statusText);
    }
  }
 
  function isSuccess(status) {
    return 200 <= status && status < 300;
  }
};
 
function createXhr() {
  var xhr = new XMLHttpRequest();
  Iif (!("withCredentials" in xhr)) {
    // XDomainRequest for IE.
    xhr = new XDomainRequest();
  }
  return xhr;
}
 
var http = new HttpRequest(createXhr);
 
module.exports = {
  http: http,
  HttpRequest: HttpRequest,
  HttpRequestError: HttpRequestError,
  createXhr: createXhr
};