This post comes from the first version of this blog.
Please send me an email if anything needs an update. Thanks!

W firmie, w której pracuję, zajmuję się m. in. utrzymaniem portalu, który jest osadzony na kilku subdomenach określających poszczególne regiony Polski. Na podstawie tej informacji użytkownik widzi na stronie tylko wiadomości, które są związane z wybraną przez niego częścią kraju. W dzisiejszym wpisie chciałbym pokazać Wam, jak zasymulować takie zachowanie na serwerze lokalnym.

Problem.

Rozważmy następujący przykład: projektujemy ogólnoświatowy portal, który ma za zadanie prześcignąć pod względem popularności Google i Facebooka razem wziętych. Plany bardzo ambitne, aczkolwiek naszym głównym celem będzie umożliwienie użytkownikowi wyboru kontynentu na którym się znajduje - dostanie on wtedy materiały dotyczące tylko tej części świata. Nazwiemy naszą witrynę bardzo ambitnie - będzie to międzynarodowa korporacja Example, a strona główna portalu znajdzie się pod, a jakże, domeną example.com. Subdomeny, jakie nas interesują, to:

europe.example.com asia.example.com northamerica.example.com southamerica.example.com africa.example.com australia.example.com
Przypuśćmy, że Antarktydę i Arktykę pominiemy, bo nie są one zbyt medialne. ;]

Ze względu na to, że chcemy utrzymać maksymalną spójność serwisu zarówno pod względem logicznym jak i fizycznym nie możemy sobie pozwolić na odniesienie tych domen do różnych katalogów - wszystko ma być podpięte pod jeden kod i na podstawie odpowiednich instrukcji po stronie serwera przekazywany parametr informujący o wybranym kontynencie. Zobaczmy więc, co da się w tej kwestii zrobić.

Rozwiązanie.

Tym, którzy nie wiedzą, jak tworzy się vhosty polecam jeden z moich wcześniejszych wpisów, gdzie wyjaśniłem dokładnie, krok po kroku, jak podpiąć jedną domenę pod jeden katalog. W tym wpisie skupię się tylko na informacjach, jak do utworzonego już wirtualnego hosta dołączyć inne domeny tak, aby wskazywały w to samo miejsce co oryginalny adres.

W ramach przypomnienia pozwolę sobie wstawić kod vhosta z wspomnianego wyżej wpisu:

<VirtualHost *:80>
DocumentRoot [ścieżka]
ServerName example.com
</VirtualHost>

Widzimy, że nazwę domeny określa dyrektywa ServerName. Aby określić pozostałe domeny będziemy potrzebowali oddzielnej dyrektywy - jest nią ServerAlias. Jego działanie polega właśnie na “podłączeniu” podanej listy domen i takim samym wskazaniu na ścieżkę zawartą w dyrektywie DocumentRoot jak oryginalna domena. Dokumentacja serwera Apache tłumaczy całość następująco:

ServerAlias Directive Description:    Alternate names for a host used when matching requests to name-virtual hosts Syntax:    ServerAlias hostname [hostname] ... Context:    virtual host Status:    Core Module:    core

The ServerAlias directive sets the alternate names for a host, for use with name-based virtual hosts.

<VirtualHost *> ServerName server.domain.com ServerAlias server server2.domain.com server2

Jak widzimy, dyrektywa ServerAlias akceptuje listę nazw domen oddzielonych spacjami, które mają stanowić aliasy dla głównej. Zróbmy więc tak, jak nam nakazali developerzy serwera Apache. Nasza deklaracja vhosta wzbogaci się więc o jedną linijkę:

<VirtualHost *:80>
DocumentRoot [ścieżka]
ServerName example.com
ServerAlias europe.example.com asia.example.com northamerica.example.com southamerica.example.com africa.example.com australia.example.com
</VirtualHost>

Kod wynikowy jest mało czytelny, dlatego lepiej jest zapisać aliasy w postaci osobnych wpisów [tak też można ;]]:

<VirtualHost *:80>
DocumentRoot [ścieżka]
ServerName example.com
ServerAlias europe.example.com
ServerAlias asia.example.com
ServerAlias northamerica.example.com
ServerAlias southamerica.example.com
ServerAlias africa.example.com
ServerAlias australia.example.com
</VirtualHost>

Oczywiście w tym momencie nie zadziała to jeszcze , ponieważ rzeczone domeny nie istnieją w pliku hosts. Dopiszmy zatem odpowiednie dane do tego pliku:

127.0.0.1 europe.example.com
127.0.0.1 asia.example.com
127.0.0.1 northamerica.example.com
127.0.0.1 southamerica.example.com
127.0.0.1 africa.example.com
127.0.0.1 australia.example.com

Teraz istnieją zarówno wpisy w deklaracji vhosta jak i w tablicy hosts systemu operacyjnego. Restartujemy Apache i możemy się połowicznie ucieszyć - wpisanie w pasku adresu każdej subdomeny kieruje nas do naszego serwisu. Dlaczego połowicznie? Ponieważ nasz skrypt jeszcze nie wie, jak “wyłuskać” informację o kontynencie. Ta część jest jednak trywialnie prosta - wykorzystamy tablicę $_SERVER dobrze znaną wszystkim z języka PHP. Zawiera ona w sobie indeks SERVER_NAME, którego wartość zostanie ustawiona na domenę, z której został wywołany nasz skrypt. Wystarczy więc wyciągnąć żądaną informację za pomocą prostego kodu [oczywiście można też skorzystać z wyrażenia regularnego, kwestia gustu ;]]:

1
2
3
4
// sample domain: europe.example.com
$pieces = explode('.', $_SERVER['SERVER_NAME']);
// equals to array('europe', 'example', 'com')
$continent = $pieces[0];

I zmusić skrypt do generowania zawartości odpowiedniej dla tej części świata. Prawda, że proste?

Podsumowanie.

Powyższe informacje można też zastosować w przypadku publicznego serwera dostępnego w Internecie. Jedyne, co musimy zrobić to zmienić adres IP na odpowiedni - zamiast tradycyjnego, lokalnego 127.0.0.1. Mam nadzieję, że rozjaśniło Wam to możliwości, jakie możemy uzyskać za pomocą kilku linijek w kilku plikach. ;] Żeby zamknąć temat należałoby jeszcze pokazać możliwości oferowane przez zastosowanie wildcardów w nazwie domeny, ale to już chyba materiał na kolejny artykuł [na pewno ukaże się w przyszłości ;]]. Pozdrawiam i do zobaczenia w niedzielę w Linkdumpie... numer 22!