Ostatnio trafiłem na ciekawy problem, który wielokrotnie rozwiązywałem w nginx’ie ale tym razem musiałem zrobić to w Apache. Pewna stronka działa sobie na HTTPS’ie i chciałem by wszystkie powiązane z nią pliki były serwowane z jej adresu szyfrowanym połączeniem by nie pojawiały się w przeglądarce monity że “część ruchu nie jest szyfrowana”. Tyle że część potrzebnych plików była już obecnie serwowana na innym serwerze (w innej domenie) poprzez HTTP.
Mogłem albo skopiować te pliki i wykombinować jakiś mechanizm synchronizujący albo wykorzystać proxy + cache. Drugie rozwiązanie wydało mi się prostsze i ładniejsze 😃
Na początek włączamy w Apache’m odpowiednie moduły:
a2enmod proxy
a2enmod proxy_http
Teraz przykładowa konfiguracja vhosta:
<VirtualHost *:80>
#podstawowa konfiguracja vhosta
ServerAdmin webmaster@example.com
ServerName www.example.com
ServerAlias example.com
# wyłącza działanie Apache'go jako przekazującego proxy (forwarding proxy)
ProxyRequests Off
# nie chciałem by błędy HTTP z backendowego serwera były przekazywane
# zamiast nich będą błędy Apache'go
ProxyErrorOverride On
# przykład prostego reverse proxy - wystarczą dwa poniższe polecenia
# ProxyPass proxuje ruch do danego serwera pod wskazanym URL'em
ProxyPass /stats/ http://google-anal.com/
# ProxyPassReverse modyfikuje nagłówki odpowiedzi ze zdalnego serwera
# tak by odpowiedź wyglądała na wysłaną z lokalnego serwera
ProxyPassReverse /stats/ http://google-anal.com/
# ciekawszy przykład proxowania z dodatkowymi ustawieniami cachowania
# najpierw konfiguracja cache'u dyskowego
<IfModule mod_disk_cache.c>
# CacheRoot to wymagany parametr - ścieżka w której znajduje się cache
CacheRoot /var/cache/apache2/mod_disk_cache/example
# ponieważ przewidywałem że cache'owanych będzie kilka GB małych plików
# to by listowanie ich w cache'u było efektywne warto wykorzystać wielo
# poziomowe zagłębienie katalogów - wtedy na każdym poziomie, w danym
# katalogu będzie stosunkowo mało plików, indeksy mniejsze, listowanie
# szybsze
CacheDirLevels 5
CacheDirLength 2
# teraz czas na konfiguracje cache'u
<IfModule mod_cache.c>
# pozwolę sobie na zignorowanie nagłówków Expires/Cache-Control
# z aplikacji sam lepiej wiem że te pliki nie zmieniają się
# zbyt często
CacheIgnoreCacheControl On
# pliki stracą ważność w cache'u po tygodniu
CacheDefaultExpire 604800
# ponieważ zasoby nie różnią się dla różnych zalogowanych użytkowników
# zignoruję cookies'y
CacheIgnoreHeaders Set-Cookie
# nie chcę by proxy weryfikowało czy pojawiła się nowa wersja obrazka
# bo raczej rzadko pojawiają się zmiany
CacheIgnoreNoLastMod On
# cache uruchamiany dla dwóch "subkatalogów"
# http://example.com/images oraz http://example.com/files
CacheEnable disk /images
CacheEnable disk /files
</IfModule>
</IfModule>
# włączamy mod_rewrite - będzie za chwilkę potrzebny
RewriteEngine on
# poprzednio do uruchomienia proxy wykorzystałem opcję ProxyPass,
# ale często potrzebujemy bardziej zaawansowanego przekierowania
# i wtedy warto wykorzystać mod_rewrite do modyfikacji URL'i w locie
# koniecznie z flagą [P]
RewriteRule ^/images/(.+)/(.+) http://10.0.0.100:8080/example-images/get.php?id=$1&width=$2 [P]
<Location /images>
# jak powyżej - modyfikacja zwrotnych nagłówków
ProxyPassReverse /example-images/
# kilka nagłówków z backendu ukrywam by nie były przekazywane dalej
Header unset Server
Header unset Expires
Header unset ETag
# akurat nagłówek Via można wyłączyć w konfiguracji modułu proxy
# ale ponieważ bywa przydatny przy debugowaniu to w niektórych miejscach
# wolę gdy jest ustawiony - a w innych nie
Header unset Via
# ręczne ustawienie nagłówka Cache-Control i zezwolenie
# na cachowanie przez inne proxy lub przeglądarki
Header set Cache-Control "max-age=604800, public"
</Location>
# i drugie przekierowanie
RewriteRule ^/files/(.+)/(.+) http://10.0.0.100:8080/example-files/$1/$2 [P]
<Location /files>
ProxyPassReverse /example-files/
Header unset Server
Header unset Via
Header unset ETag
Header unset Expires
Header set Cache-Control "max-age=604800, public"
</Location>
# standardowa konfiguracja
DocumentRoot /var/www/example
<Directory /var/www/example>
Options -Indexes FollowSymLinks Includes
AllowOverride None
Order allow,deny
Allow from all
</Directory>
LogLevel warn
CustomLog /var/log/apache2/example_access.log combined
</VirtualHost>