Uppercase- auf Lowercase-URLs umschreiben per nginx Rewrite Rule

Wenn Sie eine URL mit Großbuchstaben wie z.B. http://www.example.com/BEISPIEL.html oder http://www.example.com/BEIspiel.html auf ihr Pendant mit Kleinbuchstaben (also http://www.example.com/beispiel.html) per Rewrite Rule umschreiben möchten, könnten Sie unter Apache die folgende Rewrite Rule in einer .htaccess-Datei verwenden:

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

 

Umleitung per nginx-Perl-Modul

Unter nginx können Sie das nginx-Perl-Modul (ngx_http_perl_module) verwenden, die entsprechende Rewrite Rule könnte dann so aussehen...

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

... oder so:

http {
[...]
  perl_modules perl/lib;

  perl_set $uri_lowercase 'sub {
    my $r = shift;
    my $uri = $r->uri;
    $uri = lc($uri);
    return $uri;
  }';
[...]
}

server {
[...]
  location / {
    if ( $uri != $uri_lowercase ) {
      rewrite . http://$host$uri_lowercase;
    }
  }
[...]
}

Nun ist es leider so, daß das nginx-Perl-Modul nicht in allen nginx-Installationen vorhanden ist, nginx muß mit der Option --with-http_perl_module kompiliert worden sein. Unter Debian und Ubuntu müssen Sie z.B. mit apt das Paket nginx-extras statt nginx-full installieren, um in den Genuß des Perl-Moduls zu kommen. Ob Ihr nginx das Perl-Modul mitbringt, können Sie mit dem Befehl

nginx -V

prüfen - in der Ausgabe sollte --with-http_perl_module aufgelistet sein.

 

Umleitung per PHP-Skript

Falls Ihr nginx nicht das Perl-Modul enthält, gibt es die folgende Möglichkeit, Uppercase-URLs auf Lowercase-URLs umzuschreiben. Dabei werden URLs, die Großbuchstaben enthalten, intern und nach außen unsichtbar auf ein PHP-Skript umgeleitet, das mit der strtolower()-Funktion die URL in Kleinbuchstaben umwandelt und dann mit der header()-Funktion einen 301-Redirect auf die Kleinbuchstaben-URL durchführt.

Das PHP-Skript, wir nennen es hier lower.php, wird ins Document Root gelegt und sieht so aus:

<?php
$uri = $_SERVER['REQUEST_URI'];
$uri_lower = strtolower( $uri );
$location = ($_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
$location .= '://' . $_SERVER['HTTP_HOST'] . $uri_lower;
header( "Location: $location", true, "301" );
exit;
?>

Die Rewrite Rule für nginx prüft erst, ob Großbuchstaben in der URL vorkommen und im nächsten Schritt, ob die angefragte Datei existiert (wenn ja, soll die Datei natürlich direkt ausgeliefert werden, wir brauchen dann keine Umleitung auf die Lowercase-URL). Wenn die Datei nicht existiert, dann wird nach außen unsichtbar auf die PHP-Datei lower.php umgeschrieben, die dann den 301-Redirect auf die Lowercase-URL durchführt.

So sieht die Rewrite Rule für nginx dann im Endeffekt aus:

if ($uri ~ "[A-Z]"){
    set $uc 1;
}
if (!-e $request_filename) {
    set $uc 2$uc;
}
if ($uc = 21) {
    rewrite ^ /lower.php last;
}

Nach oben