jquery/jquery

View on GitHub
src/ajax/xhr.js

Summary

Maintainability
A
2 hrs
Test Coverage
define( [
    "../core",
    "../ajax"
], function( jQuery ) {

"use strict";

jQuery.ajaxSettings.xhr = function() {
    try {
        return new window.XMLHttpRequest();
    } catch ( e ) {}
};

var xhrSuccessStatus = {

        // File protocol always yields status code 0, assume 200
        0: 200
    };

jQuery.ajaxTransport( function( options ) {
    var callback;

    // Cross domain only allowed if supported through XMLHttpRequest
    return {
        send: function( headers, complete ) {
            var i,
                xhr = options.xhr();

            xhr.open(
                options.type,
                options.url,
                options.async,
                options.username,
                options.password
            );

            // Apply custom fields if provided
            if ( options.xhrFields ) {
                for ( i in options.xhrFields ) {
                    xhr[ i ] = options.xhrFields[ i ];
                }
            }

            // Override mime type if needed
            if ( options.mimeType && xhr.overrideMimeType ) {
                xhr.overrideMimeType( options.mimeType );
            }

            // X-Requested-With header
            // For cross-domain requests, seeing as conditions for a preflight are
            // akin to a jigsaw puzzle, we simply never set it to be sure.
            // (it can always be set on a per-request basis or even using ajaxSetup)
            // For same-domain requests, won't change header if already provided.
            if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
                headers[ "X-Requested-With" ] = "XMLHttpRequest";
            }

            // Set headers
            for ( i in headers ) {
                xhr.setRequestHeader( i, headers[ i ] );
            }

            // Callback
            callback = function( type ) {
                return function() {
                    if ( callback ) {
                        callback = xhr.onload = xhr.onerror = xhr.onabort = xhr.ontimeout = null;

                        if ( type === "abort" ) {
                            xhr.abort();
                        } else if ( type === "error" ) {
                            complete(

                                // File: protocol always yields status 0; see #8605, #14207
                                xhr.status,
                                xhr.statusText
                            );
                        } else {
                            complete(
                                xhrSuccessStatus[ xhr.status ] || xhr.status,
                                xhr.statusText,

                                // For XHR2 non-text, let the caller handle it (gh-2498)
                                ( xhr.responseType || "text" ) === "text" ?
                                    { text: xhr.responseText } :
                                    { binary: xhr.response },
                                xhr.getAllResponseHeaders()
                            );
                        }
                    }
                };
            };

            // Listen to events
            xhr.onload = callback();
            xhr.onabort = xhr.onerror = xhr.ontimeout = callback( "error" );

            // Create the abort callback
            callback = callback( "abort" );

            try {

                // Do send the request (this may raise an exception)
                xhr.send( options.hasContent && options.data || null );
            } catch ( e ) {

                // #14683: Only rethrow if this hasn't been notified as an error yet
                if ( callback ) {
                    throw e;
                }
            }
        },

        abort: function() {
            if ( callback ) {
                callback();
            }
        }
    };
} );

} );