Reputation: 371
I need to translate the address:
www.example.com/TEST in ---> www.example.com/test
Upvotes: 37
Views: 39141
Reputation: 338
Another way is with module pure c ngx_http_lower_upper_case because load perl is resource usage high:
location ~ [A-Z] {
lower $uri_lowercase "$request_uri";
rewrite ^(.*)$ $scheme://$host$uri_lowercase;
}
Upvotes: 1
Reputation: 2441
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
Upvotes: 0
Reputation: 1171
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;
}
...
Upvotes: 23
Reputation: 123
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;
}
Upvotes: 0
Reputation: 66
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 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;
}';
Upvotes: 1
Reputation: 8183
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;
}
Upvotes: 4
Reputation: 1215
location /dupa/ {
set_by_lua $request_uri_low "return ngx.arg[1]:lower()" $request_uri;
rewrite ^ https://$host$request_uri_low;
}
Upvotes: 10
Reputation: 553
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
Upvotes: 3
Reputation: 676
i managed to achieve the goal using embedded perl:
location ~ [A-Z] {
perl 'sub { my $r = shift; $r->internal_redirect(lc($r->uri)); }';
}
Upvotes: 9