readme.md
# Angular HTTP ETag
[![GitHub release](https://img.shields.io/github/release/shaungrady/angular-http-etag.svg?style=flat-square)](https://github.com/shaungrady/angular-http-etag/releases)
[![npm](https://img.shields.io/npm/v/angular-http-etag.svg?style=flat-square)](https://www.npmjs.com/package/angular-http-etag)
[![npm](https://img.shields.io/npm/dm/angular-http-etag.svg?style=flat-square)](https://www.npmjs.com/package/angular-http-etag)
[![JS style](https://img.shields.io/badge/js%20style-standard-orange.svg?style=flat-square)](https://standardjs.com/)
[![Travis](https://img.shields.io/travis/shaungrady/angular-http-etag.svg?style=flat-square)](https://travis-ci.org/shaungrady/angular-http-etag)
[![Test Coverage](https://api.codeclimate.com/v1/badges/cd179568de4ea601823f/test_coverage)](https://codeclimate.com/github/shaungrady/angular-http-etag/test_coverage)
[![David](https://img.shields.io/david/shaungrady/angular-http-etag.svg?style=flat-square)](https://david-dm.org/shaungrady/angular-http-etag)
[![David](https://img.shields.io/david/peer/shaungrady/angular-http-etag.svg?style=flat-square)](https://david-dm.org/shaungrady/angular-http-etag?type=peer)
Tested: IE 9+; Edge 13; Chrome 29, 50+; Firefox 46+; Safari 7+; iOS 9.2+; Android 4.4, 5.1.
---
Easy ETag-based caching for `$http` service requests! Increase responsiveness, decrease bandwidth usage.
* Caches ETag headers and sends them back to the server in the `If-None-Match` header.
* Caches response data with flexible cache configuration.
* Support for `$cacheFactory`, `sessionStorage`, and `localStorage` caches out-of-the-box.
* Easily [adaptable][Cache Service Adapters] for other third-party cache services.
* Compatible with AngularJS 1.2–1.6.
**Example Usage:**
``` javascript
angular
.module('myApp', [
'http-etag'
])
.config(function (httpEtagProvider) {
httpEtagProvider
.defineCache('persistentCache', {
cacheService: 'localStorage'
})
})
.controller('MyCtrl', function ($http) {
var self = this
$http
.get('/my_data.json', {
etagCache: 'persistentCache'
})
.then(function success (response, itemCache) {
var data = response.data
// Modify the data from the server
data._fullName = data.first_name + ' ' + data.last_name
// Update the cache with the modified data
itemCache.set(data)
// Assign to controller property
self.fullName = data._fullName
}, function error (response) {
if (response.status != 304) alert('Request error')
})
// Synchronous method called if request was previously cached
// status == 'cached'; headers === undefined;
.ifCached(function (response, itemCache) {
self.fullName = data._fullName
})
})
```
_Need more information on how ETags work? [Read this](http://bitworking.org/news/ETags__This_stuff_matters)._
## Detailed Documentation
- [Service Provider]
- [Service]
- [$http Decorator]
- [Cache Service Adapters]
[Service Provider]: https://github.com/shaungrady/angular-http-etag/blob/master/docs/service_provider.md
[Service]: https://github.com/shaungrady/angular-http-etag/blob/master/docs/service.md
[$http Decorator]: https://github.com/shaungrady/angular-http-etag/blob/master/docs/http_decorator.md
[Cache Service Adapters]: https://github.com/shaungrady/angular-http-etag/blob/master/docs/cache_service_adapters.md
## Quick Guide
### Install Module
``` bash
$ npm install angular-http-etag
```
Or download from [master/release](https://github.com/shaungrady/angular-http-etag/tree/master/release)
### Include Dependency
Include `'http-etag'` in your module's dependencies.
``` javascript
// The node module exports the string 'http-etag'...
angular.module('myApp', [
require('angular-http-etag')
])
```
``` javascript
// ... otherwise, include the code first then the module name
angular.module('myApp', [
'http-etag'
])
```
### Define Caches
``` javascript
.config(function ('httpEtagProvider') {
httpEtagProvider
.defineCache('persistentCache', {
cacheService: 'localStorage'
})
.defineCache('sessionCache', {
cacheService: 'sessionStorage'
})
.defineCache('memoryCache', {
cacheService: '$cacheFactory',
cacheOptions: {
number: 50 // LRU cache
},
deepCopy: true // $cacheFactory copies by reference by default
})
})
```
If you so desire, you can define your own caches. The default cache uses `$cacheFactory`
and is limited to 25 cache items (Least Recently Used algorithm).
Define the caches you'd like to use by using `defineCache(cacheId[, config])`, passing a cache ID
followed by the cache configuration. The configuration you pass will extend the
default configuration, which can be set using the `setDefaultCacheConfig(config)`
method. If you don't pass a config, a new cache will be defined using the default config.
_See more in the [Service Provider] documentation._
### Cache Requests
Using the default cache with default configuration and an automatically generated cache itemKey based on the request:
``` javascript
$http.get('/data', {
etagCache: true
})
.then(responseHandler)
.ifCached(responseHandler)
function responseHandler (response, itemCache) {
// Differentiating between cached and successful request responses
var isCached = response.status === 'cached'
// itemCache is a cache object bound to the cache item associated with this request.
itemCache.info()
// { id: 'httpEtagCache',
// itemKey: '/data',
// deepCopy: false,
// cacheResponseData: true,
// cacheService: '$cacheFactory',
// cacheOptions: { number: 25 } }
}
```
Using a defined cache from the previous section and an automatically generated cache itemKey:
``` javascript
$http.get('/data', {
etagCache: 'persistentCache'
})
.then(responseHandler)
.ifCached(responseHandler)
function responseHandler (response, itemCache) {
itemCache.info()
// { id: 'persistentCache',
// itemKey: '/data',
// deepCopy: false,
// cacheResponseData: true,
// cacheService: 'localStorage',
// cacheOptions: { number: 25 } }
}
```
Using a defined cache and a specified key for the cache item:
``` javascript
$http.get('/data', {
etagCache: {
id: 'persistentCache',
itemKey: 'whatFineKeyYouHave'
}
})
.then(responseHandler)
.ifCached(responseHandler)
function responseHandler (response, itemCache) {
itemCache.info()
// { id: 'persistentCache',
// itemKey: 'whatFineKeyYouHave',
// deepCopy: false,
// cacheResponseData: true,
// cacheService: 'localStorage',
// cacheOptions: { number: 25 } }
}
```
The `etagCache` property also accepts a function that returns on of the values
demonstrated; a `boolean`, a `string`, or an `object`.
_See more in the [$http Decorator] and [Service] documentation._
## Contributing
Write an issue. Then, possibly, hopefully...
1. Fork the repo.
2. Make a branch.
3. Write the code.
3. Write the tests.
3. Run tests. (`npm test`)
3. Open a pull request.