我如何在 nginx Web 服务器的重写规则中将大写字母转换为小写字母?

发布于 2024-09-18 17:10:41 字数 77 浏览 11 评论 0原文

我需要翻译地址:

www.example.com/TEST in ---> www.example.com/test

I need to translate the address:

www.example.com/TEST in ---> www.example.com/test

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

囍笑 2024-09-25 17:10:41

是的,你将需要 Perl。

如果您使用的是 Ubuntu,请使用 apt-get install nginx-extras,而不是 apt-get install nginx-full,它将具有嵌入式 Perl 模块。

然后,在您的配置文件中:

  http {
  ...
    # Include the perl module
    perl_modules perl/lib;
    ...
    # Define this function
    perl_set $uri_lowercase 'sub {
      my $r = shift;
      my $uri = $r->uri;
      $uri = lc($uri);
      return $uri;
    }';
    ...
    server {
    ...
      # As your first location entry, tell nginx to rewrite your uri,
      # if the path contains uppercase characters
      location ~ [A-Z] {
        rewrite ^(.*)$ $scheme://$host$uri_lowercase;
      }
    ...

Yes, you are going to need perl.

If you are using Ubuntu, instead of apt-get install nginx-full, use apt-get install nginx-extras, which will have the embedded perl module.

Then, in your configuration file:

  http {
  ...
    # Include the perl module
    perl_modules perl/lib;
    ...
    # Define this function
    perl_set $uri_lowercase 'sub {
      my $r = shift;
      my $uri = $r->uri;
      $uri = lc($uri);
      return $uri;
    }';
    ...
    server {
    ...
      # As your first location entry, tell nginx to rewrite your uri,
      # if the path contains uppercase characters
      location ~ [A-Z] {
        rewrite ^(.*)$ $scheme://$host$uri_lowercase;
      }
    ...
蒲公英的约定 2024-09-25 17:10:41
location /dupa/ {
    set_by_lua $request_uri_low "return ngx.arg[1]:lower()" $request_uri;
    rewrite ^ https://$host$request_uri_low;
}
location /dupa/ {
    set_by_lua $request_uri_low "return ngx.arg[1]:lower()" $request_uri;
    rewrite ^ https://$host$request_uri_low;
}
金兰素衣 2024-09-25 17:10:41

我设法使用嵌入式 Perl 实现了目标:

location ~ [A-Z] {
  perl 'sub { my $r = shift; $r->internal_redirect(lc($r->uri)); }';
}

i managed to achieve the goal using embedded perl:

location ~ [A-Z] {
  perl 'sub { my $r = shift; $r->internal_redirect(lc($r->uri)); }';
}
_畞蕅 2024-09-25 17:10:41

根据 Adam 的回答,我最终使用了 lua,因为它在我的服务器上可用。

set_by_lua $request_uri_low "return ngx.arg[1]:lower()" $request_uri;
if ($request_uri_low != $request_uri) {
   set $redirect_to_lower 1;
}
if (!-f $request_uri) {
    set $redirect_to_lower "${redirect_to_lower}1";
}
if ($redirect_to_lower = 11) {
    rewrite . https://$host$request_uri_low permanent;
}

Based on Adam's answer, I ended up using lua, as it's available on my server.

set_by_lua $request_uri_low "return ngx.arg[1]:lower()" $request_uri;
if ($request_uri_low != $request_uri) {
   set $redirect_to_lower 1;
}
if (!-f $request_uri) {
    set $redirect_to_lower "${redirect_to_lower}1";
}
if ($redirect_to_lower = 11) {
    rewrite . https://$host$request_uri_low permanent;
}
不再见 2024-09-25 17:10:41
location ~*^/test/ {
  return 301 http://www.example.com/test;
}

位置可以由前缀字符串或正则表达式定义。正则表达式使用前面的“~*”修饰符(用于不区分大小写的匹配)或“~”修饰符(用于区分大小写的匹配)来指定。

来源: http://nginx.org/en/docs/http/ngx_http_core_module.html #位置

location ~*^/test/ {
  return 301 http://www.example.com/test;
}

A location can either be defined by a prefix string, or by a regular expression. Regular expressions are specified with the preceding “~*” modifier (for case-insensitive matching), or the “~” modifier (for case-sensitive matching).

Soruce: http://nginx.org/en/docs/http/ngx_http_core_module.html#location

柠北森屋 2024-09-25 17:10:41

我想指出大多数 Perl 答案都容易受到 CRLF 注入的影响。

您永远不应该在 HTTP 重定向中使用 nginx 的 $uri 变量。 $uri 变量需要标准化(更多信息),包括:

  • URL 编码字符被解码
  • 删除?而查询字符串中
  • 连续的 / 字符被单个 / 替换,

URL 解码是 CRLF 注入漏洞的原因。如果您在重定向中使用 $uri 变量,以下示例 url 将在您的重定向中添加恶意标头。

https://example.org/%0ASet-Cookie:MaliciousHeader:Injected

% 0A 被解码为 \n\r 并且 nginx 会将以下行添加到标头中:

Location: https://example.org
set-cookie: maliciousheader:injected

安全 Perl 重定向需要替换所有换行符。

perl_set $uri_lowercase 'sub {
    my $r = shift;
    my $uri = $r->uri;
    $uri =~ s/\R//; # replace all newline characters
    $uri = lc($uri);
    return $uri;
}';

I would like to point out that most of Perl answers are vulnerable to CRLF injection.

You should never use nginx's $uri variable in a HTTP redirection. $uri variable is subject to normalization (more info), including:

  • URL encoded characters are decoded
  • Removal of the ? and query string
  • Consecutive / characters are replace by a single /

URL decoding is the reason of CRLF injection vulnerability. The following example url would add a malicious header into your redirect, if you used $uri variable in the redirection.

https://example.org/%0ASet-Cookie:MaliciousHeader:Injected

%0A is decoded to \n\r and nginx will add into headers the following lines:

Location: https://example.org
set-cookie: maliciousheader:injected

The secure Perl redirection requires to replace all newline characters.

perl_set $uri_lowercase 'sub {
    my $r = shift;
    my $uri = $r->uri;
    $uri =~ s/\R//; # replace all newline characters
    $uri = lc($uri);
    return $uri;
}';
↘人皮目录ツ 2024-09-25 17:10:41

使用 LUA 模块重定向。

load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;

set_by_lua $uri_lowercase "return string.lower(ngx.var.uri)";
location ~[A-Z] {
  return 301 $scheme://$http_host$uri_lowercase$is_args$args;
}

Redirect with LUA module.

load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;

set_by_lua $uri_lowercase "return string.lower(ngx.var.uri)";
location ~[A-Z] {
  return 301 $scheme://$http_host$uri_lowercase$is_args$args;
}
柠檬色的秋千 2024-09-25 17:10:41

我在互联网上看到过这段代码,它确实有效。但是,它使用 nginx 服务器收到的主机名。对于 Kubernetes 基础设施,这可能与客户端使用的不同,因此重定向不仅会失败,还会泄露有关集群命名方案的私有信息。

这段代码对我有用,并且速度稍快一些,因为它使用内部重定向

sub {
    my $r = shift;
    my $uri = $r->uri;
    $uri =~ s/\R//; # replace all newline characters
    $uri = lc($uri);
    $r -> internal_redirect($uri)
}

它可以在 nginx 配置文件中使用,如下所示:

user        nginx; # Not important for this answer, use any user you want
                   # but nginx is a sensible default.

# Load the Perl module
load_module /usr/lib/nginx/modules/ngx_http_perl_module.so;

...

http {
    server {
        # Given any location that contains an upper-case letter
        location ~ [A-Z] {
            # Lowercase it and redirect internally
            perl 'sub {
                my $r = shift;
                my $uri = $r->uri;
                $uri =~ s/\R//; # replace all newline characters
                $uri = lc($uri);
                $r -> internal_redirect($uri)
            }';
        }

        # This can be any set of rules, below is a simple one that hosts
        # static content. It will receive the lower-cased location and
        # serve it.
        location / {
            root  /usr/share/nginx/html;
            index index.html;
        }
    }
}

我的 Dockerfile 以这一行开头,不需要额外的包:

FROM nginx:1.23.4-perl

在本例中,您将需要复制静态文件站点到 /usr/share/nginx/html 例如:

COPY nginx.conf /etc/nginx/nginx.conf
COPY src/ /usr/share/nginx/html

I've seen this code all over the internet, and it does work. However, it uses the host name that the nginx server receives. In the case of a Kubernetes infrastructure, this may not be the same as what the client uses so the redirect will not only fail but give away private information about the cluster naming scheme.

This code works for me and is slightly faster because it uses internal redirection

sub {
    my $r = shift;
    my $uri = $r->uri;
    $uri =~ s/\R//; # replace all newline characters
    $uri = lc($uri);
    $r -> internal_redirect($uri)
}

It might be used in an nginx configuration file like this:

user        nginx; # Not important for this answer, use any user you want
                   # but nginx is a sensible default.

# Load the Perl module
load_module /usr/lib/nginx/modules/ngx_http_perl_module.so;

...

http {
    server {
        # Given any location that contains an upper-case letter
        location ~ [A-Z] {
            # Lowercase it and redirect internally
            perl 'sub {
                my $r = shift;
                my $uri = $r->uri;
                $uri =~ s/\R//; # replace all newline characters
                $uri = lc($uri);
                $r -> internal_redirect($uri)
            }';
        }

        # This can be any set of rules, below is a simple one that hosts
        # static content. It will receive the lower-cased location and
        # serve it.
        location / {
            root  /usr/share/nginx/html;
            index index.html;
        }
    }
}

My Dockerfile starts with this line and doesn't require additional packages:

FROM nginx:1.23.4-perl

In this example you will want to copy your static site to /usr/share/nginx/html for example:

COPY nginx.conf /etc/nginx/nginx.conf
COPY src/ /usr/share/nginx/html
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文