Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use varnish with RESTful Api using Oauth2 protocol?

I have a RESTful Api written in Symfony2 using FosOauth2Serverbundle, FosRestBundle and FosUserBundle. I am planing to bring varnish in front of my api as reverse proxy. Since my app using my api always send access_token as parameter or header varnish caches almost every request as different requests and it is not effective. Because i use user of access_token in my controller for security and sometimes for content, i can not remove access_token from request completely from request in vcl_recv. After several search on internet, i come across a solution for authentication http://www.adayinthelifeof.nl/2012/07/06/using-varnish-to-offload-and-cache-your-oauth-requests/ . However, i can not figure out how to tell FosUserBundle current user in header to pass security in security.yml:

  access_control:
   - { path: ^/2013-08-30/foo$, role: ROLE_USER, requires_channel: https, methods: [GET] }

In short, How can i tell FosUserBundle current user in request(send from varnish) header?

like image 544
Omer Temel Avatar asked Nov 10 '22 15:11

Omer Temel


1 Answers

There are a couple ways to get around issues like this, if you want two slightly different requests to return the same response (i.e. the requests differ only by an API key GET param) the quickest and easiest solution is to customize varnish's definition of uniqueness using the hash_data function in vcl_hash. You just strip out all url elements that don't contribute toward making the response distinct and hash that. For example, if the url contains "access_token", strip all GET params out of the hash key:

sub vcl_hash {
  if (req.url ~ "access_token"){
    set req.url = regsub(req.url, "^https?://(.*)\?access_token=.*$","\1");
  }
  hash_data(req.url);
}

In other words this would cache mydomain.com/some/restful/request?access_token=abc and mydomain.com/some/restful/request?access_token=def as a match.

If the response is mostly the same with small areas that should be unique (i.e. one value in a large JSON response, or a div in the header that says "Welcome Username!"), you can use edge side includes. The catch, of course, is that this requires customization to what the backend returns.

like image 191
jaybrau Avatar answered Nov 15 '22 08:11

jaybrau