aboutsummaryrefslogtreecommitdiffstats
path: root/src/ajax/xhr.js
blob: c7b057a6efa0a219369098c3c7ebf98617594214 (plain)
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
import { jQuery } from "../core.js";

import "../ajax.js";

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

var xhrSuccessStatus = {

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

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

	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 trac-8605, trac-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 ) {

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

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