Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$http service cache when the method is post

when I set the $http to cache requests, I still see duplicate requests (with the same url and same data) sent to the server from browser network,

$http.post(url, data, {cache:true} ).success(function(response) {

I have following questions:

  • Is this a right behaviour?
  • Can we cache post requests?
  • Is this the right way to do so or should I be doing it manually with the $cachefactory ?
like image 741
sisimh Avatar asked Oct 13 '16 10:10

sisimh


People also ask

Can POST method be cached?

"Responses to POST method are not cacheable, UNLESS the response includes appropriate Cache-Control or Expires header fields." So, YES, you can cache POST request response but only if it arrives with appropriate headers. In most cases you don't want to cache the response.

Which HTTP status code is usually returned when a resource is cached?

The HTTP 304 Not Modified client redirection response code indicates that there is no need to retransmit the requested resources. It is an implicit redirection to a cached resource.

Are POST requests cacheable by default?

POST requests are not cacheable by default but can be made cacheable if either an Expires header or a Cache-Control header with a directive, to explicitly allows caching, is added to the response. Responses to PUT and DELETE requests are not cacheable at all.

Which HTTP methods can be cached?

The method used in the request is itself cacheable, that is either a GET or a HEAD method. A response to a POST or PATCH request can also be cached if freshness is indicated and the Content-Location header is set, but this is rarely implemented.


2 Answers

From the docs:

Only GET and JSONP requests are cached.

If you want to cache POST-requests you would have to do it manually. You will need to make a service/factory that caches responses and serves as a layer before $http. You can use $cacheFactory or just a plain object.

function cacheService($http, $q){      
  var cache = {};      
  this.callSomething = function(postData){
    let deferred = $q.defer();
    let hash = angular.toJson(postData);
    if(cache[hash]){
      deferred.resolve(cache[hash]);
    } else {
      $http.post('path/to/resource', postData).then(function(response){
        cache[hash] = response;
        deferred.resolve(response);
      });
    }        
    return deferred.promise;
  }
}

This is a simple example, you could of course use the same principle and make a more generalized service that takes an URL, postData and a cache object and returns a function that does the request and caches it.

like image 164
Amygdaloideum Avatar answered Oct 04 '22 23:10

Amygdaloideum


I am not sure about cache working. But you can use $cacheFactory for same.

app.factory('Cache', function ($cacheFactory) {
    return $cacheFactory('Cache');
});

app.controller('MyController', function ($scope, $http, Cache) {
    $http.post(url, data, {cache:Cache} ).success(function(response) {}
});

EDIT:

Only GET and JSONP requests are cached.

The cache key is the request URL including search parameters; headers are not considered.

Cached responses are returned asynchronously, in the same way as responses from the server.

If multiple identical requests are made using the same cache, which is not yet populated, one request will be made to the server and remaining requests will return the same response.

A cache-control header on the response does not affect if or how responses are cached.

like image 20
Ved Avatar answered Oct 04 '22 22:10

Ved