1

Varnish is running, Magento is skyrocketing until we noticed that currency change doesn't work. OF course it doesn't because url is same when you switch currency.

Is there a workaround solution for this?

Currency exchange url is: /directory/currency/switch/currency/EUR/uenc/xxxsomethingyyy/

Varnish config;

backend default {
        .host = "127.0.0.1";
        .port = "8000";
     }

    acl trusted {
        "127.0.0.1";
        "127.0.1.1";
    }


    sub vcl_recv {
        if (req.http.x-forwarded-for) {
            set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
        }
        else {
            set req.http.X-Forwarded-For = client.ip;
        }

    if (req.request == "PURGE") {
        # Allow requests from trusted IPs to purge the cache
        if (!client.ip ~ trusted) {
           error 405 "Not allowed.";
        }
        ban("req.url ~ " + req.url);
        error 200 "Ok"; #We don't go to backend 

    }

    if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "PUT" &&
       req.request != "POST" &&
       req.request != "TRACE" &&
       req.request != "OPTIONS" &&
       req.request != "DELETE") {
         /* Non-RFC2616 or CONNECT which is weird. */
         return (pipe);
    }

     # Cache only GET or HEAD requests
     if (req.request != "GET" && req.request != "HEAD") {
         /* We only deal with GET and HEAD by default */
         return (pass);
     }

    # parse accept encoding rulesets to normalize
    if (req.http.Accept-Encoding) {
        if (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        } else {
           remove req.http.Accept-Encoding;
        }
    }

     # Rules for static files
     if (req.url ~ "\.(jpeg|jpg|png|gif|ico|swf|js|css|gz|rar|txt|bzip|pdf)(\?.*|)$") {
        set req.http.staticmarker = "1";
        unset req.http.Cookie;

        return (lookup);
    }

    # Don't cache pages for Magento Admin
    # FIXME: change this rule if you use custom url in admin
    if (req.url ~ "^/(index.php/)?admin") {
        return(pass);
    }

    # Don't cache checkout/customer pages, product compare
    if (req.url ~ "^/(index.php/)?(checkout|customer|catalog/product_compare|wishlist)") {
        return(pass);
    }
    # Don't cache checkout/customer pages, product compare, custom urls, & WP
    if (req.url ~ "/(checkout|customer|catalog/product_compare|wishlist|paywayr|directory)/") {
        return(pass);
    }


    # Don't cache till session end
    if (req.http.cookie ~ "nocache_stable") {
        return(pass);
    }

    # Unique identifier witch tell Varnish use cache or not
    if (req.http.cookie ~ "nocache") {
        return(pass);
    }

    # Remove cookie 
    unset req.http.Cookie;
    set req.http.magicmarker = "1"; #Instruct varnish to remove cache headers received from backend
    return(lookup);
 }


sub vcl_pipe {
     return (pipe);
}



# Called after a cache lookup if the req. document was found in the cache.
sub vcl_hit {
    if (req.request == "PURGE") {
        ban_url(req.url);
        error 200 "Purged";
    }

    return (deliver);
}

    # Called after a cache lookup and odc was not found in cache.
    sub vcl_miss {
        if (req.request == "PURGE"){
            error 200 "Not in cache";
        }
        return (fetch);
    }

    # Called after document was retreived from backend
    sub vcl_fetch {
        set req.grace = 30s;

        # Current response should not be cached
        if(beresp.http.Set-Cookie ~ "nocache=1") {
            return (deliver);
        }

        # Flag set when we want to delete cache headers received from backend
        if (req.http.magicmarker){
            unset beresp.http.magicmarker;
            unset beresp.http.Cache-Control;
            unset beresp.http.Expires;
            unset beresp.http.Pragma;
            unset beresp.http.Cache;
            unset beresp.http.Server;
            unset beresp.http.Set-Cookie;
            unset beresp.http.Age;

            # default ttl for pages
            set beresp.ttl = 1d;
        }
        if (req.http.staticmarker) {
            set beresp.ttl = 30d; # static file cache expires in 30 days
            unset beresp.http.staticmarker;
            unset beresp.http.ETag; # Removes Etag in case we have multiple frontends
        }

        return (deliver);
    }

    # Called after a cached document is delivered to the client.
    sub vcl_deliver {
        if (obj.hits > 0) {
            set resp.http.X-Cache = "HIT ("+obj.hits+")";
        } else {
            set resp.http.X-Cache = "MISS";
            #    set resp.http.X-Cache-Hash = obj.http.hash;
        }
        return (deliver);
    }
2

As the currency is stored in a cookie parameter, one solution is to add that value into the hash for the varnish lookup.

sub vcl_hash {
  hash_data(req.url);
  if (req.http.host) {
    hash_data(req.http.host);
  } else {
    hash_data(server.ip);
  }

  if (req.http.cookie ~ "currency=") {
    set req.http.X-TMP = regsub(req.http.cookie, ".*currency=([^;]+);.*",
"\1");
    hash_data(req.http.X-TMP);
    remove req.http.X-TMP;
  }
  return (hash);
}

Example is taken from this this link, and slightly modified. Untested.

Also Varnish docs on the subject on caching on cookies: Caching, even when cookies are present, link, look for the link as well in, couldn't post third link since not enough rep yet.

  • Turned out there was miss configuration, or better told there was one parameter missing in /etc/default/varnish: -p cli_buffer=10000 Also tested your solution and it is working! Thanks :) – nordashi Jun 14 '14 at 16:58
  • I'm facing similar issue. on home page currency switcher does not work. It only shows the first time selected currency with each product. is this same solution for my problem ? Kindly help – Moyed Ansari Apr 12 '16 at 6:54
0

The above works BUT, when using Geolocation is rather useless, as it will cache the currency based on the first request.

So Varnish must handle that because the code for geolocation to set the currency will never run unless the request hits the backend.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.