API Docs for: 1.5.0
Show:

File: src/connections/XmlHttpRequestConnection.js

/* global define */
define(["structures/Response", "structures/CAPIError"], function (Response, CAPIError) {
    "use strict";

    /**
     * Creates an instance of XmlHttpRequestConnection object
     * This connection class handles low-level implementation of XHR connection for generic (non-Microsoft) browsers
     *
     * @class XmlHttpRequestConnection
     * @constructor
     */
    var XmlHttpRequestConnection = function () {
            this._xhr = new XMLHttpRequest();
        },
        _assignCallback = function(xhr, eventName, callback) {
            if (typeof callback !== 'function') {
                return xhr;
            }

            xhr[eventName] = callback;

            return xhr;
        };

    /**
     * Basic request implemented via XHR technique
     *
     * @method execute
     * @param request {Request} structure containing all needed params and data
     * @param [requestEventHandlers] {Object} a set of callbacks to apply on a specific XHR event like onload, onerror, onprogress, etc.
     * @param callback {Function} function, which will be executed on request success
     */
    XmlHttpRequestConnection.prototype.execute = function (request, requestEventHandlers, callback) {
        var XHR = this._xhr,
            headerType,
            method = request.method,
            standardMethods = {"OPTIONS": 1, "GET": 1, "HEAD": 1, "POST": 1, "PUT": 1, "DELETE": 1, "TRACE": 1};

        if (typeof requestEventHandlers === 'function') {
            callback = requestEventHandlers;
            requestEventHandlers = {};
        }

        // Create the state change handler:
        XHR.onreadystatechange = function () {
            var response;

            if (XHR.readyState != 4) {return;} // Not ready yet

            response = new Response({
                status: XHR.status,
                headers: XHR.getAllResponseHeaders(),
                body: XHR.responseText,
                xhr: XHR,
            });
            if (XHR.status >= 400 || !XHR.status) {
                callback(
                    new CAPIError("Connection error : " + XHR.status + ".", {request: request}),
                    response
                );
                return;
            }
            callback(false, response);
        };

        // Send non-standard HTTP methods as headers using POST.
        // Avoids problems with conservative proxies, HTTP security tools and limited web servers.
        if (standardMethods[method.toUpperCase()] !== 1) {
            method = "POST";
        }

        if (requestEventHandlers && Object.keys(requestEventHandlers).length) {
            if (requestEventHandlers.upload && Object.keys(requestEventHandlers.upload).length) {
                _assignCallback(XHR.upload, 'onloadstart', requestEventHandlers.upload.onloadstart);
                _assignCallback(XHR.upload, 'onload', requestEventHandlers.upload.onload);
                _assignCallback(XHR.upload, 'onloadend', requestEventHandlers.upload.onloadend);
                _assignCallback(XHR.upload, 'onprogress', requestEventHandlers.upload.onprogress);
                _assignCallback(XHR.upload, 'onabort', requestEventHandlers.upload.onabort);
                _assignCallback(XHR.upload, 'onerror', requestEventHandlers.upload.onerror);
                _assignCallback(XHR.upload, 'ontimeout', requestEventHandlers.upload.ontimeout);
            }

            _assignCallback(XHR, 'onloadstart', requestEventHandlers.onloadstart);
            _assignCallback(XHR, 'onload', requestEventHandlers.onload);
            _assignCallback(XHR, 'onloadend', requestEventHandlers.onloadend);
            _assignCallback(XHR, 'onprogress', requestEventHandlers.onprogress);
            _assignCallback(XHR, 'onabort', requestEventHandlers.onabort);
            _assignCallback(XHR, 'onerror', requestEventHandlers.onerror);
            _assignCallback(XHR, 'ontimeout', requestEventHandlers.ontimeout);
        }

        if (request.httpBasicAuth) {
            XHR.open(method, request.url, true, request.login, request.password);
        } else {
            XHR.open(method, request.url, true);
        }

        if (method !== request.method) {
            XHR.setRequestHeader("X-HTTP-Method-Override", request.method);
        }

        for (headerType in request.headers) {
            if (request.headers.hasOwnProperty(headerType)) {
                XHR.setRequestHeader(
                    headerType,
                    request.headers[headerType]
                );
            }
        }
        XHR.send(request.body);
    };

    /**
     * Connection checks itself for compatibility with running environment
     *
     * @method isCompatible
     * @static
     * @return {Boolean} whether the connection is compatible with current environment
     */
    XmlHttpRequestConnection.isCompatible = function () {
        return !!window.XMLHttpRequest;
    };

    return XmlHttpRequestConnection;
});