Odpowiedzi:
To jest błąd w kodzie programistów / programistów. Jeśli porównasz te dwa adresy URL:
http://www.example.com/A/B/C/
http://www.example.com/A/B//C/
Wyglądają inaczej, ale gdybyś je odwiedził, oba działałyby w większości nowoczesnych przeglądarek.
To jest coś, co chcesz naprawić. Jeśli masz podwójny ukośnik, może pomylić roboty indeksujące Google i sprawić, że będą myśleć, że istnieją 2 wersje strony.
Jak wspomniano w @RandomBen , podwójne cięcie jest najprawdopodobniej wynikiem błędu.
To, że strona się ładuje, nie ma nic wspólnego z przeglądarką , ale raczej, że serwer ignoruje dodatkowe ukośniki. Przeglądarka nie robi nic specjalnego z dodatkowymi ukośnikami w adresie URL, po prostu wysyła je wraz z żądaniem:
GET /A/B//C/D HTTP/1.1
Host: www.example.com
...
Wygląda na to, że obecne wersje Apache i IIS zignorują dodatkowe ukośniki podczas rozwiązywania ścieżki i zwrócą dokument, który zostałby zwrócony, gdyby adres URL nie zawierał dodatkowych ukośników. Jednak przeglądarki (testowałem IE 8 i Chrome 9) są mylone przez względne adresy URL (zawierające komponenty ścieżki nadrzędnej) zasobów na stronie, co daje złe wyniki. Na przykład jeśli strona ma:
<link rel="stylesheet" href="../../style.css" type="text/css" />
Po załadowaniu strony /a/b/c/
przeglądarka zażąda /a/style.css
. Ale jeśli - z jakiegokolwiek powodu - /a/b//c/
zostanie zażądany (a serwer zignoruje dodatkowy ukośnik), przeglądarka skończy z żądaniem /a/b/style.css
, które nie będzie istnieć. Ups, strona wygląda brzydko.
(To oczywiście nie nastąpi, jeśli adres URL nie zawiera komponentu ścieżki nadrzędnej ( ..
) lub jest bezwzględny).
To jest moja opinia, że Apache i IIS (i prawdopodobnie innych) działają nieprawidłowo , jak /a/b/c/
i /a/b//c/
technicznie reprezentują dwa różne zasoby. Według RFC 2396 każdy ukośnik jest znaczący:
path = [ abs_path | opaque_part ]
path_segments = segment *( "/" segment )
segment = *pchar *( ";" param )
param = *pchar
pchar = unreserved | escaped |
":" | "@" | "&" | "=" | "+" | "$" | ","
Tak więc /a/b/c/
składa się z trzech segmentów: „a”, „b” i „c”; /a/b//c/
właściwie składa się z czterech: „a”, „b”, „” (pusty ciąg) i „c”. To, czy pusty ciąg znaków jest poprawnym katalogiem systemu plików, jest szczegółem platformy serwera. (I logicznie oznacza to, że przeglądarki faktycznie działają poprawnie podczas analizowania względnych adresów URL ze składnikami ścieżki nadrzędnej - w moim przykładzie przechodzą one powyżej katalogu „c” i katalogu „”, pozostawiając nam żądanie style.css
z „b”.)
Jeśli używasz Apache z mod_rewrite
, istnieje dość prosta poprawka :
# remove multiple slashes anywhere in url
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
Spowoduje to 301 Moved Permanently
przekierowanie HTTP, dzięki czemu wszelkie podwójne ukośniki zostaną usunięte z adresu URL.
mod_rewrite
rozwiązanie uwzględniało także 3, 4, ... ukośniki? Coś w stylu /{2,}
? (Zakładając, że Apache zezwala na tego rodzaju kwantyfikator, nie znam go zbyt dobrze)
a/b
i a//b
rzeczywiście są dwie odrębne ścieżki URL, ale nic nie zabrania serwer z powrotem ten sam zasób dla obu z nich, jeśli chce. Zgadzam się jednak z tobą, że w praktyce zwrócenie przekierowania 301 wydaje się bardziej przydatne.
a//b
jako katalog (patrz przykład arkusza stylów powyżej).
Podwójny ukośnik ma znaczenie, gdy jest używany w adresach URL zasobów. Na przykład, gdy jest użytkownikiem CSS dla adresu URL obrazu tła:
.classname {
background : url("//example.com/a/b/c/d.png");
}
Oznacza to, że obraz tła pobiera się z innej domeny niż domena bieżącej strony internetowej. Innymi słowy, http://
można go zapisać tak, jak w //
przypadku użycia go w adresach URL zasobów.
Ale ten podwójny ukośnik między adresami URL (np . /a//b/c/d.htm
:) nie ma żadnego znaczenia.
Jak wspomniano, niektóre serwery są skonfigurowane tak, aby ignorować podwójny ukośnik w ścieżce adresu URL, ale statyczny hosting Amazon S3 nie. Jeśli chcesz je obsłużyć / zignorować, możesz użyć Reguł przekierowania w panelu właściwości.
Jeśli chcesz zignorować podwójny ukośnik następujący po nazwie domeny, możesz użyć czegoś takiego:
<RoutingRules>
<RoutingRule>
<Condition>
<KeyPrefixEquals>/</KeyPrefixEquals>
</Condition>
<Redirect>
<ReplaceKeyPrefixWith/>
</Redirect>
</RoutingRule>
</RoutingRules>
Prawdopodobnie możesz je również znaleźć i wymienić na cały, ale to mi wystarczyło.