2

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

我设法找到了这个讨论,但 Varnish 的创建者表示我必须使用内联 C 来完成它。我可以使用多个正则表达式以简单的方式实现这一点,但这似乎注定会失败。

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

4

6 回答 6

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 文件中,然后为它添加了一个包含。

于 2011-07-29T10:28:05.363 回答
2

我将分享我的解决方案,它将 Richard 的代码扩展为一个完整的解决方案。

如果 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 *有一个丑陋的转换......基本上,我们正在就地修改字符串,尽管 Varnish 告诉我们不要这样做。它似乎工作。:-)char *req.url

于 2011-08-30T14:22:14.410 回答
2

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

这比嵌入式 C 路由(在 Varnish 4 中默认禁用)要干净得多。这是我用来规范化请求 Host 和 url 的示例;

    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));
      ....
    }
于 2014-09-30T08:46:07.870 回答
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-insensitive

于 2016-02-26T03:09:29.953 回答
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;
}

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

于 2011-07-28T11:21:28.857 回答
0

请注意,要从 C 块设置 URL 并避免崩溃使用:

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
}
于 2011-10-17T19:59:10.783 回答