Varnish中的小写网址(内联C)

时间:2011-07-28 10:24:26

标签: c caching lowercase varnish

Varnish(3.0)中,网址以区分大小写的方式处理。我的意思是http://test.com/user/a4556http://test.com/user/A4556的处理方式不同。在我的网络服务器上,它们被视为相同的网址。我想做的是在它们进来时将varnish小写所有请求URL。

我设法找到this discussion但是Varnish的创建者表示我必须使用内联C来完成它。我可以使用多个正则表达式以一种简单的方式实现这一点,但看起来它肯定会失败。

理想情况下,我想要的是一个VCL配置来执行此操作(此示例可以是found here)但我会选择接受const char *并返回的C函数const char *(我不是C程序员,如果我的语法错误,请原谅我)。

6 个答案:

答案 0 :(得分:2)

好的,我继续为自己解决了这个问题。这是VCL:

C{
    #include <ctype.h>
    //lovingly lifted from:
    //https://github.com/cosimo/varnish-accept-language/blob/master/examples/accept-language.vcl
    static void strtolower(const char *s) {
        register char *c;
        for (c=s; *c; c++) {
            if (isupper(*c)) {
                *c = tolower(*c);
            }
        }
        return;
    }
}C

sub vcl_recv {
   C{
        strtolower(VRT_r_req_url(sp));
   }C
}

我把它放在一个单独的VCL文件中,然后为它添加了一个包含。

答案 1 :(得分:2)

我将分享我的解决方案,将理查德的代码扩展为完整的解决方案。

如果URL包含大写字母,我们会将用户重定向到正确的URL,而不是在进入缓存机制之前简单地规范化URL。这可以防止搜索引擎将混合大小写的URL与小写分开索引。

# Define a function that converts a string to lower-case in-place.
# http://stackoverflow.com/questions/6857445
C{
    #include <ctype.h>

    static void strtolower(char *c) {
        for (; *c; c++) {
            if (isupper(*c)) {
                *c = tolower(*c);
            }
        }
    }
}C

sub vcl_recv {
    if (req.http.host ~ "[A-Z]" || req.url ~ "[A-Z]") {
        # Convert host and path to lowercase in-place.
        C{
            strtolower(VRT_GetHdr(sp, HDR_REQ, "\005host:"));
            strtolower((char *)VRT_r_req_url(sp));
        }C
        # Use req.http.location as a scratch register; any header will do.
        set req.http.location = "http://" req.http.host req.url;
        error 999 req.http.location;
    }

    # Fall-through to default
}

sub vcl_error {
    # Check for redirects - redirects are performed using: error 999 "http://target-url/"
    # Thus we piggyback the redirect target in the error response variable.
    if (obj.status == 999) {
        set obj.http.location = obj.response;
        set obj.status = 301;
        set obj.response = "Moved permanently";
        return(deliver);
    }

    # Fall-through to default
}

在将const char *转换为小写时,从char *req.url有一个丑陋的演员......基本上,尽管Varnish告诉我们不要,我们正在修改字符串。 。它似乎工作。 : - )

答案 2 :(得分:2)

在提出原始问题近5年之后,我认为我们现在有了更清晰的答案。在搜索“小写清漆”时,这个SO问题仍然排在首位。

以下是Fastly建议的示例的简化变体:

# at the top of your VCL
import std;

sub vcl_recv {
  # Lowercase all incoming URLs. It will also be lowercase by the time the hash is computed.
  set req.url = std.tolower(req.url);
}

https://www.fastly.com/blog/varnish-tip-case-insensitivity

答案 3 :(得分:1)

必须提到的是,Varnish包含std vmod(https://www.varnish-cache.org/docs/trunk/reference/vmod_std.generated.html#func-tolower)中大写和小写字符串的能力

这比嵌入式C路由(在Varnish 4中默认禁用)要清晰得多。这是我用来规范化请求主机和网址的示例;

    import std;

    sub vcl_recv {

      # normalize Host header
      set req.http.Host = std.tolower(regsub(req.http.Host, ":[0-9]+", ""));
      ....

    }

    sub vcl_hash {
      # set cache key to lowercased req.url 
      hash_data(std.tolower(req.url));
      ....
    }

答案 4 :(得分:0)

如果您正在寻找将大写字符串转换为小写字母的C函数,则会执行以下操作:

#include <ctype.h>

static char *
to_lower (char *str)
{
  char *s = str;  

  while (*s)
    {
      if (isupper (*s))
        *s = tolower (*s);
      s++;
    }
  return str;
}

请注意,这会就地修改字符串。因此,您可能希望将原始字符串的副本作为参数传递。

答案 5 :(得分:0)

请注意,要设置来自C区块的网址并避免崩溃,请使用:

VRT_l_req_url(sp,"new-string", vrt_magic_string_end);

(从“varnishd -C”输出中拉出这个细节。)这是对第一个答案的未经测试的修订:

C{
    #include <ctype.h>
    //lovingly lifted from:
    //https://github.com/cosimo/varnish-accept-language/blob/master/examples/accept-language.vcl
    static void strtolower(const char *s) {
        register char *c;
        for (c=s; *c; c++) {
            if (isupper(*c)) {
                *c = tolower(*c);
            }
        }
        return;
    }
}C

sub vcl_recv {
   C{
        const char *url = VRT_r_req_url(sp);
        char urlRewritten[1000];
        strcat(urlRewritten, url);
        strtolower(urlRewritten);
        VRT_l_req_url(sp, urlRewritten, vrt_magic_string_end);
   }C
}