guillaumepotier
guillaumepotier

Reputation: 7448

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:

Thanks for your answers and lights on that.

Upvotes: 6

Views: 2458

Answers (1)

Eric
Eric

Reputation: 2087

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!

Upvotes: 8

Related Questions