Wędrując po internecie, niejednokrotnie natrafimy na błędne adresy URL. Czasami przyczyną błędu jest przeniesienie strony WWW do innego folderu, kiedy indziej literówka w adresie URL. Jeśli adres URL wskazuje nieistniejący plik, wówczas internauta ujrzy komunikat o błędzie. Ten artykuł opisuje, w jaki sposób przygotować własne strony błędów 404, wykorzystując serwer Apache oraz skrypty PHP.
Strony wyświetlane po podaniu błędnego adresu URL
Jeśli w przeglądarce internetowej wpiszesz
nieistniejący adres URL, to ujrzysz jeden z trzech
możliwych komunikatów. Pierwszym rodzajem błędu
jest podanie niepoprawnego adresu serwera.
Domena lorem.ipsum.pl nie jest opisana w DNS,
a zatem wpisanie w przeglądarce adresu:
http://lorem.ipsum.pl/dolor/sitamet.html
zakończy się błędem. W takiej sytuacji przeglądarka
wyświetli komunikat: Nie odnaleziono serwera.
Drugim rodzajem błędu jest podanie adresu
URL zawierającego poprawną nazwę serwera oraz
błędną nazwę pliku, np. {stala}http://example.net/lorem/ipsum/dolor.html{/stala}.
Domena example.net jest zarejestrowana i ma
stronę WWW, co możemy stwierdzić odwiedzając
witrynę {stala}http://example.net{/stala}. Jednak na serwerze nie
istnieje plik o nazwie: {stala}/lorem/ipsum/dolor.html{/stala}
W tej sytuacji serwer example.net wysyła
odpowiedź: HTTP/1.x 404 Not Found, na co przeglądarka reaguje, wyświetlając informację
Not found, widoczną na rysunku 1.
Trzecim rodzajem stron wyświetlanych w odpowiedzi
na nieistniejące adresy URL są dedykowane
strony obsługi błędu 404. Strona taka zazwyczaj
zachowuje stylistykę serwera, a przy tym zawiera
komunikat informujący o zaistniałym błędzie.
Rysunek 2 przedstawia stronę obsługi błędu 404
na serwerze google.pl po podaniu adresu: {stala}http://www.google.pl/lorem/ipsum/dolor.html{/stala}.
Mamy zatem trzy rodzaje informacji wyświetlanych
po podaniu nieistniejącego adresu URL:
- błędny adres serwera,
- poprawny adres serwera, błędna nazwa pliku,
serwer nie obsługuje błędów 404, - poprawny adres serwera, błędna nazwa pliku,
serwer obsługuje błędy 404.
Oczywiście w przypadku pierwszego rodzaju
błędu za wygląd wyświetlanej strony odpowiada
wyłącznie przeglądarka. Z punktu widzenia webmastera
jest to przypadek nieciekawy.
W artykule zajmiemy się tym, w jaki sposób na
serwerze zainstalować obsługę błędów 404 tak, by
zamiast komunikatu z rysunku 1 internauta ujrzał
ładną stronę WWW z rysunku 2. Podane przykłady
będą dotyczyły wyłącznie serwera Apache i interpretatora
PHP.
Dyrektywa ErrorDocument
Obsługę błędnych adresów URL przez serwer
Apache ustalamy dyrektywą ErrorDocument.
Dyrektywa ta może zostać umieszczona w ogólnym
pliku konfiguracyjnym serwera Apachehttpd.conf
lub w plikach .htaccess. Ponieważ firmy hostingowe
zazwyczaj nie umożliwiają modyfikowania
pliku httpd.conf, zatem w przykładach wykorzystam
pliki .htaccess.
Utwórz trzy pliki: .htaccess, error-404.html, error-
404.css i umieść je w folderze głównym htdocs/
serwera Apache.
W pliku .htaccess wprowadź jedną linijkę:
ErrorDocument 404 /error-404.html.
W pliku error-404.html wprowadź dowolny
komunikat, zaś w stylach error-404.css dowolnie
ustal wygląd witryny. Zwróć uwagę na to, by użyte
adresy URL były bezwzględne.
Adresy występują w dwóch miejscach:
- w dyrektywie ErrorDocument (/error-404.html),
- w elemencie link (/error-404.css).
Jeśli teraz podasz w przeglądarce adres:
{stala}http://localhost/lorem/ipsum/dolor.html{/stala},
ujrzysz wykonaną przed chwilą stronę błędu.
Jeśli użyjesz względnych adresów URL, obsługa
błędu 404 nie będzie wykonana poprawnie. Dyrektywa
ErrorDocument zawierająca adres względny:
ErrorDocument 404 error-404.html
nie działa, zaś użycie względnego adresu stylów:
spowoduje, że wyłącznie adresy URL dotyczące
foldera głównego, czyli np.
{stala}http://localhost/a.html{/stala},
będą sformatowane zgodnie z podanymi stylami.
W przypadku strony pochodzącej z podfolderu, np.
{stala}http://localhost/a/b/c/d.html{/stala},
style nie zostaną odnalezione.
Oczywiście strona obsługi błędu 404 może
zostać wykonana w języku PHP. Utwórz plik error-
-404.php z dowolnym komunikatem po czym
zmień dyrektywę ErrorDocument:
ErrorDocument 404 /error-404.php
Ustalanie odpowiedzi HTTP w PHP
W języku PHP kod odpowiedzi wysyłanej
przez serwer Apache możemy zmienić, wywołując
funkcję {stala}header():{/stala}
header(\'HTTP/1.x 404 Not Found\');
Należy pamiętać, że przed wywołaniem funkcji
{stala}header(){/stala} nie może pojawić się żadna instrukcja
wysyłająca dane (np. echo lub print). Skrypt:
jest niepoprawny.
Niektóre witryny stosują połowiczną obsługę
błędu 404, nazywaną soft 404. Polega to na tym,
że strona błędu 404 jest atrakcyjnie wizualna, ale
opatrzona nagłówkiem poprawnej odpowiedzi
HTTP, czyli
HTTP/1.x 200 OK
Usuwanie dostępu do plików
Jeśli skrypt składa się z kilku plików PHP dołączanych
instrukcją require_once, to należy pamiętać
o tym, aby żadne skrypty zawierające tajne informacje
nie były dostępne w ramach usługi WWW. Jeśli w pliku
db.inc zapiszemy hasło dostępu do bazy danych:
$link = mysql_connect(\'localhost\', \'appadm\', \'tajnehaslo\');
a plik umieścimy w folderze include/, to wystarczy
użyć adresu:
{stala}http://example.net/include/db.inc{/stala}
by poznać dane konta appadm.
Jeśli to tylko możliwe, wszystkie biblioteki,
szablony i pliki z danymi należy przenieść poza
drzewo katalogów widoczne w ramach usługi
WWW (np. poza folder public_html/). Niestety
wielu dostawców hostingu nie pozwala na taki
manewr: wszystkie pliki nagrywane na serwerze
znajdują się w folderze dostępnym poprzez WWW.
W takiej sytuacji należy wykorzystać plik .htaccess.
Dyrektywa:
Order allow,deny
Deny from all
wyłącza dostęp do plików, których nazwa kończy
się rozszerzeniem .php. W podobny sposób możemy
wyłączyć:
Order allow,deny
Deny from all
lub włączyć
Order allow,deny
Allow from all
dostęp do dowolnego rodzaju plików.
Przykład praktyczny
Jako przykład praktyczny przeanalizujmy dwie
witryny WWW. Jedna z nich będzie stosowała
zwykłe adresy URL, a druga – adresy przyjazne.
Witryny te są tak wykonane, by mogły zostać
umieszczone na serwerze udostępnianym przez
zewnętrzną firmę. Zakładamy, że:
- serwer obsługuje pliki .htaccess,
- wszystkie pliki umieszczane na serwerze są
dostępne poprzez WWW.
Przykładowa witryna Lorem ipsum
Wygląd witryny jest przedstawiony na rysunku
6. Jest ona wykonana w PHP przy wykorzystaniu
szablonów Smarty i plików tekstowych.
Poziome
menu witryny powstaje na podstawie pliku tekstowego
dane/menu.txt o zawartości:
Lorem|lorem.txt|2
Ipsum|ipsum.txt|3
Dolor|dolor.txt|4
Sit amet|sit-amet.txt|5
Każda linijka pliku opisuje jedną opcję. Kolejne
kolumny to:
- tytuł opcji umieszczany w menu strony,
- nazwa pliku tekstowego z zawartością strony,
- wartość zmiennej id użytej w adresie index.php?id=XXX.
Cała witryna stosuje następujące adresy URL:
- index.php?id=1 – strona błędu 404
- index.php?id=2 – strona lorem
- index.php?id=3 – strona ipsum
- index.php?id=4 – strona dolor
- index.php?id=5 – strona sit amet
- img/*.png – obrazy użyte na stronie
- style.css – style strony
Dodatkowo adres index.php jest przekierowaniem
do strony domyślnej lorem o adresie index.php?id=2.
Witryna składa się z plików i folderów przedstawionych
na rysunku 7. W ramach usługi WWW
dostępnymi plikami powinny być wyłącznie:
- index.php
- style.css
- img/*.png
żadne pliki z folderów:
- dane/
- include/
- template/
- template_c/
nie powinny być dostępne poprzez WWW.
Rozwiązanie pierwsze: witryna bez przyjaznych URL-i
W przypadku witryny, która nie stosuje przyjaznych
adresów URL, w pliku .htaccess umieszczamy
następujące dyrektywy:
- ustalamy stronę domyślną,
- definiujemy strony błędów,
- wyłączamy dostęp do plików.
Do ustalenia strony domyślnej stosujemy dyrektywy
Options oraz DirectoryIndex:
Options -Indexes
DirectoryIndex index.php
Pierwsza z nich wyłącza możliwość listowania
zawartości katalogu, a druga ustala, że adres
kończący się nazwą folderu, np.
{stala}http://localhost/przyklad/{/stala}
będzie odwoływał się do pliku:
{stala}http://localhost/przyklad/index.php{/stala}
Następnie ustalamy strony błędów:
ErrorDocument 404 /index.php?id=1
ErrorDocument 403 /index.php?id=1
pamiętając o tym, by w skrypcie index.php użyć funkcji
{stala}header(){/stala} do generowania nagłówka Not found:
if ($akcja == 1) {
header(\'HTTP/1.x 404 Not Found\');
} else {
...
}
Na zakończenie blokujemy dostęp do wszystkich
plików:
Order allow,deny
Deny from all
po czym odblokowujemy dostęp do plików index.
php, .css, .png oraz do folderu:
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Pełna zawartość pliku {stala}.htaccess{/stala} jest przedstawiona
na listingu 1.
Options -Indexes
DirectoryIndex index.php
ErrorDocument 404 /index.php?id=1
ErrorDocument 403 /index.php?id=1
Order allow,deny
Deny from all
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Rozwiązanie drugie: witryna z przyjaznymi adresami URL
Przypadek, w którym witryna stosuje przyjazne
adresy URL, jest nieco bardziej skomplikowany.
Options -Indexes
DirectoryIndex index.php
RewriteEngine on
RewriteRule ^error\.html$ index.php?id=1
RewriteRule ^lorem\.html$ index.php?id=2
RewriteRule ^ipsum\.html$ index.php?id=3
RewriteRule ^dolor\.html$ index.php?id=4
RewriteRule ^sit-amet\.html$ index.php?id=5
ErrorDocument 404 /error.html
ErrorDocument 403 /error.html
Order allow,deny
Deny from all
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Order allow,deny
Allow from all
Tym razem stosujemy adresy .html, które będą
przekierowane na skrypty PHP:
- error.html -> index.php?id=1
- lorem.html -> index.php?id=2
- ipsum.html -> index.php?id=3
- dolor.html -> index.php?id=4
- sit-amet.html -> index.php?id=5
Podobnie jak poprzednio, plik .htaccess rozpoczynamy
od ustalenia strony domyślnej:
Options -Indexes
DirectoryIndex index.php
Następnie dołączamy dyrektywy odpowiedzialne
za translacje adresów:
RewriteEngine on
RewriteRule ^error\.html$ index.php?id=1
RewriteRule ^lorem\.html$ index.php?id=2
RewriteRule ^ipsum\.html$ index.php?id=3
RewriteRule ^dolor\.html$ index.php?id=4
RewriteRule ^sit-amet\.html$ index.php?id=5
Po czym ustalamy strony błędów:
ErrorDocument 404 /error.html
ErrorDocument 403 /error.html
i blokujemy dostęp do plików.
W kodzie skryptu PHP możemy dodatkowo zablokować
dostęp do witryny adresami index.php:
if (preg_match(\'/index\.php/\', $_SERVER[\'REQUEST_URI\'])) {
header(\'Location: http://localhost/lorem.html\');
header(\'HTTP/1.x 301 Moved Permanently\');
}
Dzięki temu odwołania do stron:
index.php
index.php?id=2
index.php?id=3
...
będą przekierowywane na stronę główną.
Kody błędów protokołu HTTP
Liczba 404 obecna w dyrektywie ErrorDocument
jest jednym z tzw. kodów błędów protokołu
HTTP. Przeglądarka WWW wysyła do serwera
żądania (zdefiniowane protokołem HTTP). W odpowiedzi
serwer wysyła do przeglądarki odpowiedź
HTTP. Każda odpowiedź serwera musi rozpoczynać
się od kodu. Jeśli serwer nie może zrealizować
żądań klienta, wówczas przeglądarka może – na
podstawie kodu dołączonego do odpowiedzi – częściowo
poznać przyczyny niepowodzenia.
Kody błędów protokołu HTTP mają wartości od 400 do
417. Pełną listę błędów zawarto w specyfikacji RFC
2616, dostępnej pod adresem http://www.w3.org/
Protocols/rfc2616/rfc2616-sec10.html#sec10.4.
Przykładowymi błędami są:
- 400 Bad Request – błędne zapytanie HTTP,
- 401 Unauthorized – strona wymaga autoryzacji,
- 403 Forbidden – dostęp zabroniony,
- 404 Not Found – plik nie został odnaleziony.
Podglądanie odpowiedzi serwera WWW
Do analizy zapytań i odpowiedzi HTTP wymienianych
przez przeglądarkę i serwer można użyć wtyczki
LiveHTTPHeaders dla przeglądarki Firefox (dostępnej
do pobrania pod adresem http://livehttpheaders.mozdev.org) lub dodatku ieHTTPHeaders dla Internet
Explorera (dostępnego pod adresem http://www.blunck.se/iehttpheaders/iehttpheaders.html).
Po zainstalowaniu wtyczki LiveHTTPHeaders
wybierz z menu opcję Narzędzia > Live HTTP Headers.
Ujrzysz zakładkę wyświetlającą zapytania oraz odpowiedzi
HTTP wysyłane i odbierane przez przeglądarkę.
Przykładowo, po podaniu adresu: http://google.pl, serwer google.pl wysyła do przeglądarki odpowiedź
HTTP/1.x 200 OK widoczną na rysunku 3.
Odpowiedź wysyłana przez serwer google.pl
po podaniu adresu (strona z rysunku 2)
{stala}http://www.google.pl/lorem/ipsum/dolor.html{/stala} zawiera kod 404 widoczny na rysunku 4.
W ten sposób możesz sprawdzić kod odpowiedzi
HTTP wysyłany przez serwer WWW.
Dyrektywa ErrorDocument i pozostałe błędy HTTP
Poznana wcześniej dyrektywa ErrorDocument
zawiera dwa parametry: kod błędu oraz adres URL:
ErrorDocument kod-błędu url
Po wystąpieniu podanego błędu serwer Apache
wyśle w odpowiedzi do przeglądarki stronę o podanym
adresie URL. Na przykład dyrektywa:
ErrorDocument 403 /brak-dostepu.html,
będzie powodowała wysyłanie dokumentu brak-dostepu.html w odpowiedzi na błędy 403.
Przygotuj teraz cztery pliki:
- a/.htaccess,
- .htaccess,
- brak-dostepu.html,
- brak-dostepu.css
i umieść je w folderze głównym serwera Apache
zachowując strukturę widoczną na rysunku 5.
W pliku a/.htaccess umieść jedną linijkę:
Options -Indexes
Podana dyrektywa powoduje, że odwiedzenie przeglądarką adresu:
{stala}http://localhost/a/{/stala}
zakończy się komunikatem 403.
W pliku .htaccess wprowadź natomiast dyrektywę:
ErrorDocument 403 /brak-dostepu.html
W ten sposób skonfigurujesz obsługę błędów
403. Jeśli teraz odwiedzisz stronę:
{stala}http://localhost/a/{/stala}
to ujrzysz treść dokumentu brak-dostepu.html.
Oczywiście jeden plik .htaccess może zawierać
wiele dyrektyw ErrorDocument:
ErrorDocument 403 /brak-dostepu.html
ErrorDocument 404 /error-404.html
...
Ponadto obsługa wielu różnych błędów może być wykonywana przez jeden dokument:
ErrorDocument 403 /blad.html
ErrorDocument 404 /blad.html
...