Rewrite uri to lowercase in nginx and apache webserver

Rewrite uri to lowercase in nginx and apache webserver

Rewrite uri to lowercase in nginx webserver


We want make our uri case insensitive. What it is? When I call uri like https://mybluelinux.com/INdex.html, so such uri will be first rewrite to all lowercase chars like https://mybluelinux.com/index.html.

First of all, We will need some function in nginx server that rewrite a large letters in url to small.

For nginx webserver we have a two choices - perl and lua module

Perl module to nginx case insensitive rewrite


  • we need install libnginx-mod-http-perl module for nginx webserver
]$ apt-get install libnginx-mod-http-perl
  • enable libnginx-mod-http-perl module in nginx webserver and reload configuration
]$ cd /etc/nginx/modules-enabled/
/etc/nginx/modules-enabled]$ ln -s /usr/share/nginx/modules-available/50-mod-http-perl.conf .
/etc/nginx/modules-enabled]$ /etc/init.d/nginx reload
  • to http context in nginx write this configuration
 http {
...
        ##
        # define perl function
        ##
        perl_set $my_uri_to_lowercase 'sub {
          my $r = shift;
          my $uri = $r->uri;
          $uri = lc($uri);
          return $uri;
        }';
...
}

Rewrite url to lowercase with return redirect status code


Add to your virtual host this config:

...
      # As your first location entry, tell nginx to rewrite your uri,
      # if the path contains uppercase characters
      location ~ [A-Z] {
          return 307 $scheme://$host$my_uri_to_lowercase;
      }
...

Explanation


We known Nginx Location directive priority and selection algorithm from this article - nginx location manual.

Search of regular expressions terminates on the first match, and the corresponding configuration is used. So, we make our uri to lowercase location as a first location context in our configuration. When uri is rewrite to lowercases, we than make another location context that match such uri as lowercase prefix or lowercase regular expression.

Redirect with http 301 redirect vs 302 redirect vs 307 redirect


  • redirect 301 - Status 301 means that the resource (page) is moved permanently to a new location. The client/browser should not attempt to request the original location but use the new location from now on.

  • redirect 302 - Status 302 means that the resource is temporarily located somewhere else, and the client/browser should continue requesting the original url.

  • redirect 307 - The target resource resides temporarily under a different URI and the user agent MUST NOT change the request method if it performs an automatic redirection to that URI. This status code is similar to 302 Found, except that it does not allow changing the request method from POST to GET.

Redirect 307 came about because user agents adopted as a de facto behaviour to take POST requests that receive a 302 response and send a GET request to the Location response header.

That is the incorrect behaviour — only a 303 should cause a POST to turn into a GET. User agents should (but don’t) stick with the POST method when requesting the new URL if the original POST request returned a 302.

Redirect 307 was introduced to allow servers to make it clear to the user agent that a method change should not be made by the client when following the Location response header.

Http Redirect 307
Http redirect with status code 307 is similar to 302 Found, except that it does not allow changing the request method from POST to GET.

Examples of HTTP Headers in redirect 301, 302 and 307

HTTP headers in http redirect 301


POST /AutomatedSolution/AutomatedSolution.asmx HTTP/1.1
Host: test-nginx.secar.cz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: */*
Accept-Language: en-US,cs;q=0.8,sk;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: text/xml
Content-Length: 2982

HTTP/2.0 301 Moved Permanently
Server: nginx/1.14.0
Date: Thu, 01 Nov 2018 12:30:11 GMT
Content-Type: text/html
Content-Length: 185
Location: https://test-nginx.secar.cz/automatedsolution/automatedsolution.asmx
X-Firefox-Spdy: h2

GET /automatedsolution/automatedsolution.asmx HTTP/1.1
Host: test-nginx.secar.cz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: */*
Accept-Language: en-US,cs;q=0.8,sk;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: text/xml
DNT: 1
Connection: keep-alive

HTTP headers in http redirect 302


POST /AutomatedSolution/AutomatedSolution.asmx HTTP/1.1
Host: test-nginx.secar.cz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: */*
Accept-Language: en-US,cs;q=0.8,sk;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: text/xml
Content-Length: 2982
DNT: 1
Connection: keep-alive

HTTP/2.0 302 Found
Server: nginx/1.14.0
Date: Thu, 01 Nov 2018 12:43:58 GMT
Content-Type: text/html
Content-Length: 161
Location: https://test-nginx.secar.cz/automatedsolution/automatedsolution.asmx
X-Firefox-Spdy: h2

GET /automatedsolution/automatedsolution.asmx HTTP/1.1
Host: test-nginx.secar.cz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: */*
Accept-Language: en-US,cs;q=0.8,sk;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: text/xml
DNT: 1
Connection: keep-alive

HTTP headers in http redirect 307


POST /AutomatedSolution/AutomatedSolution.asmx HTTP/1.1
Host: test-nginx.secar.cz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: */*
Accept-Language: en-US,cs;q=0.8,sk;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: text/xml
Content-Length: 2982
DNT: 1
Connection: keep-alive

HTTP/2.0 307 Temporary Redirect
Server: nginx/1.14.0
Date: Thu, 01 Nov 2018 12:56:58 GMT
Content-Type: text/html
Content-Length: 187
Location: https://test-nginx.secar.cz/automatedsolution/automatedsolution.asmx
X-Firefox-Spdy: h2

POST /automatedsolution/automatedsolution.asmx HTTP/1.1
Host: test-nginx.secar.cz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: */*
Accept-Language: en-US,cs;q=0.8,sk;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Length: 2982
Content-Type: text/xml
DNT: 1
Connection: keep-alive

Rewrite url to lowercase without redirect - best solution


Add to your virtual host this config:

...
    rewrite ^(.*)[A-Z]+(.*)$ $my_uri_to_lowercase;
...

Explanation

This settings in virtual host config rewrite all large letters to small and make internal redirect to new url with all small letters.

Rewrite uri to lowercase in apache webserver


We need add this config to our virtual host as the first rewrite rule:

RewriteEngine On
RewriteMap  lc int:tolower
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule (.*) ${lc:$1} [R=301,L]