ETag for GET in angular js - do i need to check on server-side

how to fix 304 not modified angular
etag header
angular http etag example
etag in rest api
etag vs last-modified
how to use etag
cache json response in browser
how to implement if-modified-since http header

I'm trying to implement etag for a GET request in angular JS, So far I've seen and restangular(a complicated one but good). They all say it gives build in support for GET request, which i think means i don't have to code anything on server side(which is in c#.NET).

Am i right in assuming that, OR i've to use CacheCow or something to look for ETAG in the header and send 304 response.

Just a background, I've to use ETAG instead of cache(angular), so as to get latest data from server.

I'm the author of angular-http-etag, so I can only speak directly to the functionality of that module. It decorates Angular's $http service to allow you to specify requests that you'd like to cache. Here's the usage example I provide in the

  .module('myApp', [
  .config(function (httpEtagProvider) {
      .defineCache('persistentCache', {
        cacheService: 'localStorage'

  .controller('MyCtrl', function ($http) {
    var self = this

      .get('/my_data.json', {
        etagCache: 'persistentCache'
      .success(function (data, status, headers, config, itemCache) {
        // Modify the data from the server
        data._fullName = data.first_name + ' ' + data.last_name
        // Update the cache with the modified data
        // Assign to controller property
        self.fullName = data._fullName
      // Synchronous method called if request was previously cached
      .cached(function (data, status, headers, config, itemCache) {
        self.fullName = data._fullName
      .error(function (data, status) {
        // 304: 'Not Modified'--Etag matched, cached data is fresh
        if (status != 304) alert('Request error')

The only thing that's required server-side is to make sure that the server is sending the ETag response header. You can find information about how to inspect response headers in Chrome here:

Package, Angular module for easy ETag-based caching of $http responses Caches ETag headers and sends them back to the server in the If-None-Match header. self = this $http .get('/my_data.json', { etagCache: 'persistentCache' }) .then( function If you don't pass a config, a new cache will be defined using the default config. With Etags, you ask the server if your cached response is still valid (using the etag id the server provided in its intial response), and the server response with either a 304 with no response body (meaning the cache is still valid), or a 200 OK with a new reponse body.

Well, for certain server has to support issuing ETags and ASP.NET MVC or Web API do not by default. You have to use some form of output caching on the server.

One such project is Filip Woj's CacheOutput here

ETag, ETags with the Spring - ShallowEtagHeaderFilter, integration testing of the REST API, and Pagination with Spring REST and AngularJS table And there you have it – ETags in the wild and saving bandwidth. the ETag based on the response, which will save bandwidth but not server performance. Let's now see how we can use external JavaScript in Angular 10. We'll make use of the popular jQuery library as an example. Note : Please note that it's not recommended to use jQuery for maniplulating the DOM in Angular.

I wanted a $http interceptor based solution, as I need it to work with all users of $http, and I can't just use a $http decorator like angular-http-etag does because e.g. $translateProvider.useStaticFilesLoader from Angular Translate uses $http and I want those calls to also be cached.

The solution below is written in Typescript and will store/retrieve the cache from localstorage, and will only keep the newest 25 cached items.

interface CacheObject {
    data: any;
    etag: string;
    index: number;

appModule.config(['$httpProvider', ($httpProvider) => {
    const cacheKey = 'add_your_unique_custom_localstorage_key_here';
    const cacheSize = 25;
    let index = 0;
    let cache: {[key: string]: CacheObject};

    const cacheString = localStorage.getItem(cacheKey);

    if (cacheString == null) {
        cache = Object.create(null);
    } else {
        cache = JSON.parse(cacheString);
        let cacheEntries = Object.entries(cache);

        for (const entry of cacheEntries) {
            // Find largest index
            const entryIndex = entry[1].index;
            if (entryIndex > index) {
                index = entryIndex;
        if (index > Number.MAX_SAFE_INTEGER) {
            // Reset cache if index gets larger than max safe int
            // This is kind of a theoretical problem
            cache = Object.create(null);
            cacheEntries = [];
            index = 0;

        if (cacheEntries.length > cacheSize) {
            // Clean up cache once in a while. Only keep the 25 newest items
            const sortedCacheEntries = cacheEntries.sort((a, b) => {
                return b[1].index - a[1].index;
            sortedCacheEntries.length = cacheSize;
            cache = sortedCacheEntries.reduce(
                (accum, [k, v]) => {
                    accum[k] = v;
                    return accum;

    $httpProvider.interceptors.push(['$q', ($q: ng.IQService) => {
        return {
            response: (response) => {
                const headers = response.headers();
                if (response.status === 200 && headers.etag) {
                    const cacheObject = {
                        etag: headers.etag,
                        index: index++,
                    cache[response.config.url] = cacheObject;
                    localStorage.setItem(cacheKey, JSON.stringify(cache));
                return response;
            responseError: (response) => {
                if (response.status === 304) {
                    const cacheObject = cache[response.config.url];
                    if (cacheObject != null) {
                        const data =;
                        const dataString = JSON.stringify(data);
                        const clonedData = JSON.parse(dataString);
               = clonedData;
                        // Will only recover if we set status to 200
                        response.status = 200;
                        return $q.resolve(response);
                return $q.reject(response);
            request: (config) => {
                const cacheObject = cache[config.url];
                if (cacheObject != null) {
                    config.headers['If-None-Match'] = cacheObject.etag;
                return config;

ETags for REST with Spring, The browser will send some information about the cached resource it holds and the server will determine whether updated content should be� @estus bcoz I'm trying to do it in Angular 4 Universal, you right though, angular tag can be removed – Bhushan Babar Jun 26 '17 at 16:02 @estus do you have any idea, how to do it? – Bhushan Babar Jun 26 '17 at 16:07

Increasing Application Performance with HTTP Cache Headers , We have successfully completed the API service. If needed, you can check all methods using Postman or any other tool. Create Angular 8� Quick story: so, my good friend (an experienced developer) and I were discussing this exact topic a few weeks back. He thought that, OF COURSE you should learn core JS before playing with frameworks.

Client-Side Caching In Angular 8 Using HTTP Interceptor, It has been checked for equivalence with what the origin server would have MAY be in any appropriate natural language (perhaps based on the client's Accept headers), The ETag response-header field value, an entity tag, provides for an� Angular also supports workspaces with multiple projects. This type of development environment is suitable for advanced users who are developing shareable libraries , and for enterprises that use a "monorepo" development style, with a single repository and global configuration for all Angular projects.

HTTP/1.1: Caching in HTTP, A close look at what a 304 Not Modified response code is, including The If- None-Match header indicates that the ETag response header should be Instead, it will be something on the server-side, which is performing most of the As with anything, it's better to have played it safe at the start than to screw� Looking at the angular-resource source indicates that triggering caching isn't possible with the way it is currently written. Here's the request object from the source:

  • If you ever found out your solution please share