Generates an XHR request. The $xhr service delegates all requests to
$browser.xhr()
and adds error handling and security features.
While $xhr service provides nicer api than raw XmlHttpRequest, it is still considered a lower
level api in angular. For a higher level abstraction that utilizes $xhr
, please check out the
$resource
service.
If no error callback
is specified, XHR response with response code other then 2xx
will be
delegated to $xhr.error
. The $xhr.error
can intercept the
request and process it in application specific way, or resume normal execution by calling the
request success
method.
The $xhr service will automatically add certain http headers to all requests. These defaults can
be fully configured by accessing the $xhr.defaults.headers
configuration object, which
currently contains this default configuration:
$xhr.defaults.headers.common
(headers that are common for all requests):
Accept: application/json, text/plain, *\/*
X-Requested-With: XMLHttpRequest
$xhr.defaults.headers.post
(header defaults for HTTP POST requests):
Content-Type: application/x-www-form-urlencoded
To add or overwrite these defaults, simple add or remove a property from this configuration
object. To add headers for an HTTP method other than POST, simple create a new object with name
equal to the lowercased http method name, e.g. $xhr.defaults.headers.get['My-Header']='value'
.
When designing web applications your design needs to consider security threats from JSON Vulnerability and XSRF. Both server and the client must cooperate in order to eliminate these threats. Angular comes pre-configured with strategies that address these issues, but for this to work backend server cooperation is required.
A JSON Vulnerability allows third party web-site to turn your JSON resource URL into
JSONP request under some conditions. To
counter this your server can prefix all JSON requests with following string ")]}',\n"
.
Angular will automatically strip the prefix before processing it as JSON.
For example if your server needs to return:
['one','two']
which is vulnerable to attack, your server can return:
)]}', ['one','two']
angular will strip the prefix, before processing the JSON.
XSRF is a technique by which an
unauthorized site can gain your user's private data. Angular provides following mechanism to
counter XSRF. When performing XHR requests, the $xhr service reads a token from a cookie
called XSRF-TOKEN
and sets it as the HTTP header X-XSRF-TOKEN
. Since only JavaScript that
runs on your domain could read the cookie, your server can be assured that the XHR came from
JavaScript running on your domain.
To take advantage of this, your server needs to set a token in a JavaScript readable session
cookie called XSRF-TOKEN
on first HTTP GET request. On subsequent non-GET requests the server
can verify that the cookie matches X-XSRF-TOKEN
HTTP header, and therefore be sure that only
JavaScript running on your domain could have read the token. The token must be unique for each
user and must be verifiable by the server (to prevent the JavaScript making up its own tokens).
We recommend that the token is a digest of your site's authentication cookie with
salt for added security.
$browser
$xhr delegates all XHR requests to the $browser.xhr()
. A mock version
of the $browser exists which allows setting expectations on XHR requests
in your tests
$xhr.error
$xhr delegates all non 2xx
response code to this service.
$log
$xhr delegates all exceptions to $log.error()
.
$updateView
After a server response the view needs to be updated for data-binding to take effect.
$xhr(method, url[, post], success, error);
method – {string} –
HTTP method to use. Valid values are: GET
, POST
, PUT
, DELETE
, and
JSON
. JSON
is a special case which causes a
JSONP cross domain request using script tag
insertion.
url – {string} –
Relative or absolute URL specifying the destination of the request. For
JSON
requests, url
should include JSON_CALLBACK
string to be replaced with a name of an
angular generated callback function.
post(optional) – {(string|Object)} –
Request content as either a string or an object to be stringified as JSON before sent to the server.
success – {function(number, (string|Object), Function)} –
A function to be called when the response is received. The success function will be called with:
angular.service.$xhr.error
service (or custom error callback).error – {function(number, (string|Object))} –
A function to be called if the response code is not 2xx.. Accepts the same arguments as success, above.
<script> function FetchCntl($xhr) { var self = this; this.fetch = function() { self.code = null; self.response = null; $xhr(self.method, self.url, function(code, response) { self.code = code; self.response = response; }, function(code, response) { self.code = code; self.response = response || "Request failed"; }); }; this.updateModel = function(method, url) { self.method = method; self.url = url; }; } FetchCntl.$inject = ['$xhr']; </script> <div ng:controller="FetchCntl"> <select name="method"> <option>GET</option> <option>JSON</option> </select> <input type="text" name="url" value="index.html" size="80"/> <button ng:click="fetch()">fetch</button><br> <button ng:click="updateModel('GET', 'index.html')">Sample GET</button> <button ng:click="updateModel('JSON', 'https://www.googleapis.com/buzz/v1/activities/googlebuzz/@self?alt=json&callback=JSON_CALLBACK')">Sample JSONP (Buzz API)</button> <button ng:click="updateModel('JSON', 'https://www.invalid_JSONP_request.com&callback=JSON_CALLBACK')">Invalid JSONP</button> <pre>code={{code}}</pre> <pre>response={{response}}</pre> </div>
it('should make xhr GET request', function() { element(':button:contains("Sample GET")').click(); element(':button:contains("fetch")').click(); expect(binding('code')).toBe('code=200'); expect(binding('response')).toMatch(/angularjs.org/); }); it('should make JSONP request to the Buzz API', function() { element(':button:contains("Buzz API")').click(); element(':button:contains("fetch")').click(); expect(binding('code')).toBe('code=200'); expect(binding('response')).toMatch(/buzz-feed/); }); it('should make JSONP request to invalid URL and invoke the error handler', function() { element(':button:contains("Invalid JSONP")').click(); element(':button:contains("fetch")').click(); expect(binding('code')).toBe('code='); expect(binding('response')).toBe('response=Request failed'); });