mirror of
https://github.com/apache/httpd.git
synced 2025-11-02 06:53:27 +03:00
actually necessary, but it's sort of an annual tradition. We think tradition is pretty important. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@895795 13f79535-47bb-0310-9956-ffa450edef68
1377 lines
53 KiB
Forth
1377 lines
53 KiB
Forth
<?xml version="1.0" encoding="ISO-8859-1"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr"><head><!--
|
|
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
This file is generated from xml source: DO NOT EDIT
|
|
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
-->
|
|
<title>Guide de réécriture des URLs - Sujets avancés - Serveur Apache HTTP</title>
|
|
<link href="/style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
|
|
<link href="/style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
|
|
<link href="/style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" />
|
|
<link href="/images/favicon.ico" rel="shortcut icon" /></head>
|
|
<body id="manual-page"><div id="page-header">
|
|
<p class="menu"><a href="/mod/">Modules</a> | <a href="/mod/directives.html">Directives</a> | <a href="/faq/">FAQ</a> | <a href="/glossary.html">Glossaire</a> | <a href="/sitemap.html">Plan du site</a></p>
|
|
<p class="apache">Serveur Apache HTTP Version 2.3</p>
|
|
<img alt="" src="/images/feather.gif" /></div>
|
|
<div class="up"><a href="./"><img title="<-" alt="<-" src="/images/left.gif" /></a></div>
|
|
<div id="path">
|
|
<a href="http://www.apache.org/">Apache</a> > <a href="http://httpd.apache.org/">Serveur HTTP</a> > <a href="http://httpd.apache.org/docs/">Documentation</a> > <a href="/">Version 2.3</a> > <a href="./">Rewrite</a></div><div id="page-content"><div id="preamble"><h1>Guide de réécriture des URLs - Sujets avancés</h1>
|
|
<div class="toplang">
|
|
<p><span>Langues Disponibles: </span></p>
|
|
</div>
|
|
|
|
|
|
<p>Ce document complémente la
|
|
<a href="../mod/mod_rewrite.html">documentation de référence</a> du
|
|
module <code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code>. Il décrit les différentes
|
|
manières d'utiliser le module d'Apache <code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code>
|
|
pour résoudre les problèmes d'URLs typiques auxquels sont souvent
|
|
confrontés les webmasters. Nous fournissons une description
|
|
détaillée de la résolution de chaque problème par la configuration
|
|
d'un jeu de règles de réécriture.</p>
|
|
|
|
<div class="warning">ATTENTION: il pourra s'avérer nécessaire de
|
|
modifier les exemples en fonction de la
|
|
configuration de votre serveur, par exemple en ajoutant le drapeau
|
|
<code>[PT]</code> si les modules <code class="module"><a href="/mod/mod_alias.html">mod_alias</a></code> et
|
|
<code class="module"><a href="/mod/mod_userdir.html">mod_userdir</a></code> sont utilisés, etc... Les jeux de
|
|
règles devront également être adaptés pour passer d'un contexte de
|
|
serveur à un contexte de répertoire (fichiers
|
|
<code>.htaccess</code>). Essayez de toujours bien comprendre ce que
|
|
fait un jeu de règles avant de l'utiliser, ce qui pourra vous éviter
|
|
bien des problèmes.</div>
|
|
|
|
</div>
|
|
<div id="quickview"><ul id="toc"><li><img alt="" src="/images/down.gif" /> <a href="#cluster">Accès à une grappe de serveurs via un espace d'adressage
|
|
compatible</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#structuredhomedirs">Répertoires utilisateurs structurés</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#filereorg">Réorganisation du système de fichiers</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#redirect404">Rediriger les URLs erronées vers un autre serveur Web</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#archive-access-multiplexer">Multiplexeur d'accès aux archives</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#browser-dependent-content">Contenu dépendant du navigateur</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#dynamic-mirror">Miroir dynamique</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#reverse-dynamic-mirror">Miroir dynamique inverse</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#retrieve-missing-data">Récupérer des données manquantes depuis l'Intranet</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#load-balancing">Répartition de charge</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#new-mime-type">Nouveau type MIME, nouveau service</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#on-the-fly-content">Régéneration de contenu à la volée</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#autorefresh">Actualisation automatique d'un document</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#mass-virtual-hosting">Hébergement virtuel de masse</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#host-deny">Interdiction d'hôtes</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#proxy-deny">Interdiction du mandataire</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#special-authentication">Variante particulière d'authentification</a></li>
|
|
<li><img alt="" src="/images/down.gif" /> <a href="#referer-deflector">Redirection basée sur le référent</a></li>
|
|
</ul><h3>Voir aussi</h3><ul class="seealso"><li><a href="../mod/mod_rewrite.html">Documentation du
|
|
module</a></li><li><a href="intro.html">Introduction à
|
|
mod_rewrite</a></li><li><a href="rewrite_guide.html">Guide de réécriture - exemples
|
|
utiles</a></li><li><a href="tech.html">Détails techniques</a></li></ul></div>
|
|
<div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="cluster" id="cluster">Accès à une grappe de serveurs via un espace d'adressage
|
|
compatible</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Comment créer un espace d'adressage homogène et compatible
|
|
avec
|
|
tous les serveurs WWW d'une grappe de serveurs d'un intranet ?
|
|
C'est à dire que toutes les URLs (par définition
|
|
locales à un
|
|
serveur et dépendant donc de celui-ci) deviennent
|
|
véritablement <em>indépendantes</em> du serveur ! Nous voulons
|
|
disposer, pour accéder à l'espace de nommage WWW, d'un seul
|
|
espace d'adressage compatible : aucune URL ne
|
|
doit inclure d'information quelconque à propos du serveur
|
|
cible physique. La grappe de serveurs doit elle-même nous
|
|
diriger automatiquement vers le bon serveur cible physique,
|
|
selon les besoins, et ceci de manière transparente.</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Tout d'abord, la connaissance des serveurs cibles est issue
|
|
de tables de correspondances externes (distribuées) qui
|
|
contiennent des informations sur la localisation de nos
|
|
utilisateurs, groupes et entités. Elles se présentent sous la
|
|
forme :</p>
|
|
|
|
<div class="example"><pre>
|
|
utilisateur1 serveur_utilisateur1
|
|
utilisateur2 serveur_utilisateur2
|
|
: :
|
|
</pre></div>
|
|
|
|
<p>On les enregistre sous forme de fichiers
|
|
<code>map.xxx-vers-serveur</code>. On doit ensuite faire
|
|
rediriger à tous les serveurs les URLs de la forme :</p>
|
|
|
|
<div class="example"><pre>
|
|
/u/utilisateur/chemin
|
|
/g/groupe/chemin
|
|
/e/entité/chemin
|
|
</pre></div>
|
|
|
|
<p>vers</p>
|
|
|
|
<div class="example"><pre>
|
|
http://serveur-physique/u/utilisateur/chemin
|
|
http://serveur-physique/g/groupe/chemin
|
|
http://serveur-physique/e/entité/chemin
|
|
</pre></div>
|
|
|
|
<p>si il n'est pas nécessaire que chaque chemin d'URL être valide sur chaque
|
|
serveur. Le jeu
|
|
de règles suivant le fait pour nous à l'aide des fichiers de
|
|
correspondance (en supposant que serveur0 soit un serveur par
|
|
défaut qui sera choisi si l'utilisateur ne possède aucune
|
|
entrée dans la table) :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
|
|
RewriteMap utilisateur-vers-serveur txt:/chemin/vers/map.utilisateur-vers-serveur
|
|
RewriteMap groupe-vers-serveur txt:/chemin/vers/map.groupe-vers-serveur
|
|
RewriteMap entité-vers-serveur txt:/chemin/vers/map.entité-vers-serveur
|
|
|
|
RewriteRule ^/u/<strong>([^/]+)</strong>/?(.*)
|
|
http://<strong>${utilisateur-vers-serveur:$1|serveur0}</strong>/u/$1/$2
|
|
RewriteRule ^/g/<strong>([^/]+)</strong>/?(.*)
|
|
http://<strong>${groupe-vers-serveur:$1|serveur0}</strong>/g/$1/$2
|
|
RewriteRule ^/e/<strong>([^/]+)</strong>/?(.*)
|
|
http://<strong>${entité-vers-serveur:$1|serveur0}</strong>/e/$1/$2
|
|
|
|
RewriteRule ^/([uge])/([^/]+)/?$ /$1/$2/.www/
|
|
RewriteRule ^/([uge])/([^/]+)/([^.]+.+) /$1/$2/.www/$3\
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="structuredhomedirs" id="structuredhomedirs">Répertoires utilisateurs structurés</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Certains sites possédant des milliers d'utilisateurs
|
|
organisent les répertoires home de manière
|
|
structurée, <em>c'est à dire</em> que chaque répertoire home
|
|
se situe dans un sous-répertoire dont le nom commence (par
|
|
exemple) par le premier caractère du nom de l'utilisateur.
|
|
Ainsi, <code>/~foo/chemin</code> est dans
|
|
<code>/home/<strong>f</strong>/foo/.www/chemin</code>, tandis
|
|
que <code>/~bar/chemin</code> est dans
|
|
<code>/home/<strong>b</strong>/bar/.www/chemin</code>.</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Le jeu de règles suivant permet de développer les URLs avec
|
|
tilde selon la représentation ci-dessus.</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteRule ^/~(<strong>([a-z])</strong>[a-z0-9]+)(.*) /home/<strong>$2</strong>/$1/.www$3
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="filereorg" id="filereorg">Réorganisation du système de fichiers</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Voici un cas d'espèce : une application très efficace qui
|
|
fait un usage intensif de règles <code>RewriteRule</code>
|
|
dans le contexte du répertoire pour présenter un aspect
|
|
compréhensible sur le Web sans modifier la structure des
|
|
données.
|
|
Les coulisses de l'affaire : <strong><em>net.sw</em></strong>
|
|
rassemble mes archives de paquetages de logiciels Unix
|
|
librement accessibles, que j'ai commencé à collectionner en
|
|
1992. Pour moi, c'est un passe-temps, mais aussi un travail,
|
|
car alors que j'étudie la science informatique, j'ai aussi
|
|
travaillé depuis de nombreuses années comme administrateur
|
|
système et réseau à mes heures perdues. Chaque semaine j'ai
|
|
besoin de tel ou tel logiciel, et j'ai donc créé une
|
|
arborescence très ramifiée de répertoires où je stocke les
|
|
paquetages :</p>
|
|
|
|
<div class="example"><pre>
|
|
drwxrwxr-x 2 netsw users 512 Aug 3 18:39 Audio/
|
|
drwxrwxr-x 2 netsw users 512 Jul 9 14:37 Benchmark/
|
|
drwxrwxr-x 12 netsw users 512 Jul 9 00:34 Crypto/
|
|
drwxrwxr-x 5 netsw users 512 Jul 9 00:41 Database/
|
|
drwxrwxr-x 4 netsw users 512 Jul 30 19:25 Dicts/
|
|
drwxrwxr-x 10 netsw users 512 Jul 9 01:54 Graphic/
|
|
drwxrwxr-x 5 netsw users 512 Jul 9 01:58 Hackers/
|
|
drwxrwxr-x 8 netsw users 512 Jul 9 03:19 InfoSys/
|
|
drwxrwxr-x 3 netsw users 512 Jul 9 03:21 Math/
|
|
drwxrwxr-x 3 netsw users 512 Jul 9 03:24 Misc/
|
|
drwxrwxr-x 9 netsw users 512 Aug 1 16:33 Network/
|
|
drwxrwxr-x 2 netsw users 512 Jul 9 05:53 Office/
|
|
drwxrwxr-x 7 netsw users 512 Jul 9 09:24 SoftEng/
|
|
drwxrwxr-x 7 netsw users 512 Jul 9 12:17 System/
|
|
drwxrwxr-x 12 netsw users 512 Aug 3 20:15 Typesetting/
|
|
drwxrwxr-x 10 netsw users 512 Jul 9 14:08 X11/
|
|
</pre></div>
|
|
|
|
<p>J'ai décidé en 1996 de rendre cette archive disponible pour
|
|
le monde via une interface web agréable. "Agréable" signifie
|
|
que je voulais vous offrir une interface où vous pourriez
|
|
naviguer directement à travers la hiérarchie des archives.
|
|
Mais "agréable" signifie aussi que je ne voulais rien changer
|
|
dans cette hiérarchie - même pas en ajoutant queques scripts
|
|
CGI à son sommet. Pourquoi ? Parceque j'avais prévu de rendre
|
|
ultérieurement la structure ci-dessus accessible aussi via
|
|
FTP, et je ne voulais pas voir de fichiers CGI ou Web à ce
|
|
niveau.</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>La solution comporte deux parties : la première consiste en
|
|
un ensemble de scripts CGI qui créent toutes les pages à tous
|
|
les niveaux de répertoires à la volée. Je les ai placés dans
|
|
<code>/e/netsw/.www/</code> comme suit :</p>
|
|
|
|
<div class="example"><pre>
|
|
-rw-r--r-- 1 netsw users 1318 Aug 1 18:10 .wwwacl
|
|
drwxr-xr-x 18 netsw users 512 Aug 5 15:51 DATA/
|
|
-rw-rw-rw- 1 netsw users 372982 Aug 5 16:35 LOGFILE
|
|
-rw-r--r-- 1 netsw users 659 Aug 4 09:27 TODO
|
|
-rw-r--r-- 1 netsw users 5697 Aug 1 18:01 netsw-about.html
|
|
-rwxr-xr-x 1 netsw users 579 Aug 2 10:33 netsw-access.pl
|
|
-rwxr-xr-x 1 netsw users 1532 Aug 1 17:35 netsw-changes.cgi
|
|
-rwxr-xr-x 1 netsw users 2866 Aug 5 14:49 netsw-home.cgi
|
|
drwxr-xr-x 2 netsw users 512 Jul 8 23:47 netsw-img/
|
|
-rwxr-xr-x 1 netsw users 24050 Aug 5 15:49 netsw-lsdir.cgi
|
|
-rwxr-xr-x 1 netsw users 1589 Aug 3 18:43 netsw-search.cgi
|
|
-rwxr-xr-x 1 netsw users 1885 Aug 1 17:41 netsw-tree.cgi
|
|
-rw-r--r-- 1 netsw users 234 Jul 30 16:35 netsw-unlimit.lst
|
|
</pre></div>
|
|
|
|
<p>Le sous-répertoire <code>DATA/</code> contient la structure
|
|
de répertoires proprement dite mentionnée plus haut, <em>c'est
|
|
à dire</em> les véritables ressources
|
|
<strong><em>net.sw</em></strong> et est mis à jour
|
|
automatiquement via <code>rdist</code> à intervalles de temps
|
|
réguliers. Reste la seconde partie du problème : comment
|
|
relier ces deux structures selon une arborescence d'URL
|
|
facile d'accès ? Il nous faut cacher le répertoire
|
|
<code>DATA/</code> à l'utilisateur durant l'exécution des
|
|
scripts CGI appropriés aux différentes URLs. Voici comment :
|
|
tout d'abord, j'ajoute ces deux règles dans le fichier de
|
|
configuration du répertoire racine <code class="directive"><a href="/mod/core.html#documentroot">DocumentRoot</a></code> du serveur afin de
|
|
réécrire le chemin d'URL public <code>/net.sw/</code> vers le
|
|
chemin interne <code>/e/netsw</code> :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteRule ^net.sw$ net.sw/ [R]
|
|
RewriteRule ^net.sw/(.*)$ e/netsw/$1
|
|
</pre></div>
|
|
|
|
<p>La première règle concerne les requêtes qui ne comportent
|
|
pas de slash de fin ! C'est la seconde règle qui fait le
|
|
véritable travail. Et maintenant vient la super configuration
|
|
qui se trouve dans le fichier de configuration de répertoire
|
|
<code>/e/netsw/.www/.wwwacl</code> :</p>
|
|
|
|
<div class="example"><pre>
|
|
Options ExecCGI FollowSymLinks Includes MultiViews
|
|
|
|
RewriteEngine on
|
|
|
|
# l'accès s'effectue via le préfixe /net.sw/
|
|
RewriteBase /net.sw/
|
|
|
|
# tout d'abord, on réécrit le répertoire racine vers
|
|
# le script CGI qui lui est associé
|
|
RewriteRule ^$ netsw-home.cgi [L]
|
|
RewriteRule ^index\.html$ netsw-home.cgi [L]
|
|
|
|
# on supprime les sous-répertoires lorsque
|
|
# le navigateur nous atteint depuis des pages de répertoire
|
|
RewriteRule ^.+/(netsw-[^/]+/.+)$ $1 [L]
|
|
|
|
# on stoppe maintenant la réécriture pour les fichiers locaux
|
|
RewriteRule ^netsw-home\.cgi.* - [L]
|
|
RewriteRule ^netsw-changes\.cgi.* - [L]
|
|
RewriteRule ^netsw-search\.cgi.* - [L]
|
|
RewriteRule ^netsw-tree\.cgi$ - [L]
|
|
RewriteRule ^netsw-about\.html$ - [L]
|
|
RewriteRule ^netsw-img/.*$ - [L]
|
|
|
|
# ce qui reste est un sous-répertoire qui peut être traité
|
|
# par un autre script CGI
|
|
RewriteRule !^netsw-lsdir\.cgi.* - [C]
|
|
RewriteRule (.*) netsw-lsdir.cgi/$1
|
|
</pre></div>
|
|
|
|
<p>Quelques indices pour l'interprétation :</p>
|
|
|
|
<ol>
|
|
<li>Remarquez le drapeau <code>L</code> (last) et l'absence
|
|
de chaîne de substitution ('<code>-</code>') dans la
|
|
quatrième partie.</li>
|
|
|
|
<li>Remarquez le caractère <code>!</code> (not) et le
|
|
drapeau <code>C</code> (chain) dans la première règle de la
|
|
dernière partie.</li>
|
|
|
|
<li>Remarquez le modèle qui correspond à tout dans la
|
|
dernière règle.</li>
|
|
</ol>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="redirect404" id="redirect404">Rediriger les URLs erronées vers un autre serveur Web</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Une question typique de la FAQ à propos de la réécriture
|
|
revient souvent : comment rediriger vers un serveur B les
|
|
requêtes qui échouent sur un serveur A ? On s'acquitte en
|
|
général de cette tâche via des scripts CGI <code class="directive"><a href="/mod/core.html#errordocument">ErrorDocument</a></code> en Perl, mais il
|
|
existe aussi une solution avec <code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code>.
|
|
Notez cependant que les performances sont moindres qu'avec
|
|
l'utilisation d'un script CGI <code class="directive"><a href="/mod/core.html#errordocument">ErrorDocument</a></code> !</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>La première solution possède des performances supérieures
|
|
mais moins de souplesse, et est moins sure :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteCond %{DOCUMENT_ROOT/%{REQUEST_URI} <strong>!-f</strong>
|
|
RewriteRule ^(.+) http://<strong>serveurB</strong>.dom/$1
|
|
</pre></div>
|
|
|
|
<p>Le problème réside dans le fait que seules les pages
|
|
situées dans la racine <code class="directive"><a href="/mod/core.html#documentroot">DocumentRoot</a></code> seront redirigées. Mais
|
|
même si vous pouvez ajouter des conditions supplémentaires (par
|
|
exemple pour traiter aussi les répertoires home, etc...), il
|
|
existe une meilleure solution :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteCond %{REQUEST_URI} <strong>!-U</strong>
|
|
RewriteRule ^(.+) http://<strong>serveurB</strong>.dom/$1
|
|
</pre></div>
|
|
reprendre ici
|
|
<p>On utilise ici la fonctionnalité de prévision des URLs
|
|
futures de <code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code>. Et cette solution
|
|
fonctionne pour tous les types d'URLs et de manière sûre. Par
|
|
contre, cette méthode a un impact sur les performances du
|
|
serveur web, car chaque requête entraîne le traitement d'une
|
|
sous-requête interne supplémentaire. Par conséquent, vous
|
|
pouvez l'utiliser si votre serveur web s'exécute sur un CPU
|
|
puissant. Dans le cas d'une machine plus lente, utilisez la
|
|
première approche, ou mieux, un script CGI <code class="directive"><a href="/mod/core.html#errordocument">ErrorDocument</a></code>.</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="archive-access-multiplexer" id="archive-access-multiplexer">Multiplexeur d'accès aux archives</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Connaissez-vous la grande archive CPAN (Comprehensive Perl Archive
|
|
Network) située à <a href="http://www.perl.com/CPAN">http://www.perl.com/CPAN</a> ?
|
|
CPAN redirige automatiquement les navigateurs vers un des
|
|
nombreux serveurs FTP répartis à travers le monde
|
|
(généralement un serveur assez proche du client) ; chaque
|
|
serveur héberge l'intégralité d'un miroir CPAN. Il s'agit ni
|
|
plus ni moins qu'un service d'accès FTP multiplexé. Alors que
|
|
le fonctionnement de l'archive CPAN repose sur des scripts
|
|
CGI, comment implémenter une approche similaire avec
|
|
<code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code> ?</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Premièrement, remarquons que depuis la version 3.0.0,
|
|
<code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code> accepte aussi le préfixe
|
|
"<code>ftp:</code>" dans les redirections. Et deuxièmement,
|
|
l'approximation de la localisation peut être effectuée par une
|
|
table de correspondances <code class="directive"><a href="/mod/mod_rewrite.html#rewritemap">RewriteMap</a></code>, en se basant sur
|
|
la racine du domaine du client. Un jeu de règles chaînées
|
|
astucieux nous permet d'utiliser cette racine du domaine comme
|
|
clé de recherche dans notre table de correspondances de
|
|
multiplexage.</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteMap multiplex txt:/chemin/vers/map.cxan
|
|
RewriteRule ^/CxAN/(.*) %{REMOTE_HOST}::$1 [C]
|
|
RewriteRule ^.+\.<strong>([a-zA-Z]+)</strong>::(.*)$
|
|
${multiplex:<strong>$1</strong>|ftp.défaut.dom}$2 [R,L]
|
|
</pre></div>
|
|
|
|
<div class="example"><pre>
|
|
##
|
|
## map.cxan -- Multiplexing Map for CxAN%{DOCUMENT_ROOT/%{REQUEST_URI}
|
|
##
|
|
|
|
de ftp://ftp.cxan.de/CxAN/
|
|
uk ftp://ftp.cxan.uk/CxAN/
|
|
com ftp://ftp.cxan.com/CxAN/
|
|
:
|
|
##EOF##
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="browser-dependent-content" id="browser-dependent-content">Contenu dépendant du navigateur</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Il est parfois nécessaire, au moins pour les pages
|
|
principales, de fournir un contenu optimum adapté à chaque
|
|
type de navigateur, c'est à dire que l'on doit
|
|
fournir une version pour les navigateurs courants, une version
|
|
différente pour les navigateurs en mode texte du style de
|
|
Lynx, et une autre pour les autres navigateurs.</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>On ne peut pas utiliser la négociation de contenu car les
|
|
navigateurs ne fournissent pas leur type dans cette forme.
|
|
Nous devons nous baser sur l'en-tête HTTP "User-Agent". La
|
|
configuration ci-dessous effectue les actions suivantes : si
|
|
l'en-tête HTTP "User-Agent" commence par "Mozilla/3", la page
|
|
<code>foo.html</code> est réécrite en <code>foo.NS.html</code>
|
|
et la réécriture s'arrête. Si le navigateur est "Lynx" ou
|
|
"Mozilla" version 1 ou 2, la page
|
|
<code>foo.html</code> est réécrite en
|
|
<code>foo.20.html</code>. Tous les autres navigateurs
|
|
reçoivent la page <code>foo.32.html</code>. Voici le jeu de
|
|
règles :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteCond %{HTTP_USER_AGENT} ^<strong>Mozilla/3</strong>.*
|
|
RewriteRule ^foo\.html$ foo.<strong>NS</strong>.html [<strong>L</strong>]
|
|
|
|
RewriteCond %{HTTP_USER_AGENT} ^<strong>Lynx/</strong>.* [OR]
|
|
RewriteCond %{HTTP_USER_AGENT} ^<strong>Mozilla/[12]</strong>.*
|
|
RewriteRule ^foo\.html$ foo.<strong>20</strong>.html [<strong>L</strong>]
|
|
|
|
RewriteRule ^foo\.html$ foo.<strong>32</strong>.html [<strong>L</strong>]
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="dynamic-mirror" id="dynamic-mirror">Miroir dynamique</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Supposons que nous voulions intégrer dans notre espace de
|
|
nommage de belles pages web situées sur un serveur distant.
|
|
Dans le cas d'un serveur FTP, nous aurions utilisé le
|
|
programme <code>mirror</code> qui maintient vraiment une copie
|
|
des données distantes mise à jour explicitement sur le serveur
|
|
local. Pour un serveur web, nous pourrions utiliser le
|
|
programme <code>webcopy</code> qui utilise le protocole HTTP.
|
|
Ces deux techniques présentent cependant un
|
|
inconvénient majeur : la copie locale n'est véritablement à
|
|
jour qu'au moment où nous avons lancé le programme. Plutôt qu'
|
|
un miroir statique devant être défini explicitement, il serait
|
|
préférable d'avoir un miroir dynamique dont le contenu serait
|
|
mis à jour automatiquement, à la demande, sur le(s) serveur(s)
|
|
distant(s).</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Pour y parvenir, on fait
|
|
correspondre la page web ou même l'ensemble du
|
|
répertoire web distants à notre espace de nommage en utilisant
|
|
la fonctionnalité <dfn>Mandataire</dfn> (drapeau
|
|
<code>[P]</code> ou <code>[proxy]</code>) :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteBase /~quux/
|
|
RewriteRule ^<strong>page-convoitée/</strong>(.*)$ <strong>http://www.tstimpreso.com/page-convoitée/</strong>$1 [<strong>P</strong>]
|
|
</pre></div>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteBase /~quux/
|
|
RewriteRule ^<strong>usa-news\.html</strong>$ <strong>http://www.quux-corp.com/news/index.html</strong> [<strong>P</strong>]
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="reverse-dynamic-mirror" id="reverse-dynamic-mirror">Miroir dynamique inverse</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>...</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteCond /miroir/du/site-distant/$1 -U
|
|
RewriteRule ^http://www\.site-distant\.com/(.*)$ /miroir/du/site-distant/$1
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="retrieve-missing-data" id="retrieve-missing-data">Récupérer des données manquantes depuis l'Intranet</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>C'est une méthode astucieuse permettant de faire
|
|
fonctionner virtuellement un serveur web d'entreprise
|
|
(<code>www.quux-corp.dom</code>) sur
|
|
l'Internet (extérieur à l'entreprise), tout en maintenant et
|
|
conservant dans la réalité ses données sur un serveur web
|
|
(<code>www2.quux-corp.dom</code>) de l'Intranet (interne à
|
|
l'entreprise) protégé par un pare-feu. L'astuce consiste, sur
|
|
le serveur web externe, à récupérer à la volée sur le serveur interne
|
|
les données demandées.</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Tout d'abord, nous devons nous assurer que notre pare-feu
|
|
protège bien le serveur web interne, et que seul le serveur
|
|
web externe est autorisé à y récupérer des données. Dans le
|
|
cas d'un filtrage par paquets, nous pourrions par exemple
|
|
définir un jeu de règles du pare-feu du style :</p>
|
|
|
|
<div class="example"><pre>
|
|
<strong>ALLOW</strong> serveur www.quux-corp.dom Port >1024 -->
|
|
serveur www2.quux-corp.dom Port <strong>80</strong>
|
|
<strong>DENY</strong> serveur * Port * -->
|
|
serveur www2.quux-corp.dom Port <strong>80</strong>
|
|
</pre></div>
|
|
|
|
<p>Il vous suffit d'adapter ces règles à la syntaxe de votre
|
|
pare-feu. Nous pouvons maintenant définir les règles de
|
|
<code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code> qui serviront à récupérer les
|
|
données manquantes en arrière-plan via la fonctionnalité de
|
|
mandataire :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteRule ^/~([^/]+)/?(.*) /home/$1/.www/$2 [C]
|
|
# L'utilisation de REQUEST_FILENAME ci dessous est correcte dans cet
|
|
# exemple de contexte au niveau serveur car la règle qui fait référence
|
|
# à REQUEST_FILENAME est chaînée à une règle qui définit
|
|
# REQUEST_FILENAME.
|
|
RewriteCond %{REQUEST_FILENAME} <strong>!-f</strong>
|
|
RewriteCond %{REQUEST_FILENAME} <strong>!-d</strong>
|
|
RewriteRule ^/home/([^/]+)/.www/?(.*) http://<strong>www2</strong>.quux-corp.dom/~$1/pub/$2 [<strong>P</strong>]
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="load-balancing" id="load-balancing">Répartition de charge</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Supposons que nous voulions répartir la charge du trafic
|
|
vers <code>www.example.com</code> entre les serveurs
|
|
<code>www[0-5].example.com</code> (un total de 6 serveurs).
|
|
Comment y parvenir ?</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Il existe de nombreuses solutions à ce problème. Nous
|
|
décrirons tout d'abord une variante assez connue basée sur
|
|
DNS, puis une autre basée sur <code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code>
|
|
:</p>
|
|
|
|
<ol>
|
|
<li>
|
|
<strong>Round-Robin (tourniquet) DNS</strong>
|
|
|
|
<p>La méthode de répartition de charge la plus simple
|
|
consiste à utiliser le "DNS round-robin"
|
|
(rotation d'adresses) de
|
|
<code>BIND</code>. Vous devez seulement enregistrer les
|
|
serveurs <code>www[0-9].example.com</code> de manière
|
|
habituelle dans votre DNS à l'aide d'enregistrements de
|
|
type A (adresse), comme suit :</p>
|
|
|
|
<div class="example"><pre>
|
|
www0 IN A 1.2.3.1
|
|
www1 IN A 1.2.3.2
|
|
www2 IN A 1.2.3.3
|
|
www3 IN A 1.2.3.4
|
|
www4 IN A 1.2.3.5
|
|
www5 IN A 1.2.3.6
|
|
</pre></div>
|
|
|
|
<p>Puis vous ajoutez les entrées suivantes :</p>
|
|
|
|
<div class="example"><pre>
|
|
www IN A 1.2.3.1
|
|
www IN A 1.2.3.2
|
|
www IN A 1.2.3.3
|
|
www IN A 1.2.3.4
|
|
www IN A 1.2.3.5
|
|
</pre></div>
|
|
|
|
<p>Maintenant, lors de la résolution de
|
|
<code>www.example.com</code>, <code>BIND</code> renvoie
|
|
<code>www0-www5</code> - mais selon une permutation
|
|
différente à chaque fois. De cette façon, les clients sont
|
|
répartis entre les différents serveurs. Notez cependant
|
|
que cette méthode de répartition de charge n'est pas
|
|
parfaite, car les résolutions DNS sont mises en cache par
|
|
les clients et les autres serveurs DNS du réseau, si
|
|
bien que lorsqu'un client s'est vu résoudre
|
|
<code>www.example.com</code> en un des
|
|
<code>wwwN.example.com</code>, toutes ses requêtes ultérieures
|
|
continueront d'aller vers la même adresse IP (et donc le
|
|
même serveur), au lieu d'être réparties entre les autres
|
|
serveurs. Le résultat est cependant globalement
|
|
satisfaisant car les requêtes sont réparties
|
|
collectivement entre chacun des serveurs web.</p>
|
|
</li>
|
|
|
|
<li>
|
|
<strong>Répartition de charge basée sur DNS</strong>
|
|
|
|
<p>Une méthode de répartition de charge sophistiquée basée
|
|
sur DNS consiste à utiliser le programme
|
|
<code>lbnamed</code> que l'on peut trouver à <a href="http://www.stanford.edu/~riepel/lbnamed/">
|
|
http://www.stanford.edu/~riepel/lbnamed/</a>.
|
|
Associé à des outils auxiliaires, il s'agit d'un programme
|
|
en Perl 5 qui permet d'effectuer une véritable répartition
|
|
de charge basée sur DNS.</p>
|
|
</li>
|
|
|
|
<li>
|
|
<strong>Round-Robin basé sur la fonctionnalité de
|
|
mandataire</strong>
|
|
|
|
<p>Dans cette variante, nous utilisons
|
|
<code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code> et sa fonctionnalité de
|
|
mandataire. Tout d'abord, nous définissons
|
|
<code>www0.example.com</code> comme un autre nom de
|
|
<code>www.example.com</code> en ajoutant l'entrée</p>
|
|
|
|
<div class="example"><pre>
|
|
www IN CNAME www0.example.com.
|
|
</pre></div>
|
|
|
|
<p>dans le DNS. Puis nous définissons
|
|
<code>www0.example.com</code> comme serveur mandataire
|
|
seulement, c'est à dire que nous configurons cette machine
|
|
de telle sorte que toutes les URLs qui lui arrivent soient
|
|
simplement transmises, via le mandataire interne, vers un
|
|
des 5 autres serveurs (<code>www1-www5</code>). Pour y
|
|
parvenir, nous définissons tout d'abord un jeu de règles
|
|
qui contacte un script de répartition de charge
|
|
<code>lb.pl</code> pour toutes les URLs.</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteMap lb prg:/chemin/vers/lb.pl
|
|
RewriteRule ^/(.+)$ ${lb:$1} [P,L]
|
|
</pre></div>
|
|
|
|
<p>Puis nous écrivons <code>lb.pl</code> :</p>
|
|
|
|
<div class="example"><pre>
|
|
#!/chemin/vers/perl
|
|
##
|
|
## lb.pl -- script de répartition de charge
|
|
##
|
|
|
|
$| = 1;
|
|
|
|
$name = "www"; # la base du nom du serveur
|
|
$first = 1; # le premier serveur (pas 0 ici, car 0 correspond à
|
|
# moi-même)
|
|
$last = 5; # le dernier serveur du tourniquet
|
|
$domain = "foo.dom"; # le nom de domaine
|
|
|
|
$cnt = 0;
|
|
while (<STDIN>) {
|
|
$cnt = (($cnt+1) % ($last+1-$first));
|
|
$server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);
|
|
print "http://$server/$_";
|
|
}
|
|
|
|
##EOF##
|
|
</pre></div>
|
|
|
|
<div class="note">Une dernière remarque : à quoi cela sert-il ?
|
|
<code>www0.example.com</code>, quant à lui, n'est-il pas
|
|
toujours surchargé ? La réponse est oui, il est surchargé,
|
|
mais seulement avec des requêtes de mandataire ! Tous les
|
|
traitements SSI, CGI, ePerl, etc... sont entièrement
|
|
effectués sur les autres machines. Ceci peut fonctionner
|
|
correctement pour un site complexe. Le plus grand risque
|
|
réside ici dans le fait que www0 est un passage obligé et
|
|
que s'il est hors service, les autres serveurs deviennent
|
|
inaccessibles.</div>
|
|
</li>
|
|
|
|
<li>
|
|
<strong>Répartiteur de charge dédié</strong>
|
|
|
|
<p>Il existe aussi des solutions plus sophistiquées.
|
|
Cisco, F5, et de nombreuses autres sociétés proposent
|
|
des répartiteurs de charge matériels (utilisés en général
|
|
en mode doublé à des fins de redondance), qui offrent une
|
|
répartition de charge sophistiquée et des fonctionnalités
|
|
de passage automatique en mode de fonctionnement par défaut
|
|
en cas de problème. Cependant, des solutions logicielles
|
|
offrent aussi des fonctionnalités similaires avec du
|
|
matériel standard. Si vos besoins correspondent et si vous
|
|
êtes assez riche, vous pouvez envisager ces solutions. La
|
|
<a href="http://vegan.net/lb/">liste de diffusion lb-l</a>
|
|
est un bon point de départ pour vos recherches.</p>
|
|
</li>
|
|
</ol>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="new-mime-type" id="new-mime-type">Nouveau type MIME, nouveau service</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>On trouve de nombreux programmes CGI attractifs sur le
|
|
réseau. Mais leur emploi est souvent rébarbatif, si bien que
|
|
de nombreux webmasters ne les utilisent pas. Même la
|
|
fonctionnalité de gestionnaire Action d'Apache pour les types
|
|
MIME ne convient que lorsque les programmes CGI ne nécessitent
|
|
pas d'URLs spéciales (réellement <code>PATH_INFO</code> et
|
|
<code>QUERY_STRINGS</code>) en entrée. Tout d'abord,
|
|
définissons un nouveau type de fichier ayant pour extension
|
|
<code>.scgi</code> (pour CGI sécurisé) qui sera associé pour
|
|
traitement au programme populaire <code>cgiwrap</code>. Le
|
|
problème est le suivant : par exemple, si on utilise un style
|
|
d'URL bien défini (voir ci-dessus), un fichier situé dans le
|
|
répertoire home de l'utilisateur pourra correspondre à l'URL
|
|
<code>/u/user/foo/bar.scgi</code>. Mais <code>cgiwrap</code>
|
|
nécessite des URLs de la forme
|
|
<code>/~user/foo/bar.scgi/</code>. La règle suivante apporte
|
|
la solution :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteRule ^/[uge]/<strong>([^/]+)</strong>/\.www/(.+)\.scgi(.*) ...
|
|
... /interne/cgi/utilisateur/cgiwrap/~<strong>$1</strong>/$2.scgi$3 [NS,<strong>T=application/x-http-cgi</strong>]
|
|
</pre></div>
|
|
|
|
<p>Ou considérons ces autres programmes attractifs :
|
|
<code>wwwlog</code> (qui affiche le journal des accès
|
|
<code>access.log</code> pour un sous répertoire correspondant
|
|
à une URL) et <code>wwwidx</code> (qui exécute Glimpse sur un
|
|
sous répertoire correspondant à une URL). Nous devons fournir
|
|
l'URL correspondante à ces programmes afin qu'ils sachent sur
|
|
quel répertoire ils doivent agir. Mais c'est en général
|
|
compliqué, car ils peuvent être appelés à nouveau
|
|
par la forme d'URL alternative, c'est à dire que typiquement,
|
|
nous exécuterions le programme <code>swwidx</code> depuis
|
|
<code>/u/user/foo/</code> via un hyperlien vers</p>
|
|
|
|
<div class="example"><pre>
|
|
/internal/cgi/user/swwidx?i=/u/user/foo/
|
|
</pre></div>
|
|
|
|
<p>ce qui n'est pas satisfaisant, car nous devons expliciter
|
|
<strong>à la fois</strong> la localisation du répertoire
|
|
<strong>et</strong> la localisation du programme CGI dans
|
|
l'hyperlien. Si nous devons nous réorganiser, il nous faudra
|
|
beaucoup de temps pour modifier tous les hyperliens.</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>La solution consiste ici à fournir un nouveau format d'URL
|
|
qui redirige automatiquement vers la requête CGI appropriée.
|
|
Pour cela, on définit les règles suivantes :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteRule ^/([uge])/([^/]+)(/?.*)/\* /interne/cgi/utilisateur/wwwidx?i=/$1/$2$3/
|
|
RewriteRule ^/([uge])/([^/]+)(/?.*):log /interne/cgi/utilisateur/wwwlog?f=/$1/$2$3
|
|
</pre></div>
|
|
|
|
<p>Et maintenant l'hyperlien qui renvoie vers
|
|
<code>/u/user/foo/</code> se réduit à</p>
|
|
|
|
<div class="example"><pre>
|
|
HREF="*"
|
|
</pre></div>
|
|
|
|
<p>qui est automatiquement transformé en interne en</p>
|
|
|
|
<div class="example"><pre>
|
|
/internal/cgi/user/wwwidx?i=/u/user/foo/
|
|
</pre></div>
|
|
|
|
<p>Une approche similaire permet d'invoquer le programme CGI
|
|
du journal des accès lorsque l'hyperlien <code>:log</code> est
|
|
utilisé.</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="on-the-fly-content" id="on-the-fly-content">Régéneration de contenu à la volée</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Voici une fonctionnalité vraiment ésotérique : des pages
|
|
générées dynamiquement mais servies statiquement, c'est à
|
|
dire que les pages doivent être servies comme des pages
|
|
purement statiques (lues depuis le système de fichiers et
|
|
servies en l'état), mais doivent être générées dynamiquement
|
|
par le serveur web si elles sont absentes. Ainsi, vous pouvez
|
|
avoir des pages générées par CGI qui sont servies statiquement
|
|
à moins qu'un administrateur (ou une tâche de
|
|
<code>cron</code>) ne supprime les
|
|
contenus statiques. Les contenus sont ensuite actualisés.</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
A cet effet, on utilise le jeu de règles suivant :
|
|
|
|
<div class="example"><pre>
|
|
# Cet exemple n'est valable que dans un contexte de répertoire
|
|
RewriteCond %{REQUEST_FILENAME} <strong>!-s</strong>
|
|
RewriteRule ^page\.<strong>html</strong>$ page.<strong>cgi</strong> [T=application/x-httpd-cgi,L]
|
|
</pre></div>
|
|
|
|
<p>Ainsi, une requête pour <code>page.html</code> entraîne
|
|
l'exécution interne de la page <code>page.cgi</code>
|
|
correspondante si <code>page.html</code> n'existe pas
|
|
ou possède une taille de fichier nulle. L'astuce réside ici
|
|
dans le fait que <code>page.cgi</code> est un script CGI
|
|
qui (en plus de <code>STDOUT</code>) écrit sa sortie dans le
|
|
fichier <code>page.html</code>. Une fois le script exécuté, le
|
|
serveur sert la page <code>page.html</code> fraîchement
|
|
générée. Si le webmaster
|
|
veut actualiser les contenus, il lui suffit de supprimer le
|
|
fichier <code>page.html</code> (le plus souvent via une tâche
|
|
de <code>cron</code>).</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="autorefresh" id="autorefresh">Actualisation automatique d'un document</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Lorsque nous créons une page web complexe, ne serait-il pas
|
|
souhaitable que le navigateur web actualise automatiquement la
|
|
page chaque fois que nous en sauvegardons une nouvelle version
|
|
à partir de notre éditeur ? Impossible ?</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Non ! Nous allons pour cela combiner la fonctionnalité MIME
|
|
multipart, la fonctionnalité NPH du serveur web et la
|
|
puissance de <code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code> pour la manipulation
|
|
d'URLs. Tout d'abord, nous définissons une nouvelle
|
|
fonctionnalité pour les URLs : l'ajout de
|
|
<code>:refresh</code> à toute URL fait que la 'page' est
|
|
actualisée chaque fois que la ressource est mise à jour dans
|
|
le système de fichiers.</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteRule ^(/[uge]/[^/]+/?.*):refresh /interne/cgi/apache/nph-refresh?f=$1
|
|
</pre></div>
|
|
|
|
<p>Nous appelons maintenant cette URL</p>
|
|
|
|
<div class="example"><pre>
|
|
/u/foo/bar/page.html:refresh
|
|
</pre></div>
|
|
|
|
<p>ce qui entraîne en interne l'invocation de l'URL</p>
|
|
|
|
<div class="example"><pre>
|
|
/interne/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
|
|
</pre></div>
|
|
|
|
<p>Il ne reste plus qu'à écrire le script CGI. Bien que l'on
|
|
écrive habituellement dans ces cas "laissé à la charge du
|
|
lecteur à titre d'exercice", ;-) je vous l'offre, aussi.</p>
|
|
|
|
<div class="example"><pre>
|
|
#!/sw/bin/perl
|
|
##
|
|
## nph-refresh -- script NPH/CGI pour l'actualisation automatique de
|
|
## pages
|
|
## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
|
|
##
|
|
$| = 1;
|
|
|
|
# éclate la variable QUERY_STRING
|
|
@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 "&lt;b&gt;ERREUR&lt;/b&gt;: Aucun fichier fourni\n";
|
|
exit(0);
|
|
}
|
|
if (! -f $QS_f) {
|
|
print "HTTP/1.0 200 OK\n";
|
|
print "Content-type: text/html\n\n";
|
|
print "&lt;b&gt;ERREUR&lt;/b&gt;: Fichier $QS_f non trouvé\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, "&lt;$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 &lt; $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##
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="mass-virtual-hosting" id="mass-virtual-hosting">Hébergement virtuel de masse</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>La fonctionnalité <code class="directive"><a href="/mod/core.html#virtualhost"><VirtualHost></a></code> d'Apache est intéressante et
|
|
fonctionne de manière satisfaisante jusqu'à quelques
|
|
douzaines de serveurs virtuels. Par contre, si vous êtes un
|
|
FAI et devez héberger des centaines de serveurs virtuels,
|
|
cette méthode n'est pas optimale.</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Pour fournir cette fonctionnalité avec
|
|
<code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code>, on fait correspondre à notre espace de
|
|
nommage la page web ou même le répertoire complet distants en
|
|
utilisant la fonctionnalité <dfn>Mandataire</dfn>
|
|
(drapeau <code>[P]</code>) :</p>
|
|
|
|
<div class="example"><pre>
|
|
##
|
|
## vhost.map
|
|
##
|
|
www.vhost1.dom:80 /chemin/vers/racine-doc/vhost1
|
|
www.vhost2.dom:80 /chemin/vers/racine-doc/vhost2
|
|
:
|
|
www.vhostN.dom:80 /chemin/vers/racine-doc/vhostN
|
|
</pre></div>
|
|
|
|
<div class="example"><pre>
|
|
##
|
|
## httpd.conf
|
|
##
|
|
:
|
|
# utilisation du nom d'hôte canonique pour les redirections, etc...
|
|
UseCanonicalName on
|
|
|
|
:
|
|
# ajout du serveur virtuel en tête du format CLF
|
|
CustomLog /chemin/vers/access_log "%{VHOST}e %h %l %u %t \"%r\" %>s %b"
|
|
:
|
|
|
|
# activation du moteur de réécriture pour le serveur principal
|
|
RewriteEngine on
|
|
|
|
# définition de deux tables de correspondances : une première pour
|
|
# corriger les URLs et une seconde qui associe les serveurs virtuels
|
|
# disponibles avec leurs racines des documents correspondantes.
|
|
RewriteMap lowercase int:tolower
|
|
RewriteMap vhost txt:/chemin/vers/vhost.map
|
|
|
|
# et enfin sélection proprement dite du serveur virtuel approprié via
|
|
# une seule règle longue et complexe :
|
|
#
|
|
# 1. on s'assure de ne pas sélectionner un hôte virtuel pour les
|
|
# adresses communes
|
|
|
|
RewriteCond %{REQUEST_URI} !^/adresse-commune1/.*
|
|
RewriteCond %{REQUEST_URI} !^/adresse-commune2/.*
|
|
:
|
|
RewriteCond %{REQUEST_URI} !^/adresse-communeN/.*
|
|
#
|
|
# 2. on vérifie que l'on dispose bien d'un en-tête Host, car
|
|
# actuellement, cette méthode ne peut faire de l'hébergement virtuel
|
|
# qu'avec cet en-tête
|
|
RewriteCond %{HTTP_HOST} !^$
|
|
#
|
|
# 3. mise en minuscules du nom d'hôte
|
|
RewriteCond ${lowercase:%{HTTP_HOST}|NONE} ^(.+)$
|
|
#
|
|
# 4. recherche ce ce nom d'hôte dans vhost.map et
|
|
# enregistrement de celui-ci seulement s'il s'agit d'un chemin
|
|
# (et non "NONE" en provenance de la condition précédente)
|
|
RewriteCond ${vhost:%1} ^(/.*)$
|
|
#
|
|
# 5. nous pouvons enfin faire correspondre l'URL avec la racine des
|
|
# documents correspondant au serveur virtuel approprié et enregistrer
|
|
# ce dernier à des fins de journalisation
|
|
RewriteRule ^/(.*)$ %1/$1 [E=VHOST:${lowercase:%{HTTP_HOST}}]
|
|
:
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="host-deny" id="host-deny">Interdiction d'hôtes</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Comment interdire l'accès à notre serveur à une liste
|
|
d'hôtes ?</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Pour Apache >= 1.3b6 :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteMap hôtes-interdits txt:/chemin/vers/hôtes-interdits
|
|
RewriteCond ${hôtes-interdits:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR]
|
|
RewriteCond ${hôtes-interdits:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND
|
|
RewriteRule ^/.* - [F]
|
|
</pre></div>
|
|
|
|
<p>Pour Apache <= 1.3b6 :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteEngine on
|
|
RewriteMap hôtes-interdits txt:/chemin/vers/hôtes-interdits
|
|
RewriteRule ^/(.*)$ ${hôtes-interdits:%{REMOTE_HOST}|NOT-FOUND}/$1
|
|
RewriteRule !^NOT-FOUND/.* - [F]
|
|
RewriteRule ^NOT-FOUND/(.*)$ ${hôtes-interdits:%{REMOTE_ADDR}|NOT-FOUND}/$1
|
|
RewriteRule !^NOT-FOUND/.* - [F]
|
|
RewriteRule ^NOT-FOUND/(.*)$ /$1
|
|
</pre></div>
|
|
|
|
<div class="example"><pre>
|
|
##
|
|
## hosts.deny
|
|
##
|
|
## ATTENTION! Ceci est une table de correspondances, pas une liste,
|
|
## même si on l'utilise en tant que telle. mod_rewrite l'interprète
|
|
## comme un ensemble de paires clé/valeur ; chaque entrée doit donc
|
|
## au moins posséder une valeur fictive "-".
|
|
##
|
|
|
|
193.102.180.41 -
|
|
bsdti1.sdm.de -
|
|
192.76.162.40 -
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="proxy-deny" id="proxy-deny">Interdiction du mandataire</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Comment interdire l'utilisation du mandataire d'Apache pour
|
|
un certain hôte, ou même seulement pour un utilisateur
|
|
de cet hôte ?</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>Nous devons tout d'abord nous assurer que
|
|
<code class="module"><a href="/mod/mod_rewrite.html">mod_rewrite</a></code> arrive après(!)
|
|
<code class="module"><a href="/mod/mod_proxy.html">mod_proxy</a></code> dans le fichier de configuration
|
|
lors de la compilation du serveur web Apache. De cette façon,
|
|
il est appelé <em>avant</em> <code class="module"><a href="/mod/mod_proxy.html">mod_proxy</a></code>. Nous
|
|
pouvons ensuite définir cette règle pour une interdiction
|
|
dépendant de l'hôte :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteCond %{REMOTE_HOST} <strong>^hôte-à-rejeter\.mon-domaine\.com$</strong>
|
|
RewriteRule !^http://[^/.]\.mon-domaine.com.* - [F]
|
|
</pre></div>
|
|
|
|
<p>...et celle-ci pour une interdiction dépendant de
|
|
utilisateur@hôte :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>^utilisateur-à-
|
|
rejeter@hôte-à-rejeter\.mon-domaine\.com$</strong>
|
|
RewriteRule !^http://[^/.]\.mon-domaine.com.* - [F]
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="special-authentication" id="special-authentication">Variante particulière d'authentification</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>On a parfois besoin d'une authentification très
|
|
particulière, par exemple une authentification qui vérifie la
|
|
présence d'un utilisateur dans une liste explicitement
|
|
définie. Seuls ceux qui sont présents dans la liste se voient
|
|
accorder un accès, et ceci sans avoir à
|
|
s'identifier/authentifier (comme c'est le cas avec une
|
|
authentification de base via <code class="module"><a href="/mod/mod_auth.html">mod_auth</a></code>).</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>On définit une liste de conditions de réécriture pour
|
|
interdire l'accès à tout le monde, sauf aux utilisateurs
|
|
autorisés :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>!^ami1@client1.quux-corp\.com$</strong>
|
|
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>!^ami2</strong>@client2.quux-corp\.com$
|
|
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>!^ami3</strong>@client3.quux-corp\.com$
|
|
RewriteRule ^/~quux/seulement-pour-les-amis/ - [F]
|
|
</pre></div>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
|
|
<div class="section">
|
|
<h2><a name="referer-deflector" id="referer-deflector">Redirection basée sur le référent</a></h2>
|
|
|
|
|
|
|
|
<dl>
|
|
<dt>Description :</dt>
|
|
|
|
<dd>
|
|
<p>Comment écrire un programme souple qui redirige certaines
|
|
URLs en se basant sur l'en-tête HTTP "Referer", et peut être
|
|
configuré avec autant de pages de référence
|
|
que l'on veut ?</p>
|
|
</dd>
|
|
|
|
<dt>Solution :</dt>
|
|
|
|
<dd>
|
|
<p>On utilise le jeu de règles vraiment astucieux suivant :</p>
|
|
|
|
<div class="example"><pre>
|
|
RewriteMap deflector txt:/chemin/vers/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]
|
|
</pre></div>
|
|
|
|
<p>... en association avec la table de réécriture
|
|
correspondante :</p>
|
|
|
|
<div class="example"><pre>
|
|
##
|
|
## deflector.map
|
|
##
|
|
|
|
http://www.mauvais-sujets.com/mauvais/index.html -
|
|
http://www.mauvais-sujets.com/mauvais/index2.html -
|
|
http://www.mauvais-sujets.com/mauvais/index3.html http://quelque-part.com/
|
|
</pre></div>
|
|
|
|
<p>Les requêtes sont redirigées vers la page de référence
|
|
(lorsque la valeur correspondant à la clé extraite de la table
|
|
de correspondances est égale à "<code>-</code>"), ou vers une
|
|
URL spécifique (lorsqu'une URL est définie dans la table de
|
|
correspondances comme second argument).</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
</div></div>
|
|
<div class="bottomlang">
|
|
<p><span>Langues Disponibles: </span></p>
|
|
</div><div id="footer">
|
|
<p class="apache">Copyright 2010 The Apache Software Foundation.<br />Autorisé sous <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
|
|
<p class="menu"><a href="/mod/">Modules</a> | <a href="/mod/directives.html">Directives</a> | <a href="/faq/">FAQ</a> | <a href="/glossary.html">Glossaire</a> | <a href="/sitemap.html">Plan du site</a></p></div>
|
|
</body></html> |