
Fiche
dOOnet! projects

Version 1.3 de serveur de HTTP d'Apache
Est-ce que c'est la version que vous voulez ? Pour assurer des versions plus
récentes, examiner notre index de documentation.
Apache 1.3
URL récrivant le guide
À l'origine écrit près
Ralf S. Engelschall <rse@apache.org>
Décembre 1997
Ce document complète la documentation de référence de
mod_rewrite. Il décrit comment on peut employer le mod_rewrite d'Apache
pour résoudre les problèmes URL-basés typiques avec lesquels
des webmasters sont souvent confrontés. Nous donnons des descriptions
détaillées sur la façon dont résoudre chaque problème
en configurant l'URL récrivant des rulesets.
Introduction au mod_rewrite
Le mod_rewrite de module d'Apache est un tueur un, c.-à-d. c'est un
module vraiment sophistiqué qui fournit une manière puissante
de faire des manipulations d'URL. Avec lui vous pouvez faire presque tous
les types de manipulations d'URL que vous jamais avez rêvées
environ. Le prix que vous devez payer est d'accepter la complexité,
parce que l'inconvénient principal des mod_rewrite est qu'il n'est
pas facile de comprendre et employer pour le débutant. Et même
les experts en matière d'Apache découvrent parfois de nouveaux
aspects où le mod_rewrite peut aider.
En d'autres termes : Avec le mod_rewrite vous l'une ou l'autre pousse en
pied la première fois et ne l'employez encore vous-même jamais
ou l'aimez pour le reste de votre vie en raison de sa puissance. Cet article
essaye de te donner quelques événements initiaux de succès
pour éviter le premier cas en te présentant les solutions déjà
inventées.
Solutions pratiques
Voici venir beaucoup de solutions pratiques que je me suis inventées
ou me suis rassemblées d'autres solutions de peuples dans le passé.
Se sentir libre pour apprendre la magie noire de l'URL récrivant de
ces exemples.
ATTENTION : Selon votre serveur-configuration il peut être nécessaire
de changer légèrement les exemples pour votre situation, par
exemple ajoutant le drapeau [pinte] en utilisant en plus les mod_alias et
le mod_userdir, etc. Ou récrivant un ruleset pour s'adapter dans le
contexte de .htaccess au lieu du contexte de par-serveur. Essayer toujours
de comprendre ce qu'un ruleset particulier fait vraiment avant que vous l'employiez
afin d'éviter des problèmes.
Disposition d'URL
URLs canonique
Description :
Sur quelques webservers il y a plus d'un URL pour une ressource. Habituellement
il y a d'URLs canonique (qui devrait être employé réellement
et distribué) et tels qui sont des raccourcis justes, les internes,
l'indépendant etc. que l'URL l'écrit par l'utilisateur avec
la demande il devrait finalement voir le canonique seulement.
Solution :
Nous faisons un HTTP externe réorientons pour que tout l'URLs non-canonique
les fixe dans la vue d'endroit du navigateur et pour toutes les demandes suivantes.
Dans le ruleset d'exemple ci-dessous nous remplaçons/~user par /u/user
canonique et fixons une estafilade de remorquage absente pour /u/user.
RewriteRule ^/~ ([^/] +)/? (. *) /u/ $1/$2 [R] RewriteRule ^/([uge])/([^/] +) $/$1/$2/[R]
Hostnames canonique
Description :
Le but de cette règle est de forcer l'utilisation d'un hostname particulier,
de préférence à d'autres hostnames qui peuvent être
employés pour atteindre le même emplacement. Par exemple, si
vous souhaitez forcer l'utilisation de www.example.com au lieu d'example.com,
vous pourriez employer une variante de la recette suivante.
Solution :
# pour des emplacements fonctionnant sur un port autre que 80 RewriteCond % {HTTP_HOST} ! ^fully \ .qualified \ .domain \ .name [OR] RewriteCond % {HTTP_HOST} ! ^$ RewriteCond % {SERVER_PORT} ! ^80$ RewriteRule ^/(. *) http://fully.qualified.domain.name:% {SERVER_PORT}/$1 [L, R] # et pour un emplacement fonctionnant sur le port 80 RewriteCond % {HTTP_HOST} ! ^fully \ .qualified \ .domain \ .name [OR] RewriteCond % {HTTP_HOST} ! ^$ RewriteRule ^/(. *) http://fully.qualified.domain.name/$1 [L, R]
DocumentRoot déplacé
Description :
Habituellement le DocumentRoot du web server se relie directement au «
d'URL/ ». Mais souvent ces données ne sont pas vraiment de priorité
supérieure, il sont peut-être juste une entité de beaucoup
de bases de données. Par exemple à nos emplacements d'Intranet
il y a /e/www/ (la page d'accueil pour WWW), de /e/sww/ (la page d'accueil
pour l'Intranet) etc. Maintenant parce que les données du DocumentRoot
restent chez /e/www/ nous avons dû nous assurer que tous inlined les
images et toute autre substance à l'intérieur de ce travail
de base de données pour des demandes suivantes.
Solution :
Nous réorientons juste l'URL/à /e/www/. Tandis qu'est semble
insignifiant il est réellement insignifiant avec le mod_rewrite, seulement.
Puisque les vieux mécanismes typiques des noms d'emprunt d'URL (comme
fournit par des mod_alias et des amis) ont seulement employé l'assortiment
de préfixe. Avec ceci vous ne pouvez pas faire une telle redirection
parce que le DocumentRoot est un préfixe de tout l'URLs. Avec le mod_rewrite
il est vraiment insignifiant :
RewriteEngine sur RewriteRule ^/$ /e/www/ [R]
Problème de remorquage d'estafilade
Description :
Chaque webmaster peut chanter une chanson au sujet du problème de l'estafilade
de remorquage sur URLs mettant en référence des annuaires. S'ils
sont absents, le serveur vide une erreur, parce que si vous dites/~quux/foo
au lieu de/~quux/foo/puis le serveur recherche un dossier appelé foo.
Et parce que ce dossier est un annuaire il se plaint. Est en fait les essais
pour le fixer themself dans la plupart des cas, mais parfois ce besoin de
mécanisme d'être émulé par toi. Par exemple après
toi ont fait beaucoup de rewritings compliqués d'URL aux manuscrits
etc. de cgi.
Solution :
La solution à ce problème subtile est a laissé le serveur
ajouter l'estafilade de remorquage automatiquement. Pour faire ceci correctement
nous devons employer un externe réorientons, ainsi le navigateur demande
correctement les images suivantes etc. Si nous faisions seulement une réécriture
interne, ceci fonctionnerait seulement pour la page d'annuaire, mais tournerait
mal quand toutes les images sont incluses dans cette page avec URLs relatif,
parce que le navigateur demanderait un objet dans-rayé. Par exemple,
une demande d'image.gif dans/~quux/foo/index.html deviendrait/~quux/image.gif
sans externe réorientent !
Ainsi, pour faire ce tour que nous écrivons :
RewriteEngine sur RewriteBase/~quux/RewriteRule ^foo$ foo/[R]
Le bidon fou et paresseux font même le suivant dans le dossier supérieur de .htaccess de leur homedir. Mais noter que ceci crée quelques frais généraux de traitement.
RewriteEngine sur RewriteBase/~quux/RewriteCond % {REQUEST_FILENAME} - ^ de d RewriteRule (. + [^/]) $ $1/[R]
Webcluster par la disposition homogène d'URL
Description :
Nous voulons créer une disposition homogène et cohérente
d'URL au-dessus de tous les serveurs de WWW sur un webcluster d'Intranet,
c.-à-d. tout l'URLs (par serveur de définition local et ainsi
personne à charge de serveur !) réellement devenu le serveur
independed ! Ce que nous voulons est de donner au namespace de WWW une disposition
cohérente de serveur-independend : aucun URL si devoir inclure n'importe
quel serveur physiquement correct de cible. Le faisceau lui-même devrait
nous conduire automatiquement au centre serveur physique de cible.
Solution :
D'abord, la connaissance des serveurs de cible viennent (distribué)
des cartes externes qui contiennent l'information où nos utilisateurs,
groupes et entités restent. Le la forme
user1 server_of_user1 user2 server_of_user2 : :
Nous les avons mis dans les dossiers map.xxx-to-host. En second lieu nous devons demander à tous les serveurs pour réorienter URLs des formes
/u/user/anypath /g/group/anypath /e/entity/anypath
à
http://physical-host/u/user/anypath http://physical-host/g/group/anypath http://physical-host/e/entity/anypath
quand l'URL n'est pas localement valide à un serveur. Le ruleset suivant fait ceci pour nous par l'aide des dossiers de carte (supposant que server0 est un serveur de défaut qui sera utilisé si un utilisateur n'a aucune entrée dans la carte) :
RewriteEngine sur le txt d'utilisateur-à-centre serveur de RewriteMap : Txt de groupe-à-centre serveur de /path/to/map.user-to-host RewriteMap : Txt d'entité-à-centre serveur de /path/to/map.group-to-host RewriteMap : /path/to/map.entity-to-host RewriteRule ^/u/([^/] +)/? (. *) http://$ {utilisateur-à-centre serveur : $1|server0} /u/$1/$2 RewriteRule ^/g/([^/] +)/? (. *) http://$ {groupe-à-centre serveur : $1|server0} /g/$1/$2 RewriteRule ^/e/([^/] +)/? (. *) http://$ {entité-à-centre serveur : $1|server0} /e/$1/$2 RewriteRule ^/([uge])/([^/] +)/? $/$1/$2/.www/RewriteRule ^/([uge])/([^/] +)/([^.]+.+)/$1/$2/.www/$3 \
Déplacer Homedirs au web server différent
Description :
Beaucoup de webmaster aksed pour une solution à la situation suivante
: Ils ont voulu réorienter juste tous les homedirs sur un web server
à un autre web server. Ils ont besoin habituellement de telles choses
en établissant un plus nouveau web server qui remplacera le vieux un
temps fini.
Solution :
La solution est insignifiante avec le mod_rewrite. Sur le vieux web server
nous réorientons juste tout le/~user/anypath URLs à http://newserver/~user/anypath.
RewriteEngine sur RewriteRule ^/~ (. +) http://newserver/~$1 [R, L]
Homedirs structuré
Description :
Quelques emplacements avec le thousend des utilisateurs emploient habituellement
une disposition structurée de homedir, c.-à-d. chaque homedir
est dans un sous-répertoire qui commence par exemple par le premier
caractère de l'username. Ainsi,/~foo/anypath est /home/f/foo/.www/anypath
tandis que/~bar/anypath est /home/b/bar/.www/anypath.
Solution :
Nous employons le ruleset suivant pour augmenter le tilde URLs dans exactement
la disposition ci-dessus.
RewriteEngine sur RewriteRule ^/~ (([a-z]) [a-z0-9] +) (. *) /home/ $2/$1/.www$3
Réorganisation de Filesystem
Description :
C'est vraiment un exemple inconditionnel : une application de tueur qui emploie
fortement le par-annuaire RewriteRules pour obtenir un regard sans heurt et
pour se sentir sur le Web tandis que sa structure de données n'est
jamais touchée ou est ajustée. Fond : net.sw est mes archives
des progiciels librement disponibles d'Unix, que j'ai commencé à
rassembler en 1992. C'est mon passe-temps et travail à à ceci,
parce que tandis que j'étudie l'informatique j'ont également
travaillé pendant beaucoup d'années en tant qu'administrateur
de système et de réseau dans mon temps libre. Chaque semaine
j'ai besoin d'une certaine sorte de logiciel ainsi j'ai créé
une hiérarchie profonde des annuaires où j'ai stocké
les paquets :
utilisateurs de netsw du drwxrwxr-x 2 le 3 aoû. 18 512 : 39 utilisateurs audio de netsw du drwxrwxr-x 2 le 9 jui. 14 512 : 37 utilisateurs de netsw du drwxrwxr-x 12 de repère 512 utilisateurs Crypto/de netsw du drwxrwxr-x 5 du 9 jui. 00:34 512 utilisateurs de netsw du drwxrwxr-x 4 de base de données du 9 jui. 00:41 le 30 jui. 19 512 : 25 utilisateurs de netsw du drwxrwxr-x 10 de Dicts/le 9 jui. 01 512 : 54 utilisateurs graphiques de netsw du drwxrwxr-x 5 le 9 jui. 01 512 : 58 utilisateurs de netsw du drwxrwxr-x 8 d'intrus le 9 jui. 03 512 : 19 utilisateurs de netsw du drwxrwxr-x 3 d'InfoSys/le 9 jui. 03 512 : 21 utilisateurs de netsw du drwxrwxr-x 3 de maths le 9 jui. 03 512 : 24 utilisateurs divers de netsw du drwxrwxr-x 9 le 1er aoû. 16 512 : 33 utilisateurs de netsw du drwxrwxr-x 2 de réseau le 9 jui. 05 512 : 53 utilisateurs de netsw du drwxrwxr-x 7 de bureau le 9 jui. 09 512 : 24 utilisateurs de netsw du drwxrwxr-x 7 de SoftEng/le 9 jui. 12 512 : 17 utilisateurs de netsw du drwxrwxr-x 12 de système le 3 aoû. 20 512 : 15 utilisateurs de composition de netsw du drwxrwxr-x 10 le 9 jui. 14 512 : 08 X11/
En juillet 1996 j'ai décidé de faire ce public d'archives
au monde par l'intermédiaire d'une interface gentille de Web. «
Nice » signifie que j'ai voulu offrir une interface où vous pouvez
passer en revue directement par la hiérarchie d'archives. Et les moyens
« gentils » que je pas ont voulu changer n'importe quoi à
l'intérieur de cette hiérarchie - pour pas même en mettant
quelques manuscrits de cgi au dessus de lui. Pourquoi ? Puisque la structure
ci-dessus devrait être plus tard accessible par l'intermédiaire
du ftp aussi bien, et de moi n'a pas voulu que toute substance de Web ou de
cgi fût là.
Solution :
La solution a deux parts : Le premier est un ensemble de manuscrits de cgi
qui créent toutes pages à tous les niveaux d'annuaire en marche.
Je les ai mis sous /e/netsw/.www/ comme suit :
- rw-r--r-- utilisateurs de 1 netsw le 1er aoû. 18 1318 : 10 utilisateurs de netsw du drwxr-xr-x 18 de .wwwacl le 5 aoû. 15 512 : 51 DONNÉES - utilisateurs de netsw du rw-rw-rw- 1 le 5 aoû. 16 372982 : 35 FICHIER JOURNAL - rw-r--r-- utilisateurs de 1 netsw le 4 aoû. 09 659 : 27 TODO - rw-r--r-- utilisateurs de 1 netsw le 1er aoû. 18 5697 : 01 netsw-about.html - utilisateurs de netsw du rwxr-xr-x 1 le 2 aoû. 10 579 : 33 netsw-access.pl - utilisateurs de netsw du rwxr-xr-x 1 le 1er aoû. 17 1532 : 35 netsw-changes.cgi - utilisateurs de netsw du rwxr-xr-x 1 le 5 aoû. 14 2866 : 49 utilisateurs de netsw du drwxr-xr-x 2 de netsw-home.cgi le 8 jui. 23 512 : 47 netsw-img/- utilisateurs de netsw du rwxr-xr-x 1 le 5 aoû. 15 24050 : 49 netsw-lsdir.cgi - utilisateurs de netsw du rwxr-xr-x 1 le 3 aoû. 18 1589 : 43 netsw-search.cgi - utilisateurs de netsw du rwxr-xr-x 1 le 1er aoû. 17 1885 : 41 netsw-tree.cgi - rw-r--r-- utilisateurs de 1 netsw le 30 jui. 16 234 : 35 netsw-unlimit.lst
Le sous-répertoire de DONNÉES tient la structure ci-dessus d'annuaire, c.-à-d. la vraie substance de net.sw et obtient automatiquement mis à jour par l'intermédiaire du rdist de temps en temps. La deuxième partie des restes de problème : comment incorporer ces deux structures ensemble dans un arbre lisse-regardant d'URL ? Nous voulons cacher l'annuaire de DONNÉES de l'utilisateur tout en courant les manuscrits appropriés de cgi pour le divers URLs. Voici la solution : d'abord j'ai mis le suivant dans le dossier de configuration de par-annuaire dans la racine de document du serveur pour récrire l'URL annoncé /net.sw/ au chemin interne /e/netsw :
^ net.sw/(.*)$ e/netsw/$1 de RewriteRule ^net.sw$ net.sw/[R] RewriteRule
La première règle est pour les demandes qui manquent l'estafilade de remorquage ! La deuxième règle fait la vraie chose. Et vient alors la configuration de tueur qui reste dans le dossier /e/netsw/.www/.wwwacl de config de par-annuaire :
Les options ExecCGI FollowSymLinks inclut MultiViews RewriteEngine sur # que nous sommes atteints par l'intermédiaire du préfixe RewriteBase /net.sw/ # de /net.sw/ d'abord nous récrivons le dir de racine à # la bande de manipulation du ^index de RewriteRule ^$ netsw-home.cgi [L] RewriteRule de manuscrit de cgi \ .html$ netsw-home.cgi [L] # dehors les subdirs quand # le navigateur nous demande du perdir pagine RewriteRule ^.+/(netsw- [^/] +/.+) $ $1 [L] # et cassons maintenant la réécriture pour des gens du pays classe la ^netsw-maison de RewriteRule \ .cgi.* - [L] ^netsw-change de RewriteRule \ .cgi.* - [L] ^netsw-recherche de RewriteRule \ .cgi.* - [L] le ^netsw-arbre de RewriteRule \ .cgi$ - [L] ^netsw-au sujet de de RewriteRule \ .html$ - [L] RewriteRule ^netsw-img/.*$ - [L] # toute autre chose est un subdir qui obtient # manipulé par un autre manuscrit RewriteRule de cgi ! ^netsw-lsdir \ .cgi.* - [C] RewriteRule (. *) netsw-lsdir.cgi/$1
Quelques conseils pour l'interprétation :
1. Noter le L (dernier) drapeau et aucun champ de substitution («
- ») dans en avant la partie
2. Noter ! (pas) caractère et le drapeau (à chaînes) de
C à la première règle dans la dernière partie
3. Noter l'attraper-tout modèle dans la dernière règle
Imagemap de NCSA au mod_imap d'Apache
Description :
En commutant du web server de NCSA à un bon nombre de web server d'Apache
de gens plus moderne vouloir une transition douce. Ainsi ils veulent les pages
qui emploient leur vieux programme d'imagemap de NCSA pour fonctionner sous
Apache avec le mod_imap moderne. Le problème est qu'il y a beaucoup
d'hyperliens autour de quelle référence le programme d'imagemap
par l'intermédiaire de /cgi-bin/imagemap/path/to/page.map. Sous Apache
ceci doit lire /path/to/page.map juste.
Solution :
Nous employons une règle globale pour enlever le préfixe en
marche pour toutes les demandes :
RewriteEngine sur RewriteRule ^/cgi-bin/imagemap (. *) $1 [PINTE]
Pages de recherche dans plus d'un annuaire
Description :
Parfois elle est neccessary a laissé le web server rechercher des pages
dans plus d'un annuaire. Ici MultiViews ou d'autres techniques ne peut pas
aider.
Solution :
Nous programmons un ruleset explicite qui recherche les dossiers dans les
annuaires.
RewriteEngine sur # essayent d'abord de le trouver dans la coutume… #… et si l'arrêt trouvé et soit heureux : RewriteCond /your/docroot/dir1/ % {REQUEST_FILENAME} - ^ de f RewriteRule (. +) essai de /your/docroot/dir1/ $1 [L] # en second lieu pour le trouver en publication… #… et si l'arrêt trouvé et soit heureux : RewriteCond /your/docroot/dir2/ % {REQUEST_FILENAME} - ^ de f RewriteRule (. +) /your/docroot/dir2/ $1 [L] # continuent autrement pour d'autres directives de nom d'emprunt ou de ScriptAlias, ^ de # etc. RewriteRule (. +) - [PINTE]
Placer les variables d'environnement selon des pièces d'URL
Description :
Peut-être vous voulez garder l'information de statut entre les demandes
et employer l'URL pour le coder. Mais vous ne voulez pas employer un emballage
de cgi pour toutes les pages juste pour dépouiller dehors cette information.
Solution :
Nous employons une règle de réécriture pour dépouiller
dehors l'information de statut et pour nous rappeler la par l'intermédiaire
d'une variable d'environnement qui peut plus tard être déréférenciée
de dans XSSI ou cgi. De cette façon qu'un URL /foo/S =java/bar/obtient
traduit à /foo/bar/ et la variable d'environnement appelée STATUS
est placée à la valeur « Java ».
RewriteEngine sur le ^ de RewriteRule (. *) /S= ([^/] +)/(. *) $1/$3 [E=STATUS : $2]
Centres serveurs virtuels d'utilisateur
Description :
Supposer que vous voulez ne fournir www.username.host.domain.com pour la page
d'accueil de l'username par l'intermédiaire des disques justes de DNS
A à la même machine et sans aucun virtualhosts sur cette machine.
Solution :
Pour les demandes HTTP/1.0 il n'y a aucune solution, mais pour les demandes
HTTP/1.1 qui contiennent un centre serveur : En-tête de HTTP nous pouvons
employer le ruleset suivant pour récrire http://www.username.host.com/anypath
intérieurement à /home/username/anypath :
RewriteEngine sur % de ^www de RewriteCond {HTTP_HOST} \. [^.]+ \ ^ de .host \ .com$ RewriteRule (. +) % {HTTP_HOST} $1 [C] ^www de RewriteRule \. ([^.]+) \ .host \ .com (. *) /home/ $1$2
Réorienter Homedirs pour des Étrangers
Description :
Nous voulons réorienter le homedir URLs à un autre web server
www.somewhere.com quand l'utilisateur de demande ne reste pas dans le domaine
local ourdomain.com. Ceci est parfois employé dans des contextes virtuels
de centre serveur.
Solution :
Juste un état de réécriture :
RewriteEngine sur RewriteCond % {REMOTE_HOST} ! ^ de ^.+ \ .ourdomain \ .com$ RewriteRule (/~.+) http://www.somewhere.com/$1 [R, L]
Réorienter URLs échouant à l'autre web server
Description :
Un FAQ typique au sujet de l'URL récrivant est comment réorienter
des demandes échouantes sur le web server A au web server B. Habituellement
ceci est fait par l'intermédiaire des Cgi-manuscrits d'ErrorDocument
dans le Perl, mais il y a également une solution de mod_rewrite. Mais
noter que c'est moins performant qu'en utilisant un Cgi-manuscrit d'ErrorDocument
!
Solution :
La première solution a la meilleure exécution mais moins de
flexibilité et est moins de coffre-fort d'erreurs :
RewriteEngine sur RewriteCond /your/docroot/ % {REQUEST_FILENAME} ! - ^ de f RewriteRule (. +) http://webserverB.dom/$1
Le problème ici est que ceci fonctionnera seulement pour des pages à l'intérieur du DocumentRoot. Tandis que vous pouvez ajouter plus de conditions (par exemple à aussi manipuler les homedirs, etc.) là est une meilleure variante :
RewriteEngine sur RewriteCond % {REQUEST_URI} ! - ^ d'U RewriteRule (. +) http://webserverB.dom/$1
Ceci emploie l'URL regardent-en avant le dispositif du mod_rewrite. Le résultat est que ceci fonctionnera pour tous les types d'URLs et est une manière sûre. Mais il fait un impact d'exécution sur le web server, parce que pour chaque demande il y a un subrequest plus interne. Ainsi, si votre web server fonctionne sur une unité centrale de traitement puissante, employer celui-ci. Si c'est une machine lente, employer la première approche ou améliorer un Cgi-manuscrit d'ErrorDocument.
Redirection prolongée
Description :
Parfois nous avons besoin de plus de commande (au sujet du mécanisme
s'échappant de caractère) d'URLs réoriente dessus. Habituellement
la fonction d'évasion d'URL de grains d'Apache échappe également
aux ancres, c.-à-d. URLs comme le « url#anchor ». Vous
ne pouvez pas employer ceci directement sur réoriente avec le mod_rewrite
parce que la fonction d'uri_escape () d'Apache échapperait également
au caractère d'informations parasites. Comment pouvons-nous réorienter
à un tel URL ?
Solution :
Nous devons employer un kludge par l'utilisation d'un manuscrit de NPH-CGI
qui fait la réorientation elle-même. Puisqu'ici aucun s'échapper
n'est fait (des en-têtes de NPH=non-parseable). D'abord nous présentons
un nouveau xredirect d'arrangement d'URL : par la config-ligne suivante de
par-serveur (devrait être une des dernières règles de
réécriture) :
^xredirect de RewriteRule : (. +) /path/to/nph-xredirect.cgi/ $1 \ [T=application/x-httpd-cgi, L]
Ceci force tout l'URLs mis en tête avec le xredirect : être sifflé par le programme de nph-xredirect.cgi. Et ce programme regarde juste le goût :
# ! ## nph-xredirect.cgi de ## de /path/to/perl -- Le manuscrit de NPH/CGI pour prolongé réoriente copyright de ## (c) Ralf 1997 S. Engelschall, tous droits réservés. ## $| = 1 ; $url = $ENV {« PATH_INFO »} ; imprimer « HTTP/1.0 302 temporairement déplacé \ n » ; serveur d'impression « : $ENV {« SERVER_SOFTWARE »} \ n » ; endroit d'impression « : $url \ n » ; Contenu-type d'impression « : texte/HTML \ n » ; » d'impression \ n " ; copie « <html> \ n » ; copie « <head> \ n » ; copie « </title> (PROLONGÉ) temporairement déplacé par <title>302 \ n » ; copie « </head> \ n » ; copie « <body> \ n » ; copie « <h1>Moved temporairement </h1> (PROLONGÉ) \ n » ; imprimer « le document a déplacé le <a HREF= \ « $url \ « >here</a>.<p> \ n » ; imprimer « </body> \ n » ; imprimer « </html> \ n » ; ##EOF##
Ceci te fournit la fonctionnalité pour faire réoriente à tous les arrangements d'URL, c.-à-d. comprenant celui qui ne sont pas directement acceptés par le mod_rewrite. Par exemple vous pouvez maintenant également réorienter à news:newsgroup par l'intermédiaire de
Xredirect de ^anyurl de RewriteRule : news:newsgroup
Notification : Vous avez pour ne pas mettre [R] ou [R, L] à la règle ci-dessus parce que le xredirect : devoir être augmenté plus tard par notre « pipe spéciale par » la règle ci-dessus.
Archiver le multiplexeur d'Access
Description :
Savez-vous le grand CPAN (réseau complet d'archives de Perl) sous http://www.perl.com/CPAN
? Ceci fait une réorientation à un de plusieurs serveurs de
ftp autour du monde qui portent un miroir de CPAN et est approximativement
près de l'endroit du client de demande. En fait ceci peut s'appeler
un service de multiplexage d'accès de ftp. Tandis que CPAN fonctionne
par l'intermédiaire des manuscrits de cgi, comment ose-t-elle une approche
semblable mise en application par l'intermédiaire du mod_rewrite ?
Solution :
D'abord nous notons que de la version 3.0.0 le mod_rewrite peut également
employer le « ftp : le » arrangement réoriente dessus.
Et en second lieu, l'approximation d'endroit peut être faite par un
rewritemap au-dessus du domaine supérieur du client. Avec un ruleset
enchaîné rusé nous pouvons employer ce domaine supérieur
comme clef à notre carte de multiplexage.
RewriteEngine sur le txt multiplex de RewriteMap : /path/to/map.cxan RewriteRule ^/CxAN/(. *) % {REMOTE_HOST} : : $1 [C] RewriteRule ^.+ \. ([a-zA-Z] +) : : (. *) $ $ {multiplex : $1|FTP.DEFAULT.DOM} $2 [R, L]
## map.cxan de ## -- Carte de multiplexage pour COM britannique ftp://ftp.cxan.com/CxAN/ de CxAN ## de ftp://ftp.cxan.de/CxAN/ ftp://ftp.cxan.uk/CxAN/ : ##EOF##
Réécriture de Temps-Dependend
Description :
Quand les tours comme le contenu de temps-dependend devraient encore se produire
beaucoup de webmasters employer les manuscrits de cgi qui par exemple réorientent
aux pages spécialisées. Comment peut-il être fait par
l'intermédiaire du mod_rewrite ?
Solution :
Il y a beaucoup de variables appelées TIME_xxx pour des états
de réécriture. En même temps que le <STRING lexicographique
spécial de modèles de comparaison, le >STRING et le =STRING
que nous pouvons faire le temps-dependend réoriente :
RewriteEngine sur % {TIME_HOUR} de % {TIME_MIN} >0700 RewriteCond de % {TIME_HOUR} de % {TIME_MIN} <1900 RewriteRule du ^foo du ^foo de RewriteCond \ .html$ foo.day.html RewriteRule \ .html$ foo.night.html
Ceci fournit la teneur de foo.day.html sous l'URL foo.html de 07:00 - 19 : 00 et au temps restant les teneurs de foo.night.html. Juste un dispositif gentil pour une page d'accueil…
Compatibilité en arrière pour YYYY à la migration
Description :
Comment pouvons-nous rendre URLs en arrière - compatible (existant
toujours pratiquement) après migration document.YYYY à, par
exemple après la traduction d'un groupe de dossiers de .html à
.phtml ?
Solution :
Nous juste récrivons le nom à son basename et déterminons
l'existence de la nouvelle prolongation. Si elle existe, nous prenons ce nommé,
d'autre nous récrivons l'URL à son état original.
le ruleset de compatibilité en arrière de # pour # récrivant document.html à document.phtml # quand et seulement quand document.phtml existe # mais plus document.html RewriteEngine sur RewriteBase/~quux/# analyser dehors le basename, mais se rappellent le ^ de RewriteRule de fait (. *) \ .html$ $1 [C, E=WasHTML : oui] réécriture de # à document.phtml si existe % de RewriteCond {REQUEST_FILENAME} .phtml - ^ de f RewriteRule (. *) inverse de $ $1.phtml [S=1] # autrement le coupe-circuit précédent RewriteCond % {ENV de basename : ^ de WasHTML} ^yes$ RewriteRule (. *) $ $1.html
Manipulation contente
De vieux à nouveau (interne)
Description :
Supposer que nous avons récemment retitré la page foo.html à
bar.html et voulons maintenant fournir le vieil URL pour la compatibilité
en arrière. En fait nous voulons que des utilisateurs du vieil URL
même ne pas identifier que les pages ont été retitrées.
Solution :
Nous récrivons le vieil URL au neuf intérieurement par l'intermédiaire
de la règle suivante :
RewriteEngine sur le ^foo de RewriteBase/~quux/RewriteRule \ .html$ bar.html
De vieux à nouveau (externe)
Description :
Supposer encore que nous avons récemment retitré la page foo.html
à bar.html et vouloir maintenant fournir le vieil URL pour la compatibilité
en arrière. Mais cette fois nous voulons que les utilisateurs du vieil
URL obtiennent laissés entendre au neuf, c.-à-d. leur champ
d'endroit de navigateurs devrait changer, aussi.
Solution :
Nous forçons un HTTP réorientons au nouvel URL qui mène
à un changement des navigateurs et ainsi de la vue d'utilisateurs :
RewriteEngine sur le ^foo de RewriteBase/~quux/RewriteRule \ .html$ bar.html [R]
Contenu de Dependend de navigateur
Description :
Au moins pour les pages supérieures importantes elle est parfois necesarry
pour fournir l'optimum du contenu de dependend de navigateur, c.-à-d.
on doit fournir une version maximum pour les dernières variantes de
Netscape, une version minimum pour les navigateurs de Lynx et une version
moyenne de dispositif pour tous les autres.
Solution :
Nous ne pouvons pas employer la négociation contente parce que les
navigateurs ne fournissent pas le leur saisissent cette forme. Au lieu de
cela nous devons agir sur l'en-tête « Utilisateur-Agent »
de HTTP. Le condig suivant fait ce qui suit : Si l'en-tête « Utilisateur-Agent
» de HTTP commence par « Mozilla/3 », la page foo.html est
récrite à foo.NS.html et et aux arrêts de réécriture.
Si le navigateur est « Lynx » ou « Mozilla » de la
version 1 ou 2 l'URL devient foo.20.html. Tous autres navigateurs reçoivent
la page foo.32.html. Ceci est fait par le ruleset suivant :
% {HTTP_USER_AGENT} ^Mozilla/3.* RewriteRule de % de % du ^foo de RewriteCond \ .html$ foo.NS.html [L] RewriteCond {HTTP_USER_AGENT} ^Lynx/.* [OU] RewriteCond {HTTP_USER_AGENT} ^Mozilla/[12]. * ^foo du ^foo de RewriteRule \ .html$ foo.20.html [L] RewriteRule \ .html$ foo.32.html [L]
Miroir dynamique
Description :
Supposer qu'il y a des pages Web gentilles sur les centres serveurs à
distance que nous voulons introduire dans notre namespace. Pour des serveurs
de ftp nous emploierions le programme de miroir qui maintient réellement
une copie à jour explicite des données à distance sur
la machine locale. Pour un web server nous pourrions employer le programme
webcopy qui agit semblable par l'intermédiaire du HTTP. Mais les deux
techniques ont un inconvénient principal : La copie locale est toujours
comme à jour juste que souvent nous exécutons le programme.
Il serait bien mieux si le miroir n'est pas statique que nous devons établir
explicitement. Au lieu de cela nous voulons un miroir dynamique avec les données
qui obtiennent mises à jour automatiquement quand il y a le besoin
(données mises à jour sur le centre serveur à distance).
Solution :
Pour fournir ce dispositif nous traçons la page Web à distance
ou même le webarea à distance complet à notre namespace
par l'utilisation du dispositif de sortie de procuration (drapeau [P]) :
RewriteEngine sur RewriteBase/~quux/RewriteRule ^hotsheet/(. *) $ http://www.tstimpreso.com/hotsheet/$1 [P]
RewriteEngine sur les ^usa-nouvelles de RewriteBase/~quux/RewriteRule \ .html$ http://www.quux-corp.com/news/index.html [P]
Miroir dynamique renversé
Description :
…
Solution :
RewriteEngine sur RewriteCond /mirror/of/remotesite/ $1 - ^ http://www \ .remotesite \ .com/ d'U RewriteRule (. *) $ /mirror/of/remotesite/ $1
Rechercher les données absentes de l'Intranet
Description :
C'est une manière rusée de courir pratiquement un web server
(externe) d'Internet de corporates (www.quux-corp.do m), tout en réellement
gardant et maintenant ses données sur le web server (interne) d'Intranet
d'a (www2.quux-corp.dom) qui est protégé par un mur à
l'épreuve du feu. Le tour est celui sur le web server externe que nous
recherchons les données priées en marche de les internes.
Solution :
D'abord, nous devons nous assurer que notre mur à l'épreuve
du feu protège toujours le web server interne et que seulement le web
server externe est permis de rechercher des données de lui. Pour un
mur à l'épreuve du feu de paquet-filtrage nous pourrions par
exemple configurer un ruleset de mur à l'épreuve du feu comme
ce qui suit :
PERMETTRE le centre serveur www.quux-corp.do m >1024 gauche --> le port 80 du centre serveur www2.quux-corp.dom NIENT le centre serveur * port * --> port 80 du centre serveur www2.quux-corp.dom
L'ajuster juste sur votre syntaxe réelle de configuration. Maintenant nous pouvons établir les règles de mod_rewrite qui demandent les données absentes dans le fond par le dispositif de sortie de procuration :
RewriteRule ^/~ ([^/] +)/? (. *) /home/ $1/.www/$2 RewriteCond % {REQUEST_FILENAME} ! - f RewriteCond % {REQUEST_FILENAME} ! - d RewriteRule ^/home/([^/] +) /.www/ ? (. *) http://www2.quux-corp.dom/~$1/pub/$2 [P]
Équilibrage de charge
Description :
Supposer que nous voulons charger l'équilibre le trafic à www.foo.com
au-dessus de WWW [0-5] .foo.com (un total de 6 serveurs). Comment est-ce que
ceci peut être fait ?
Solution :
Il y a beaucoup de solutions possibles pour ce problème. Nous discuterons
d'abord une variante DNS-basée généralement connue et
puis la spéciale avec le mod_rewrite :
1. Rond-Merle de DNS
La méthode la plus simple pour charge-équilibrer est d'employer le dispositif de rond-merle de DNS du GRIPPAGE. Voici que vous configurez juste WWW [0-9] .foo.com comme d'habitude dans votre DNS avec des disques d'A (adresse), par exemple.
www0 DANS A 1.2.3.1 www1 DANS A 1.2.3.2 www2 DANS A 1.2.3.3 www3 DANS A 1.2.3.4 www4 DANS A 1.2.3.5 www5 DANS A 1.2.3.6
Alors vous ajoutez en plus l'entrée suivante :
WWW DANS CNAME www0.foo.com. DANS CNAME www1.foo.com. DANS CNAME www2.foo.com. DANS CNAME www3.foo.com. DANS CNAME www4.foo.com. DANS CNAME www5.foo.com. DANS CNAME www6.foo.com.
Noter que ceci semble erroné, mais est réellement un dispositif
prévu de GRIPPAGE et peut être employé de cette façon.
Cependant, maintenant quand www.foo.com obtient résolu, le GRIPPAGE
donne dehors www0-www6 - mais dans a permutated légèrement/ordre
tourné chaque fois. De cette façon les clients sont réparties
les divers serveurs. Mais noter que ceci pas un arrangement de équilibrage
de charge parfaite, parce que l'information de résolution de DNS obtient
cachée par les autres nameservers sur le filet, ainsi une fois qu'un
client a résolu www.foo.com à wwwN.foo.com particulier, toutes
les demandes suivantes vont également à ce nom wwwN.foo.com
de détail. Mais le résultat final est correct, parce que toute
la somme des demandes sont vraiment réparties les divers webservers.
2. Charge-Équilibrage de DNS
Une méthode DNS-basée sophistiquée pour charge-équilibrer
est d'employer le programme lbnamed qui peut être trouvé chez
http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html. C'est un programme
de Perl 5 en même temps que les outils auxiliaires qui fournit un vrai
charge-équilibrage pour le DNS.
3. Rond-Merle de sortie de procuration
Dans cette variante nous employons le mod_rewrite et son dispositif de sortie de procuration. D'abord nous consacrons www0.foo.com pour être réellement www.foo.com en employant un simple
WWW DANS CNAME www0.foo.com.
entrée dans le DNS. Alors nous convertissons www0.foo.com en serveur de procuration-seulement, c.-à-d. nous configurons cette machine ainsi tout l'URLs de arrivée sont juste poussés par la procuration interne à un des 5 autres serveurs (www1-www5). Pour accomplir ceci nous établissons d'abord un ruleset qui entre en contact avec un manuscrit de équilibrage lb.pl de charge pour tout l'URLs.
RewriteEngine sur le prg de RewriteMap livre : /path/to/lb.pl RewriteRule ^/(. +) $ $ {livre : $1} [P, L]
Alors nous écrivons lb.pl :
# ! ## lb.pl de ## de /path/to/perl -- ## de équilibrage de manuscrit de charge $| = 1 ; $name = « WWW » ; # le hostname bas $first = 1 ; # le premier serveur (non 0 ici, parce que 0 est moi-même) $last = 5 ; # le dernier serveur dans le rond-merle $domain = « foo.dom » ; # le Domain Name $cnt = 0 ; tandis que (<STDIN>) {$cnt = (($cnt+1) % ($last+1-$first)); $server = sprintf (« %s%d.%s », $name, $cnt+$first, $domain) ; copie « http://$server/$_ » ; } ##EOF##
Une dernière notification : Pourquoi est-ce que c'est utile ? Semble
comme www0.foo.com est surchargé toujours ? La réponse est oui,
elle est surchargée, mais avec des demandes plates de sortie de procuration,
seulement ! Tout le SSI, cgi, ePerl, traitement etc. est complètement
fait sur les autres machines. C'est le point essentiel.
4. Rond-Merle de Hardware/TCP
Il y a une solution de matériel disponible, aussi. Cisco a une bête appelée LocalDirector qui fait une charge équilibrant au niveau de TCP/IP. En fait c'est une certaine sorte d'un passage de niveau de circuit devant un webcluster. Si vous avez assez d'argent et avez besoin vraiment d'une solution avec le rendement élevé, employer celui-ci.
Nouveau Pantomime-type, nouveau service
Description :
Sur le filet il y a beaucoup de programmes astucieux de cgi. Mais leur utilisation
ennuyeux habituellement, ainsi beaucoup de webmaster ne les emploient pas.
Même le dispositif de traiteur de l'action d'Apache pour des Pantomime-types
est seulement approprié quand les programmes de cgi n'ont pas besoin
d'URLs spécial (réellement PATH_INFO et QUERY_STRINGS) en tant
que leur entrée. D'abord, nous laisser configurent un nouveau type
de dossier avec la prolongation .scgi (pour le cgi bloqué) qui sera
traitée par le programme populaire de cgiwrap. Le problème ici
est que par exemple nous employons une disposition homogène d'URL (voir
ci-dessus) un dossier à l'intérieur de l'utilisateur que les
homedirs a l'URL /u/user/foo/bar.scgi. Mais le cgiwrap a besoin de l'URL sous
la forme/~user/foo/bar.scgi/. La règle suivante résout le problème
:
RewriteRule ^/[] d'uge/([^/] +)/\ .www/ (. +) \ .scgi (. *)…… /internal/cgi/user/cgiwrap/ ~$1/$2.scgi$3 [NS, T=application/x-http-cgi]
Ou supposer que nous avons encore plus de programmes astucieux : wwwlog (qui montre access.log pour un sous-arbre d'URL et un wwwidx (qui court l'aperçu sur un sous-arbre d'URL). Nous devons fournir la région d'URL à ces programmes ainsi ils savent sur sur quel secteur ils doivent agir. Mais habituellement ce laid, parce qu'ils sont tous temps toujours demandés de celui des secteurs, c.-à-d. typiquement nous exécuterions le programme de swwidx de dans /u/user/foo/ par l'intermédiaire de l'hyperlien à
/internal/cgi/user/swwidx ? i=/u/user/foo/
ce qui est laid. Puisque nous devons dur-code l'endroit du secteur et l'endroit
du cgi à l'intérieur de l'hyperlien. Quand nous devons réorganiser
ou secteur, nous dépensons changer beaucoup de temps les divers hyperliens.
Solution :
La solution ici est de fournir un nouveau format spécial d'URL qui
mène automatiquement à l'invocation appropriée de cgi.
Nous configurons ce qui suit :
RewriteRule ^/([uge])/([^/] +) (/?. *)/\ * /internal/cgi/user/wwwidx ? i=/$1/$2$3/RewriteRule ^/([uge])/([^/] +) (/?. *) : notation /internal/cgi/user/wwwlog ? f=/$1/$2$3
Maintenant l'hyperlien à rechercher chez /u/user/foo/ lit seulement
HREF= " * "
à ce qu'intérieurement obtient automatiquement transformé
/internal/cgi/user/wwwidx ? i=/u/user/foo/
La même approche mène à une invocation pour le programme de cgi de notation d'accès quand l'hyperlien : la notation obtient utilisée.
De statique à dynamique
Description :
Comment pouvons nous transformer une page foo.html de charge statique en variante
dynamique foo.cgi d'une manière sans couture, c.-à-d. sans communication
préalable par le navigateur/utilisateur.
Solution :
Nous juste récrivons l'URL au Cgi-manuscrit et forçons le Pantomime-type
correct ainsi il obtient vraiment la course comme Cgi-manuscrit. De cette
façon qu'une demande à/~quux/foo.html intérieurement
mène à l'invokation de/~quux/foo.cgi.
RewriteEngine sur le ^foo de RewriteBase/~quux/RewriteRule \ .html$ foo.cgi [T=application/x-httpd-cgi]
Contenu-Régénération en marche
Description :
Voici venir un dispositif vraiment ésotérique : Des pages dynamiquement
produites mais statiquement servies, c.-à-d. pages devraient être
livrées en tant que pages statiques pures (lu du filesystem et juste
passé à travers), mais elles doivent être produites dynamiquement
par le web server si manquant. De cette façon vous pouvez Cgi-avoir
produit des pages qui sont statiquement servies à moins qu'on (ou un
cronjob) enlève le contenu statique. Alors le contenu obtient régénéré.
Solution :
Ceci est fait par l'intermédiaire du ruleset suivant :
RewriteCond % {REQUEST_FILENAME} ! - ^page de s RewriteRule \ .html$ page.cgi [T=application/x-httpd-cgi, L]
Ici une demande à page.html mène à une course interne d'un page.cgi correspondant si page.html manque toujours ou a filesize la nulle. Le tour ici est que page.cgi est un manuscrit habituel de cgi que (en plus à son STDOUT) écrit à son rendement au dossier page.html. Une fois qu'il était couru, le serveur envoie les données de page.html. Quand le webmaster veut forcer une régénération le contenu, il enlève juste page.html (habituellement fait par un cronjob).
Document With Autorefresh
Description:
Wouldn't it be nice while creating a complex webpage if the webbrowser would
automatically refresh the page every time we write a new version from within
our editor? Impossible?
Solution:
No! We just combine the MIME multipart feature, the webserver NPH feature
and the URL manipulation power of mod_rewrite. First, we establish a new URL
feature: Adding just :refresh to any URL causes this to be refreshed every
time it gets updated on the filesystem.
RewriteRule ^(/[uge]/[^/]+/?.*):refresh /internal/cgi/apache/nph-refresh?f=$1
Now when we reference the URL
/u/foo/bar/page.html:refresh
this leads to the internal invocation of the URL
/internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
The only missing part is the NPH-CGI script. Although one would usually say "left as an exercise to the reader" ;-) I will provide this, too.
#!/sw/bin/perl
##
## nph-refresh -- NPH/CGI script for auto refreshing pages
## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
##
$| = 1;
# split the QUERY_STRING variable
@pairs = split(/&/, $ENV{'QUERY_STRING'});
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$name =~ tr/A-Z/a-z/;
$name = 'QS_' . $name;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
eval "\$$name = \"$value\"";
}
$QS_s = 1 if ($QS_s eq '');
$QS_n = 3600 if ($QS_n eq '');
if ($QS_f eq '') {
print "HTTP/1.0 200 OK\n";
print "Content-type: text/html\n\n";
print "<b>ERROR</b>: No file given\n";
exit(0);
}
if (! -f $QS_f) {
print "HTTP/1.0 200 OK\n";
print "Content-type: text/html\n\n";
print "<b>ERROR</b>: File $QS_f not found\n";
exit(0);
}
sub print_http_headers_multipart_begin {
print "HTTP/1.0 200 OK\n";
$bound = "ThisRandomString12345";
print "Content-type: multipart/x-mixed-replace;boundary=$bound\n";
&print_http_headers_multipart_next;
}
sub print_http_headers_multipart_next {
print "\n--$bound\n";
}
sub print_http_headers_multipart_end {
print "\n--$bound--\n";
}
sub displayhtml {
local($buffer) = @_;
$len = length($buffer);
print "Content-type: text/html\n";
print "Content-length: $len\n\n";
print $buffer;
}
sub readfile {
local($file) = @_;
local(*FP, $size, $buffer, $bytes);
($x, $x, $x, $x, $x, $x, $x, $size) = stat($file);
$size = sprintf("%d", $size);
open(FP, "<$file");
$bytes = sysread(FP, $buffer, $size);
close(FP);
return $buffer;
}
$buffer = &readfile($QS_f);
&print_http_headers_multipart_begin;
&displayhtml($buffer);
sub mystat {
local($file) = $_[0];
local($time);
($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file);
return $mtime;
}
$mtimeL = &mystat($QS_f);
$mtime = $mtime;
for ($n = 0; $n < $QS_n; $n++) {
while (1) {
$mtime = &mystat($QS_f);
if ($mtime ne $mtimeL) {
$mtimeL = $mtime;
sleep(2);
$buffer = &readfile($QS_f);
&print_http_headers_multipart_next;
&displayhtml($buffer);
sleep(5);
$mtimeL = &mystat($QS_f);
last;
}
sleep($QS_s);
}
}
&print_http_headers_multipart_end;
exit(0);
##EOF##
Mass Virtual Hosting
Description:
The <VirtualHost> feature of Apache is nice and works great when you
just have a few dozens virtual hosts. But when you are an ISP and have hundreds
of virtual hosts to provide this feature is not the best choice.
Solution:
To provide this feature we map the remote webpage or even the complete remote
webarea to our namespace by the use of the Proxy Throughput feature (flag
[P]):
##
## vhost.map
##
www.vhost1.dom:80 /path/to/docroot/vhost1
www.vhost2.dom:80 /path/to/docroot/vhost2
:
www.vhostN.dom:80 /path/to/docroot/vhostN
##
## httpd.conf
##
:
# use the canonical hostname on redirects, etc.
UseCanonicalName on
:
# add the virtual host in front of the CLF-format
CustomLog /path/to/access_log "%{VHOST}e %h %l %u %t \"%r\"
%>s %b"
:
# enable the rewriting engine in the main server
RewriteEngine on
# define two maps: one for fixing the URL and one which defines
# the available virtual hosts with their corresponding
# DocumentRoot.
RewriteMap lowercase int:tolower
RewriteMap vhost txt:/path/to/vhost.map
# Now do the actual virtual host mapping
# via a huge and complicated single rule:
#
# 1. make sure we don't map for common locations
RewriteCond %{REQUEST_URI} !^/commonurl1/.*
RewriteCond %{REQUEST_URI} !^/commonurl2/.*
:
RewriteCond %{REQUEST_URI} !^/commonurlN/.*
#
# 2. make sure we have a Host header, because
# currently our approach only supports
# virtual hosting through this header
RewriteCond %{HTTP_HOST} !^$
#
# 3. lowercase the hostname
RewriteCond ${lowercase:%{HTTP_HOST}|NONE} ^(.+)$
#
# 4. lookup this hostname in vhost.map and
# remember it only when it is a path
# (and not "NONE" from above)
RewriteCond ${vhost:%1} ^(/.*)$
#
# 5. finally we can map the URL to its docroot location
# and remember the virtual host for logging puposes
RewriteRule ^/(.*)$ %1/$1 [E=VHOST:${lowercase:%{HTTP_HOST}}]
:
Access Restriction
Blocking of Robots
Description:
How can we block a really annoying robot from retrieving pages of a specific
webarea? A /robots.txt file containing entries of the "Robot Exclusion
Protocol" is typically not enough to get rid of such a robot.
Solution:
We use a ruleset which forbids the URLs of the webarea /~quux/foo/arc/ (perhaps
a very deep directory indexed area where the robot traversal would create
big server load). We have to make sure that we forbid access only to the particular
robot, i.e. just forbidding the host where the robot runs is not enough. This
would block users from this host, too. We accomplish this by also matching
the User-Agent HTTP header information.
RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.*
RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.[8-9]$
RewriteRule ^/~quux/foo/arc/.+ - [F]
Blocked Inline-Images
Description:
Assume we have under http://www.quux-corp.de/~quux/ some pages with inlined
GIF graphics. These graphics are nice, so others directly incorporate them
via hyperlinks to their pages. We don't like this practice because it adds
useless traffic to our server.
Solution:
While we cannot 100% protect the images from inclusion, we can at least restrict
the cases where the browser sends a HTTP Referer header.
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
RewriteRule .*\.gif$ - [F]
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$
RewriteRule ^inlined-in-foo\.gif$ - [F]
Host Deny
Description:
How can we forbid a list of externally configured hosts from using our server?
Solution:
For Apache >= 1.3b6:
RewriteEngine on
RewriteMap hosts-deny txt:/path/to/hosts.deny
RewriteCond ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR]
RewriteCond ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND
RewriteRule ^/.* - [F]
For Apache <= 1.3b6:
RewriteEngine on
RewriteMap hosts-deny txt:/path/to/hosts.deny
RewriteRule ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1
RewriteRule !^NOT-FOUND/.* - [F]
RewriteRule ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1
RewriteRule !^NOT-FOUND/.* - [F]
RewriteRule ^NOT-FOUND/(.*)$ /$1
##
## hosts.deny
##
## ATTENTION! This is a map, not a list, even when we treat it as such.
## mod_rewrite parses it for key/value pairs, so at least a
## dummy value "-" must be present for each entry.
##
193.102.180.41 -
bsdti1.sdm.de -
192.76.162.40 -
URL-Restricted Proxy
Description:
How can we restrict the proxy to allow access to a configurable set of internet
sites only? The site list is extracted from a prepared bookmarks file.
Solution:
We first have to make sure mod_rewrite is below(!) mod_proxy in the Configuration
file when compiling the Apache webserver (or in the AddModule list of httpd.conf
in the case of dynamically loaded modules), as it must get called _before_
mod_proxy.
For simplicity, we generate the site list as a textfile map (but see the mod_rewrite documentation for a conversion script to DBM format). A typical Netscape bookmarks file can be converted to a list of sites with a shell script like this:
#!/bin/sh
cat ${1:-~/.netscape/bookmarks.html} |
tr -d '\015' | tr '[A-Z]' '[a-z]' | grep href=\" |
sed -e '/href="file:/d;' -e '/href="news:/d;' \
-e 's|^.*href="[^:]*://\([^:/"]*\).*$|\1 OK|;' \
-e '/href="/s|^.*href="\([^:/"]*\).*$|\1 OK|;' |
sort -u
We redirect the resulting output into a text file called goodsites.txt. It now looks similar to this:
www.apache.org OK
xml.apache.org OK
jakarta.apache.org OK
perl.apache.org OK
...
We reference this site file within the configuration for the VirtualHost which is responsible for serving as a proxy (often not port 80, but 81, 8080 or 8008).
<VirtualHost *:8008>
...
RewriteEngine On
# Either use the (plaintext) allow list from goodsites.txt
RewriteMap ProxyAllow txt:/usr/local/apache/conf/goodsites.txt
# Or, for faster access, convert it to a DBM database:
#RewriteMap ProxyAllow dbm:/usr/local/apache/conf/goodsites
# Match lowercased hostnames
RewriteMap lowercase int:tolower
# Here we go:
# 1) first lowercase the site name and strip off a :port suffix
RewriteCond ${lowercase:%{HTTP_HOST}} ^([^:]*).*$
# 2) next look it up in the map file.
# "%1" refers to the previous regex.
# If the result is "OK", proxy access is granted.
RewriteCond ${ProxyAllow:%1|DENY} !^OK$ [NC]
# 3) Disallow proxy requests if the site was _not_ tagged "OK":
RewriteRule ^proxy: - [F]
...
</VirtualHost>
Proxy Deny
Description:
How can we forbid a certain host or even a user of a special host from using
the Apache proxy?
Solution:
We first have to make sure mod_rewrite is below(!) mod_proxy in the Configuration
file when compiling the Apache webserver. This way it gets called _before_
mod_proxy. Then we configure the following for a host-dependend deny...
RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* - [F]
...and this one for a user@host-dependend deny:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} ^badguy@badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* - [F]
Special Authentication Variant
Description:
Sometimes a very special authentication is needed, for instance a authentication
which checks for a set of explicitly configured users. Only these should receive
access and without explicit prompting (which would occur when using the Basic
Auth via mod_access).
Solution:
We use a list of rewrite conditions to exclude all except our friends:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend1@client1.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend2@client2.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend3@client3.quux-corp\.com$
RewriteRule ^/~quux/only-for-friends/ - [F]
Referer-based Deflector
Description:
How can we program a flexible URL Deflector which acts on the "Referer"
HTTP header and can be configured with as many referring pages as we like?
Solution:
Use the following really tricky ruleset...
RewriteMap deflector txt:/path/to/deflector.map
RewriteCond %{HTTP_REFERER} !=""
RewriteCond ${deflector:%{HTTP_REFERER}} ^-$
RewriteRule ^.* %{HTTP_REFERER} [R,L]
RewriteCond %{HTTP_REFERER} !=""
RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND
RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]
... in conjunction with a corresponding rewrite map:
##
## deflector.map
##
http://www.badguys.com/bad/index.html -
http://www.badguys.com/bad/index2.html -
http://www.badguys.com/bad/index3.html http://somewhere.com/
This automatically redirects the request back to the referring page (when "-" is used as the value in the map) or to a specific URL (when an URL is specified in the map as the second argument).
Other
External Rewriting Engine
Description:
A FAQ: How can we solve the FOO/BAR/QUUX/etc. problem? There seems no solution
by the use of mod_rewrite...
Solution:
Use an external rewrite map, i.e. a program which acts like a rewrite map.
It is run once on startup of Apache receives the requested URLs on STDIN and
has to put the resulting (usually rewritten) URL on STDOUT (same order!).
RewriteEngine on
RewriteMap quux-map prg:/path/to/map.quux.pl
RewriteRule ^/~quux/(.*)$ /~quux/${quux-map:$1}
#!/path/to/perl
# disable buffered I/O which would lead
# to deadloops for the Apache server
$| = 1;
# read URLs one per line from stdin and
# generate substitution URL on stdout
while (<>) {
s|^foo/|bar/|;
print $_;
}
This is a demonstration-only example and just rewrites all URLs /~quux/foo/... to /~quux/bar/.... Actually you can program whatever you like. But notice that while such maps can be used also by an average user, only the system administrator can define it.
Apache HTTP Server Version 1.3
sources : http://httpd.apache.org/docs/1.3/misc/rewriteguide.html
Dossier dOOnet! projects