Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly cache my Symfony2 APIs?

I'm making classic stateless RESTfull APIs on Symfony2: users/apps gets an authentication token on the authenticate API and give it to all others APIs to be logged and post data / access protected/private/personal data on others APIs.

I've got now three concerns regarding this workflow and caching:

  • How to use HTTP cache for my 'static' APIs (that always deliver the same content, regardless the logged user and its token) assuming that different tokens would be passed in the url by different users for the same API, so that the url would never be the same? How to use HTTP shared cache then?

  • I've got APIs for the same url that produce a different output, regarding the logged user rights (I've basically 4 different rights levels). Question is: is it a good pattern? It is not better to have 4 different urls, one for each right, that I could cache? If not, how to implement a proper cache on that?

  • Is shared HTTP Cache working on HTTPS? If not, which type of caching should I implement, and how?

Thanks for your answers and lights on that.

like image 798
guillaumepotier Avatar asked Aug 20 '12 13:08

guillaumepotier


People also ask

Can API response be cached?

Besides slowing down your app, these redundant calls also put a load on the server. Therefore, caching API responses on the client level improves both client and server efficiency. Any routinely fetched request can be kept locally on the client-side, reducing the need for additional API calls.

How does cache work in API?

The cache checks if the value in Last-Modified has changed. If no , the client uses the cached data without downloading the response from the API. If the Last-Modified header differs from what is in the client's cache, the client caches the new response data.

Does heroku cache?

Heroku doesn't provide HTTP caching by default. In order to take advantage of HTTP caching, you'll need to configure your application to set the appropriate HTTP cache control headers and use a content delivery network (CDN) or other external caching service.

What is caching in API testing?

Caching refers to storing the server response in the client itself, so that a client need not make a server request for the same resource again and again.


1 Answers

I have had a similar issue (with all 3 scenarios) and have used the following strategy successfully with Symfony's built-in reverse-proxy cache:

  1. If using Apache, update .htaccess to add an environment variable for your application to the http cache off of (NOTE: environment automatically adds REDIRECT_ to the environment variable):

    # Add `REDIRECT_CACHE` if API subdomain
    RewriteCond %{HTTP_HOST} ^api\.
    RewriteRule .* - [E=CACHE:1]
    
    # Add `REDIRECT_CACHE` if API subfolder
    RewriteRule ^api(.*)$ - [E=CACHE:1]
    
  2. Add this to app.php after instantiating AppKernel:

    // If environment instructs us to use cache, enable it
    if (getenv('CACHE') || getenv('REDIRECT_CACHE')) {
        require_once __DIR__.'/../app/AppCache.php';
    
        $kernel = new AppCache($kernel);
    }
    
  3. For your "static" APIs, all you have to do is take your response object and modify it:

    $response->setPublic();
    $response->setSharedMaxAge(6 * 60 * 60);
    

    Because you have a session, user or security token, Symfony effectively defaults to $response->setPrivate().

Regarding your second point, REST conventions (as well as reverse-proxy recommendations), GET & HEAD requests aren't meant to change between requests. Because of this, if content changes based on the logged in user, you should set the response to private & prevent caching at all for the reverse-proxy cache.

If caching is required for speed, it should be handled internally & not by the reverse-proxy.

Because we didn't want to introduce URLs based on each user role, we simply cached the response by role internally (using Redis) & returned it directly rather than letting the cache (mis)handle it.

As for your third point, because HTTP & HTTPS traffic are hitting the same cache & the responses are having public/private & cache-control settings explicitly set, the AppCache is serving the same response both secure & insecure traffic.

I hope this helps as much as it has for me!

like image 81
Eric Avatar answered Oct 03 '22 11:10

Eric