# angular.service.$xhr

Work in Progress This page is currently being revised. It might be incomplete or contain inaccuracies.

## Description

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.

### Error handling

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.

### HTTP Headers

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'`.

### Security Considerations

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.

#### JSON Vulnerability Protection

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.

#### Cross Site Request Forgery (XSRF) Protection

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.

## Dependencies

- `$browser`

  $xhr delegates all XHR requests to the `$browser.xhr()`. A mock version of the $browser exists which allows setting expectaitions 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.

## Usage

    $xhr(method, url[, post], success, error);

### Parameters

- `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))} –`

  A function to be called when the response is received. The success function will be called with:

  - {number} code HTTP status code of the response. This will currently always be 200, since all non-200 responses are routed to `angular.service.$xhr.error` service (or custom error callback).
  - {string|Object} response Response object as string or an Object if the response was in JSON format.
- `error – {function(number, (string|Object))} –`

  A function to be called if the response code is not 2xx.. Accepts the same arguments as success, above.

## Example

      <script>
        function FetchCntl($xhr) {
          var self = this;

          this.fetch = function() {
            self.clear();
            $xhr(self.method, self.url, function(code, response) {
              self.code = code;
              self.response = response;
            });
          };

          this.clear = function() {
            self.code = null;
            self.response = null;
          };
        }
        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"/><br/>
        <button ng:click="fetch()">fetch</button>
        <button ng:click="clear()">clear</button>
        <a href="" ng:click="method='GET'; url='index.html'">sample</a>
        <a href="" ng:click="method='JSON'; url='https://www.googleapis.com/buzz/v1/activities/googlebuzz/@self?alt=json&callback=JSON_CALLBACK'">buzz</a>
        <pre>code={{code}}</pre>
        <pre>response={{response}}</pre>
      </div>