Suppression de la barre oblique finale d'une URL avec nginx

14

Je voudrais que les URL suivantes sur mon site soient équivalentes:

/foo/bar
/foo/bar/
/foo/bar/index.html

et en outre, je voudrais que les deux seconds formulaires émettent des redirections HTTP 301 vers le premier formulaire. Je ne sers que des pages statiques, et elles sont organisées selon le troisième formulaire. (En d'autres termes, lorsqu'un utilisateur demande, /foo/baril doit recevoir le fichier à l'adresse /usr/share/.../foo/bar/index.html).

Mon nginx.confcontient actuellement les éléments suivants:

rewrite ^(.+)/$ $1 permanent;
index index.html;
try_files $uri $uri/index.html =404;

Cela fonctionne pour les demandes de /foo/bar/index.html, mais lorsque je demande /foo/barou que /foo/bar/Safari me dit que «trop de redirections se sont produites» - je suppose qu'il y a une boucle de redirection infinie ou quelque chose comme ça. Comment puis-je demander à nginx de mapper des URL à des fichiers comme je l'ai décrit?

Edit: Ma configuration complète

Voici mon tout nginx.confavec mon nom de domaine remplacé par "example.com".

user www-data;
worker_processes 1;
pid /run/nginx.pid;

events {
  worker_connections 768;
}

http {
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  types_hash_max_size 2048;
  server_tokens off;

  server_names_hash_bucket_size 64;

  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss application/atom+xml text/javascript image/svg+xml;

  server {
    server_name www.example.com;
    listen 80;
    return 301 $scheme://example.com$request_uri;
  }

  server {
    server_name example.com 123.45.67.89 localhost;
    listen 80 default_server;

    # Redirect /foobar/ to /foobar
    rewrite ^(.+)/$ $1 permanent;

    root /usr/share/nginx/www/example.com;
    index index.html;
    try_files $uri $uri/index.html =404;

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
      root /usr/share/nginx/html;
    }
  }
}
bdesham
la source
Ces fichiers existent-ils réellement sur le système de fichiers?
Michael Hampton
@MichaelHampton Oui. Les demandes de /foo/bar/index.htmldoivent renvoyer le fichier à /usr/share/nginx/www/foo/bar/index.htmlou quelle que soit sa configuration. Tous les chemins du site Web correspondent directement aux chemins du système de fichiers.
bdesham
@bdesham Je ne peux pas reproduire. Voici ce que j'obtiens avec votre config paste.ubuntu.com/7501697
Alexey Ten
@AlexeyTen Il est étrange que vous obteniez quelque chose de différent. Merci de l'avoir regardé. J'ai publié une configuration qui a fini par fonctionner pour moi.
bdesham

Réponses:

19

Avoir cette expression régulière sur votre serverbloc:

rewrite ^/(.*)/$ /$1 permanent;

redirigerait toutes les URL de barre oblique finale vers la barre oblique non finale respective.

Francisco Costa
la source
1
Cela ne répond qu'à une partie de la question.
bdesham
5
Cela concerne le titre complet de la question.
Jivan
5

J'ai pu obtenir mon comportement souhaité en l'utilisant comme serverbloc final dans ma configuration:

server {
  server_name example.com 123.45.67.89 localhost;
  listen 80 default_server;

  # Redirect /foobar/ and /foobar/index.html to /foobar
  rewrite ^(.+)/+$ $1 permanent;
  rewrite ^(.+)/index.html$ $1 permanent;

  root /usr/share/nginx/www/example.com;
  index index.html;
  try_files $uri $uri/index.html =404;

  error_page 404 /404.html;
  error_page 500 502 503 504 /50x.html;

  location = /50x.html {
    root /usr/share/nginx/html;
  }
}
bdesham
la source
Cela ne semble pas fonctionner pour moi - l' /index.htmlURL reçoit une réponse avec HTTP 200 au lieu d'une redirection; les lignes de "réécriture" sont ignorées. Est-ce toujours d'actualité?
Christoph Burschka
1

N'utilisez jamais la réécriture:

  location ~ (?<no_slash>.*)/$ {
       return 301 $scheme://$host$no_slash;
  }
Eldar Agalarov
la source
Pouvez-vous expliquer pourquoi vous ne pensez pas que la réécriture est une bonne idée?
bdesham
La raison pour laquelle vos liens suggèrent d'éviter les réécritures est pour une meilleure lisibilité, non pas parce qu'ils peuvent provoquer des effets secondaires involontaires. Votre réponse est beaucoup moins lisible querewrite ^(.+)/+$ $1 permanent;
chrBrd
1
Ceci est une bonne réponse, je ne sais pas pourquoi elle est rejetée. L'article a un titre "Taxing Rewrites" qui explique pourquoi rewritepeut être mauvais. Cela étant dit, la réponse fournie capture et correspond également à l'URI, je ne sais pas si cela améliorera les performances, il doit être testé. Utilisez (?<no_slash>.+)/$plutôt cette expression régulière pour ne pas rediriger la page d'accueil.
Razor
0
if ($request_uri ~ (.*?\/)(\/+)$ ) {
return 301 $scheme://$host$1;
}

Cette règle prendra en charge n'importe quel nombre de barres obliques de fin et conservera l'URL. Il prendra également en charge les barres obliques de fin des URL de base

Ashish Amre
la source