【问题标题】:Varnish: How to change language of the site based on a cookie?Varnish:如何根据 cookie 更改网站的语言?
【发布时间】:2014-09-10 10:49:39
【问题描述】:

我的网站几乎可以正常工作了。它适用于一种语言,但我有一个设置语言的 cookie。我也散列了。

问题是我无法更改 cookie 的值,我不知道该怎么做。 我的网站收到一个名为“lg=1”的变量,其中“1”是语言代码。

我不知道如何将其传递给我的网站,以获取“英文”版本并再次保存新 cookie(具有 lg=1 值),因此下次用户访问时不使用 lg=1 变量,他根据 cookie 值访问了我们的英文网站。

有人可以帮助我吗? 谢谢你

【问题讨论】:

    标签: cookies varnish varnish-vcl


    【解决方案1】:

    如果您希望能够根据 get-parameter 设置 cookie,您有两个选择

    1. 使用 javascript 设置 cookie。 Here is a SO answer for setting Cookie with JS
    2. 将 Varnish 配置为始终将包含“lg=”的请求传递给您的应用程序,以便您可以在那里设置 cookie。

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

    【讨论】:

      【解决方案2】:

      您可能需要编辑您的 VCL 文件,默认情况下类似于 /etc/varnish/default.vcl

      当您收到语言参数时,您可以通过 Varnish 设置 cookie。 然后使用cookie的值覆盖到后端的请求url。

      应该是这样的:

      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);
        }
      }
      

      我更愿意为每种语言使用不同的子域,例如,您可以在收到参数时将用户重定向到子域。通过这样做,您不需要每次都覆盖 request.url。

      【讨论】:

        【解决方案3】:

        我将使用以下方法来实现:

        1. 检查 lg cookie 是否存在。如果不存在,则使用后端服务器或清漆服务器进行设置。
        2. 我更喜欢使用 varnish 而不是后端服务器来设置语言 cookie,以避免后端服务器上的过多请求/负载。
        3. 默认语言选择必须是英语,即“1”
        4. 根据用户语言选择设置哈希值。这将有助于维护基于语言的不同缓存以及从缓存中检索数据。

          请参考以下代码:

          我使用了 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
          }
          

          注意:请确保只更改cookie名称。正则表达式支持从多个cookie中检索cookie值而不考虑其顺序

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-08-19
          • 2017-07-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-26
          • 1970-01-01
          • 2017-11-04
          相关资源
          最近更新 更多