Htaccess: dodaj / usuń końcowy ukośnik z adresu URL

81

Moja witryna internetowa uruchamia skrypt o nazwie -> skrypt tapety WSS

Mój problem -> Próbowałem wymusić usunięcie lub dodanie końcowego ukośnika na końcu mojego adresu URL, aby zapobiec powielaniu treści, a także wyczyścić moje adresy URL.

Próbowałem wszystkich rodzajów i próbowałem wszystkiego, o czym mogłem pomyśleć i ładunków z interwebów, ale nie mam jeszcze szczęścia! To może być szybka naprawa, ale patrzyłem na to tak często, że prawdopodobnie jestem ślepy na coś martwego i oczywistego.

Przedstawiam więc cały mój .htaccesskod:

DirectoryIndex index.php

RewriteEngine on
RewriteRule ^download/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+) image.php?id=$1&width=$2&height=$3&cropratio=$4&download=1 [L]
RewriteRule ^file/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+) image.php?id=$1&width=$2&height=$3&cropratio=$4 [L]
RewriteRule ^preview/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+) wallpaper_preview.php?id=$1&width=$2&height=$3&name=$4 [L]
RewriteRule ^thumbnail/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+)/([^/\.]+)/([^/\.]+)/([^/]+) image.php?wallpaper_id=$1&width=$2&height=$3&cropratio=$4&align=$5&valign=$6&file=$7 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+)/p([0-9]+) index.php?task=category&id=$1&name=$2&page=$3 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+)/([0-9a-zA-Z?-]+)/p([0-9]+) index.php?task=category&id=$1&name=$2&sortby=$3&page=$4 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+)/([0-9a-zA-Z?-]+)-([0-9]+) index.php?task=category&id=$1&sortby=$3&page=$4 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+) index.php?task=category&id=$1&name=$2 [L]
RewriteRule ^tag/([^/\.]+)/([0-9a-zA-Z?-]+)/([0-9]+) index.php?task=tag&t=$1&sortby=$2&page=$3 [L]
RewriteRule ^tag/([^/\.]+) index.php?task=tag&t=$1 [L]
RewriteRule ^profile/([0-9]+)?/([^/\.]+) index.php?task=profile&id=$1&name=$2 [L]
RewriteRule ^profile/comments/([0-9]+)?/([^/\.]+) index.php?task=users_comments&id=$1&name=$2 [L]
RewriteRule ^page/([0-9]+) index.php?task=view_page&id=$1 [L]  
RewriteRule ^register index.php?task=register [L] 
RewriteRule ^lost-password index.php?task=lost_pass [L] 
RewriteRule ^links index.php?task=links [L]
RewriteRule ^news/item/([0-9]+)/([^/\.]+) index.php?task=news&id=$1 [L]
RewriteRule ^news/page([0-9]+) index.php?task=news&page=$1 [L]
RewriteRule ^members/([^/\.]+)-([^/\.]+)/page([0-9]+)? index.php?task=member_list&sort=$1&order=$2&page=$3 [L]
RewriteRule ^members index.php?task=member_list [L]
RewriteRule ^messages index.php?task=messages [L]
RewriteRule ^submit index.php?task=submit [L]
RewriteRule ^search/([^/\.]+) index.php?task=search&q=$1 [L]
RewriteRule ^search index.php?task=search [L]
RewriteRule ^submit index.php?task=submit [L]
RewriteRule ^r-([0-9]+)?-([0-9]+)? go.php?id=$1&ref=$2 [L]
RewriteRule ^r-([0-9]+)? go.php?id=$1 [L]
RewriteRule ^([^/\.]+)/([0-9]+)/([^/\.]+) index.php?task=view&id=$2&name=$3 [L]
RewriteRule ^news/([^/\.]+) index.php?task=news&name=$1 [L]
RewriteRule ^profile/([^/\.]+) index.php?task=profile&name=$1 [L]
RewriteRule ^news index.php?task=news [L]
RewriteRule ^page/([^/\.]+) index.php?task=view_page&name=$1 [L]  
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([0-9a-zA-Z'?-]+)/([0-9]+) index.php?task=category&name=$1&sortby=$2&page=$3 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([^/\.]+) index.php?task=view&name=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+) index.php?task=category&name=$1 [L]


## www reslove ##
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
## www reslove ##

## index reslove ##
Options +FollowSymLinks
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ http://www.epicwallpaper.net/$1 [R=301,L]
## index reslove ##
Łukasz
źródło
1
Również, jeśli ktoś może naprawić złego chłopca, czy mógłbyś napisać odpowiedź tutaj Dziękuję
Luke
Wpisz kod tutaj.
Surreal Dreams
1
Edytuj swój post, wklej kod do swojego posta, zaznacz go, naciśnij "CTRL + K", aby sformatować go jako kod
Jon Lin
Czy naprawdę trzeba " lub ? dozwolone w Twoim URI? Tak sugeruje jeden z RewriteRules (u dołu). Obawiam się, że mogą zmylić serwer, zanim .htaccess będzie mógł je przetworzyć.
Phil Perry

Odpowiedzi:

199

Tuż pod RewriteEngine Onlinią dodaj:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R] # <- for test, for prod use [L,R=301]

wymusić zasadę braku końcowego ukośnika.

Aby wymusić zasady z ukośnikiem końcowym:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R] # <- for test, for prod use [L,R=301]

EDYCJA : skomentował R=301części, ponieważ, jak wyjaśniono w komentarzu:

Uważaj z tymR=301 ! Posiadanie go sprawia, że ​​wiele przeglądarek buforuje plik .htaccess na czas nieokreślony : staje się to w jakiś sposób nieodwracalne, jeśli nie możesz wyczyścić pamięci podręcznej przeglądarki na wszystkich komputerach, które go otworzyły. Podczas testowania lepiej użyj prostego RlubR=302

Po zakończeniu testów możesz użyć R=301.

Jon Lin
źródło
4
Boże, mógłbym cię pocałować! Pracowałem z wymuszeniem zerowego ukośnika, drugi dał mi błąd serwera 500 Dziękuję Jon Lin!
Łukasz
22
Reguła no-trailing-slash nie działa, jeśli witryna znajduje się w katalogu (takim jak example.org/blog/)
Gras Double
8
Uważaj z tym R=301! Posiadanie go sprawia, że ​​wiele przeglądarek buforuje plik .htaccess na czas nieokreślony: staje się to w jakiś sposób nieodwracalne, jeśli nie możesz wyczyścić pamięci podręcznej przeglądarki na wszystkich komputerach, które go otworzyły. Podczas testowania lepiej użyj prostego „R” lub „R = 302”
Jonathan Weber
Gdy VirtualDocumentRoot jest wyłączony, usuń ukośnik na początku, tj .: $1zamiast /$1And, @JonathanWeber, plik .htaccess nie jest obsługiwany, ale nagłówek expires informuje przeglądarki, jak długo buforować zasób.
twicejr
1
@Nrc, ponieważ oprócz plików i katalogów istnieją inne typy mapowań, a także istnieje możliwość, że żądanie nie jest mapowane ani na plik, ani na katalog, ale musi zostać przepisane. Wartość ujemna zapewnia, że ​​coś, co zostało przepisane lub już zostało odwzorowane na coś w systemie plików, zostanie pominięte.
Jon Lin
84

Aby uzupełnić odpowiedź Jona Lina, oto technika bez ukośnika, która działa również, jeśli witryna znajduje się w katalogu (takim jak example.org/blog/):

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]


W trosce o kompletność, oto alternatywne podkreślenie, które REQUEST_URIzaczyna się od ukośnika (przynajmniej w .htaccessplikach):

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /(.*)/$
RewriteRule ^ /%1 [R=301,L] <-- added slash here too, don't forget it

Po prostu nie używaj %{REQUEST_URI} (.*)/$ . Ponieważ w katalogu głównym REQUEST_URIjest równy /wiodący ukośnik i zostałby błędnie zinterpretowany jako końcowy ukośnik.


Jeśli chcesz przeczytać więcej:

(aktualizacja: ta technika jest teraz zaimplementowana w Laravel 5.5)

Gras Double
źródło
1
Ten konkretny wariant jest naprawdę przydatny, zwłaszcza w przypadku korzystania z nowoczesnych konwencji adresów URL. Mam nadzieję, że nie masz nic przeciwko, przesyłam to do repozytorium fragmentów htaccess .
alexw
1
Eliminuje to problem, gdy REQUEST_URI (root) jest interpretowane jako końcowy ukośnik, który również powoduje nieskończoną pętlę. Dziękuję
Ruslan Abuzant
Tak, zaakceptowana odpowiedź nie jest obsługiwana, jeśli witryna znajduje się w katalogu, ale ta odpowiedź z RewriteCond %{REQUEST_URI} (.+)/$tylko jednym końcowym ukośnikiem (np. Wymagane jest kilka przekierowań z sth /// do sth // do sth / do sth). Aby usunąć wszystkie końcowe ukośniki w jednym przekierowaniu, użyj lepszego rozwiązaniaRewriteCond %{REQUEST_URI} (.+?)/+$
mikep
1
Też o tym myślałem. Chociaż wynik jest poprawny i biorąc pod uwagę przypadek skrajny, wolałem prostotę kodu.
Gras Double
@GrasDouble, dziękuję, że szukałeś tego rozwiązania przez długi czas. wypróbowałeś niezliczone metody, ale twój działał dobrze! wielkie dzięki.
3

Właśnie tego użyłem w mojej najnowszej aplikacji.

# redirect the main page to landing
##RedirectMatch 302 ^/$ /landing

# remove php ext from url
# /programming/4026021/remove-php-extension-with-htaccess
RewriteEngine on 

# File exists but has a trailing slash
# /programming/21417263/htaccess-add-remove-trailing-slash-from-url
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?(.*)/+$ /$1 [R=302,L,QSA]

# ok. It will still find the file but relative assets won't load
# e.g. page: /landing/  -> assets/js/main.js/main
# that's we have the rules above.
RewriteCond %{REQUEST_FILENAME} !\.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f 
RewriteRule ^/?(.*?)/?$ $1.php
Svetoslav Marinov
źródło
1
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
## hide .html extension
# To externally redirect /dir/foo.html to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+).html
RewriteRule ^ %1 [R=301,L]

RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)/\s
RewriteRule ^ %1 [R=301,L]

## To internally redirect /dir/foo to /dir/foo.html
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^([^\.]+)$ $1.html [L]


<Files ~"^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</Files>

To usuwa kod html lub php, jeśli go uzupełnisz. Pozwala na dodanie końcowego ukośnika i pojawi się wraz z adresem URL bez końcowego ukośnika, a wszystko to z pominięciem kodu 404. Plus trochę dodatkowego bezpieczeństwa.

Scout Hynson
źródło
Cześć, jak byś to napisał dla nginx? Próbowałem uruchomić go w konwerterze tutaj: winginx.com/en/htaccess, ale ten wynik daje mi nieskończoną pętlę:# nginx configuration location / { rewrite ^(.*)$ /%1 redirect; rewrite ^(.*)$ /%1 redirect; rewrite ^/([^\.]+)$ /$1.html break; } location ~ ^.*\.([Hh][Tt][Aa]) { deny all; }
Asle