angular.js/src/service/httpBackend.js
Vojta Jina 3171f21591 fix($httpBackend): Set current url, if not defined or empty string
Reason to fix this was the fact that with undefined url, it ended up with weird exception
(Cannot call method 'replace' of undefined), which was more confusing than helpful.

jQuery.ajax() does request to current url, if url is not specified, so I decided for this solution.
2012-02-23 22:50:02 -08:00

99 lines
3.4 KiB
JavaScript

var XHR = window.XMLHttpRequest || function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
throw new Error("This browser does not support XMLHttpRequest.");
};
/**
* @ngdoc object
* @name angular.module.ng.$httpBackend
* @requires $browser
* @requires $window
* @requires $document
*
* @description
* HTTP backend used by the {@link angular.module.ng.$http service} that delegates to
* XMLHttpRequest object or JSONP and deals with browser incompatibilities.
*
* You should never need to use this service directly, instead use the higher-level abstractions:
* {@link angular.module.ng.$http $http} or {@link angular.module.ng.$resource $resource}.
*
* During testing this implementation is swapped with {@link angular.module.ngMock.$httpBackend mock
* $httpBackend} which can be trained with responses.
*/
function $HttpBackendProvider() {
this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,
$document[0].body, $window.location.protocol.replace(':', ''));
}];
}
function createHttpBackend($browser, XHR, $browserDefer, callbacks, body, locationProtocol) {
// TODO(vojta): fix the signature
return function(method, url, post, callback, headers, timeout) {
$browser.$$incOutstandingRequestCount();
url = url || $browser.url();
if (lowercase(method) == 'jsonp') {
var callbackId = '_' + (callbacks.counter++).toString(36);
callbacks[callbackId] = function(data) {
callbacks[callbackId].data = data;
};
var script = $browser.addJs(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
function() {
if (callbacks[callbackId].data) {
completeRequest(callback, 200, callbacks[callbackId].data);
} else {
completeRequest(callback, -2);
}
delete callbacks[callbackId];
body.removeChild(script);
});
} else {
var xhr = new XHR();
xhr.open(method, url, true);
forEach(headers, function(value, key) {
if (value) xhr.setRequestHeader(key, value);
});
var status;
// In IE6 and 7, this might be called synchronously when xhr.send below is called and the
// response is in the cache. the promise api will ensure that to the app code the api is
// always async
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
completeRequest(
callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());
}
};
xhr.send(post || '');
if (timeout > 0) {
$browserDefer(function() {
status = -1;
xhr.abort();
}, timeout);
}
}
function completeRequest(callback, status, response, headersString) {
// URL_MATCH is defined in src/service/location.js
var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];
// fix status code for file protocol (it's always 0)
status = (protocol == 'file') ? (response ? 200 : 404) : status;
// normalize IE bug (http://bugs.jquery.com/ticket/1450)
status = status == 1223 ? 204 : status;
callback(status, response, headersString);
$browser.$$completeOutstandingRequest(noop);
}
};
}