简体   繁体   中英

Varnish: How to change language of the site based on a cookie?

I have my site almost working. It works perfect with one language, but I have a cookie that sets the language. I hashed it also.

The problem is that I cant change the value of my cookie, I cant get an idea about how to do that. My site receives a variable called "lg=1" where "1" is the language code.

I dont get the idea about how to pass that to my site, to get the "english" version and save the new cookie (with lg=1 value) again, so next time the user access without the lg=1 variable, he visits our english site, based on cookie value.

Can someody help me? Thanky you

If you want to be able to set a cookie based on get-parameter you have two options

  1. Set the cookie with javascript. Here is a SO answer for setting Cookie with JS
  2. Configure Varnish to always pass requests containing "lg=" to your application so that you can set the cookie there.

     sub vcl_recv { if (req.url ~ ".*lg=") { return (pass); } #Your other code in vcl_recv..... } 

You will probably need to edit your VCL file, by default something like /etc/varnish/default.vcl

When you receive a language parameter, you can set a cookie via Varnish. Then use the value of the cookie to override the request url to the backend.

It should be something like that :

sub vcl_recv {
  // Use the value of the cookie to override the request url.
  if (req.http.Cookie ~ "lg") {
    set req.url = req.url + "?" + req.http.Cookie;
  }

  // Go to VCL_error to redirect and remove the parametter.
  if (req.url ~ "(?i)lg=1") {
    error 802 "Remember to use the english version";
  }
}


sub vcl_error {
  /* Removes lg parameter and remember the english choice */
  if (obj.status == 802) {
    set obj.http.Set-Cookie = "lg=1; domain=." + req.http.host + "; path=/";
    set obj.http.Location = req.http.X-Forwarded-Proto + "://" + req.http.host + regsub(req.url, "\?lg=1", "");
    set obj.status = 302;
    return(deliver);
  }
}

I would prefer to use a different subdomain for each language, like that you can just redirect the user to the subdomain when you receive a parameter. By doing that you would not need to override the request.url each time.

I will use below approach to achieve:

  1. Check lg cookie is exist or not. If not exist then set it using back-end server or varnish server.
  2. I preferred to set language cookie using varnish instead of back-end server to avoid excessive request/load on back-end server.
  3. Default language selection must be English ie "1"
  4. Set the hash based on user language selection.It will help to maintain different cache based on language also retrieve the data from cache.

    Please refer below code:

    I have used IPD cookie.

     backend default { #applicable code goes here } sub identify_cookie{ #Call cookie based detection method in vcl_recv if (req.http.cookie ~ "IPD=") { set req.http.Language = regsub(req.http.cookie, "(.*?)(IPD=)([^;]*)(.*)$", "\\3"); } } C{ #used to set persistent(9+ years) cookie from varnish server. const char* persistent_cookie(char *cookie_name){ time_t rawtime; struct tm *info; char c_time_string[80]; rawtime = time(NULL) * 1.2; /*Added 9 years*/; info = localtime(&rawtime); strftime(c_time_string,80,"%a, %d-%b-%Y %H:%M:%S %Z", info); char * new_str ; if((new_str = malloc(strlen(cookie_name)+strlen(c_time_string)+1)) != NULL){ new_str[0] = '\\0'; // ensures the memory is an empty string strcat(new_str,cookie_name); strcat(new_str,c_time_string); } else { syslog(LOG_INFO,"Persistent cookie malloc failed!\\n"); } return new_str; } }C sub vcl_recv { call identify_cookie; #Used to get identify cookie and get its value if(!req.http.Cookie ~ "IPD"){ C{ VRT_SetHdr(sp, HDR_REQ, "\\006X-IPD:",persistent_cookie("IPD=1; domain=yourdomain.com; path=/; Expires="),vrt_magic_string_end); }C } } sub vcl_fetch { set beresp.http.Set-Cookie = req.http.X-IPD; #used for debug purpose only.Check cookie in response header } sub vcl_backend_response { #applicable code goes here } sub vcl_deliver { #applicable code goes here set resp.http.X-Cookie = "Cookies Set ("req.http.X-IPD")"; #used for debug purpose only.Check cookie in response header } sub vcl_error { #applicable code goes here } sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } if(!req.http.Language){ req.http.Language = 1 #default english language } hash_data(req.http.Language); # make different hash for different language to avoid cache clashing return(hash); } sub vcl_pipe { #applicable code goes here } sub vcl_pass { #applicable code goes here } 

    Note: Please ensure to change cookie name only.Regular expression supports to retrive cookie value from multiple cookies without considering its order

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM