Outils pour utilisateurs

Outils du site


serveurs:apache:astuces

Diriger une ressource inexistante

Plutôt que d'utiliser la réécriture pour faire ceci :

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /handler.php [L]

Depuis la version 2.2.16, il est possible d'utiliser FallbackResource :

FallbackResource /handler.php

(ErrorDocument 404 /handler.php n'étant pas une solution, c'est le dernier maillon de la chaîne : réécriture > FallbackResource > ErrorDocument)

Les caractères "spéciaux"

Windows (et Mac ?) est un cas à part : il dispose d'une API Unicode (UTF-16) dédiée dont Apache (APR en réalité) tire partie. Par conséquent, l'URL doit être encodée en UTF-8 (APR réalise les conversions UTF-8 ⇔ UTF-16).

Cependant, la réécriture ne semble pas fonctionner avec de l'UTF-8 :

  • un .htaccess en UTF-8 (sans BOM sinon erreur 500 assurée)
  • un .htaccess ASCII/ANSI (ie en écrivant les unités de code à la main : exemple ä écrit en ä)
  • urlencodant les URLs (ä écrit en %C3%A4)

La solution qui semble marcher est l'écriture hexadécimale des unités de code (\xC3\xA4)

Note : par contre, il ne faut pas utiliser une classe (exemple : [aàäá]) mais des alternatives ((?:a|\xC3\xA0|\xC3\xA4|\xC3\xA1) pour le même exemple) puisque le caractère peut demander plusieurs octets/unités de code.

(Windows uniquement) L'erreur 403 consignée comme "(22)Invalid argument: Cannot map …" dans le journal d'erreur (pas d'accès) signifierait que ce n'est pas de l'UTF-8 (valide) (la requête est probablement en ISO).

Et l'erreur 404, signifierait qu'il n'y a pas réécriture.

Par conséquent, ne pas omettre de faire envoyer la requête en UTF-8 par le navigateur. C'est généralement le cas par défaut à présent et est normalement configurable. Sous Firefox, quand la requête n'est pas en UTF-8, les caractères spéciaux sont urlencodées.

Attention : que le lien de la page soit encodé en UTF-8 ou en ISO, le navigateur la renverra selon sa configuration. Du moins c'est le cas sous Firefox, quand network.standard-url.encode-utf8 est à TRUE (valeur par défaut, voir about:config), où l'adresse du lien en ISO est renvoyée/suivie en UTF-8 (réencodage interne au client). En revanche, sous Firefox, un lien urlencodé, est repris tel quel (donc l'encodage initial est conservé).

Unixoïde (Mac exclus ?) : rien de particulier, il ne traite que des octets. Le tout est donc de respecter l'encodage initial du nom.

Les fichiers physiques en eux-même :

  • Windows (et Mac ?) : le nom doit être en UTF-8 (pour LA raison évoquée ci-dessus, excepté si APR venait à être compilé sans APR_HAS_UNICODE_FS)
  • Unixoïde (Mac exclus ?) : respecter l'encodage initial du nom

Pour récapituler :

  • Windows : impose/requiert l'usage d'UTF-8
  • Unixoïde : il faut respecter l'encodage du fichier ou de la réécriture
  • Pour faire de la réécriture sur caractères spéciaux en UTF-8 : coder les unités de code en hexadécimal (\xDD)

Comportement d'autres clients majeurs :

  • Chrome : même comportement que Firefox ; recode les URL non-urlencodée en UTF-8 (URL urlencodée = encodage conservé)
  • IE (8) : idem
  • Opera : idem

Par conséquent, UTF-8 serait l'encodage le plus portable, bien que particulièrement inadéquat à gérer en réécriture. Quoi qu'il en soit, toujours urlencodé (fonction PHP urlencode) ses liens ; c'est le meilleur moyen de lever toute ambiguïté.

Duplicate content

Dans le cas où une même ressource pourrait avoir plusieurs adresses (ce qui arrive généralement avec la réécriture) pour être certain de ne pas être ensuite pénalisé pour duplicate content, ajouter une balise link rel="canonical" indiquant l'URL "officielle" :

<link rel="canonical" href="http://www.example.com/index.html" />

Variables d'environnement : qui utilise quoi ?

Les variables d'environnement sont en réalité gérées par 2 tables différentes au niveau d'Apache :

  • la table (apr_table_t) subprocess_env (membre de la structure request_rec)
  • la table (apr_table_t) notes (membre de la structure request_rec)
struct request_rec {
    // ...
    /** Array of environment variables to be used for sub processes */
    apr_table_t *subprocess_env;
    /** Notes from one module to another */
    apr_table_t *notes;
    // ...
};
  • SetEnvIf : consulte uniquement subprocess_env (et celle créée l'est dans cette dernière)
  • réécriture (%{ENV:X}) : consulte les deux, d'abord notes puis subprocess_env
  • les expressions (Apache >= 2.4), fonction env('X') ou variable %{env:X} : consulte d'abord notes puis subprocess_env puis le système (getenv) - la première trouvée parmi ces 3 emplacements l'emporte
  • Deny (Apache < 2.4) et Require env (Apache >= 2.4) : consulte uniquement subprocess_env
serveurs/apache/astuces.txt · Dernière modification: 08/12/2014 16:28 (modification externe)