Table of Contents

Guide pour la création de site Web

Ce guide à plusieurs objectifs :

Introduction

Généralement lors de la création d'un site Web, tous les fichiers se retrouve à la racine du serveur web (DocumentRoot). Que ce soit les fichiers générés par des scripts pour un court instant, des fichiers tampons, des fichiers chargés par les utilisateurs du site ou encore des fichier HTML statique.

Cela peut poser des problèmes, comme un fichier charger par les utilisateurs passant au travers d'un interpréteur (PHP, par exemple), les sauvegardes copiant maladroitement les fichiers tampons, … C'est donc le but de ce guide : comment garder une séparation des données en diminuant les contraintes de celle-ci.

Identifications des problèmes

Différents problèmes peuvent être listés :

Communiquer avec le serveur

Le premier problème pour le développeur est de savoir où l'administrateur système a prévu de l'espace pour tous ces fichiers.

Une des solutions serait qu'ils se décident sur un lieu pour chaque type de fichier ”[…] tu mets tes fichiers tampons dans /var/cache/ton_projet […]”, mais si l'administrateur système désire changer la structure il ne pourra pas trop déplacer ces fichiers (le développeur ayant pris soin de bien codé en dur les chemins à travers tout le code).

Une solution plus élégante est de passer par les variables d'environnement. Elles sont facilement configurables pour chaque site Web, elles sont facilement accessible par le développeur et toujours disponible. Le développeur et l'administrateur système ont juste besoin de s'entendre sur le nom de ces variables :

C'est un bon début, mais l'administrateur système devra définir cinq variables pour chaque site Web, ce qui va lui prendre du temps et augmente le risque d'erreurs (au bout de la deuxième il est déjà très fatigué).

Il suffit de laisser l'administrateur système donner un nom de code au site Web :

Ce nom de code va définir le sous-répertoire que le développeur pourra utiliser (exemple, $WEB_APP_CACHE_DIR/$WEB_APP_CODENAME)

Tenter de créer le sous-répertoire

L'administrateur système est un type sympathique, mais il n'aura certainement pas créer le sous-répertoire. Pour les répertoires en lecture-seule, le développeur ne peut pas le créer, mais pour les fichiers en lecture-écriture, l'application doit tenter des le créer s'il n'existe pas.

Le code

On a parlé des données, mais pas encore du code.

Le code va être déposer naturellement à la racine du serveur Web. C'est l'administrateur système qui va s'occuper du déploiement, mais c'est au développeur de gérer la séparation entre le code dynamique, le code statique (HTML) et les cgi-bin.

Pour rester simple, le répertoire racine contient le contenu dynamique. Les fichiers statiques et les cgi-bin sont des sous-répertoires (afin de présenter des URL absolue comme /static/css/design ou /cgi-bin/query.cgi).

L'administrateur système sait qu'il peut déplacer ces deux répertoires du moment qu'il conserve les URL identiques. Il sait aussi que le fichier d'index est dans le contenu dynamique.

Dans le cas où le fichier d'index est un fichier statique (index.html), c'est le seul fichier pouvant outrepasser la séparation des données et donc être dans le contenu dynamique.

Les outils

Si des outils sont nécessaire, pour du nettoyage avant la mise en production, un répertoire tools devrait être créer. Un README et/ou INSTALL devrait aussi être présent.

Exemple

projet-RELEASE1
 |
 +- content  # Contenu dynamique
 |   |
 |   +- cgi-bin
 |   +- static
 |   +- .htaccess
 |   +- index.php
 |
 +- tools
 |   |
 |   +- clean.sh
 |   +- Makefile
 |
 +- ro
 |   |
 |   +- config
 |   +- lib
 |   +- templates
 |
 +- rw
 |   |
 |   +- cache
 |   +- data
 |   +- spool
 |
 +- .htaccess
 +- README
 +- INSTALL

Quand l'administrateur obtient le projet, il sait :

À propos des bibliothèques

Les bibliothèques sont prévues pour être utilisées par plusieurs applications et donc devrait être un projet séparé. Si les bibliothèques fournies ne sont justes que des “fonctions pour l'application”, elles doivent être mise dans un sous-répertoire du contenu. Logiquement lib devrait être vide et le fichier README devrait contenir la liste des autres projets devant être obtenus et déposé dans l'espace des bibliothèques du serveur.

Si votre projet va être distribué à des personnes sans compétence technique spécifique, les bonnes bibliothèques devrait être incluses lors de la génération de l'archive pour la distribution.

.htaccess

Deux fichiers .htaccess sont visibles.

Le premier est à la racine du projet (et non du serveur) pour permettre aux utilisateurs sans compétence technique spécifique de dé-archiver le projet directement dans le répertoire racine du serveur et avoir un système fonctionnel. Le contenu de ce fichier ressemblerait à ça :

<Files README>
Deny from all
<Files>
<Files INSTALL>
Deny from all
<Files>

RewriteRule ^/(.*) /content/$1 [L]

Le second contient tous ce que désire le développeur. C'est à l'administrateur système de savoir s'il veut activer le gestion du .htaccess sur le serveur Web ou s'il veut inclure ce fichier directement dans la configuration du serveur.

... dans tools

Sans surprise, tools doit contenir ce fichier .htaccess :

Deny from all

Exemple (code)

Un exemple de comment cette structure pourrait être gérée. L'exemple utilise le moteur de modèle smarty :

/* index.php */
 
if(($codename=getenv('WEB_APP_CODENAME'))!==false) {
   if(!empty($codename)) {
      define('WEB_APP_CODENAME', $codename);
   }
}
if(!defined('WEB_APP_CODENAME')) {
   define('WEB_APP_CODENAME', 'project');
}
 
$S = new Smarty();
 
$S->compile_dir = dirname(__FILE__) . '/../rw/cache/compile';
$S->cache_dir = dirname(__FILE__) . '/../rw/cache/cache';
$S->config_dir = dirname(__FILE__) . '/../ro/config';
$S->template_dir = dirname(__FILE__) . '/../ro/template/';
 
$S->plugins_dir[] = dirname(__FILE__) . 'smarty/plugins';
 
if(($cache_dir=getenv('WEB_APP_CACHE_DIR'))!==false) {
   if(file_exists($cache_dir) && 
         is_dir($cache_dir) && 
         is_writable($cache_dir)) {
      $cache_dir .= '/' . WEB_APP_CODENAME;
      if(!file_exists($cache_dir)) {
         mkdir($cache_dir);
      }
      if(file_exists($cache_dir) && 
            is_dir($cache_dir) && 
            is_writable($cache_dir)) {
         mkdir($cache_dir . '/cache');
         mkdir($cache_dir . '/compile');
         if(file_exists($cache_dir . '/cache') &&
               is_dir($cache_dir . '/cache') &&
               is_writable($cache_dir . '/cache')) {
           $S->cache_dir = $cache_dir . '/cache';
         }
         if(file_exists($cache_dir . '/compile') &&
               is_dir($cache_dir . '/compile') &&
               is_writable($cache_dir . '/compile')) {
            $S->compile_dir = $cache_dir . '/compile';
         }
      }
   }
}
 
if(($config_dir=getenv('WEB_APP_CONFIG_DIR'))!==false) {
   if(file_exists($config_dir) &&
         is_dir($config_dir) &&
         is_readable($config_dir) &&
         !is_writable($config_dir)) {
      $config_dir .= '/' . WEB_APP_CODENAME;
      if(file_exists($config_dir) &&
            is_dir($config_dir) &&
            is_readable($config_dir) &&
            !is_writable($config_dir)) {
         $S->config_dir($config_dir);
      }
   }
}
 
if(($template_dir=getenv('WEB_APP_TEMPLATE_DIR'))!==false) {
   if(file_exists($template_dir) &&
         is_dir($template_dir) &&
         is_readable($template_dir) &&
         !is_writable($template_dir)) {
      $template_dir .= '/' . WEB_APP_CODENAME;
      if(file_exists($template_dir) &&
            is_dir($template_dir) &&
            is_readable($template_dir) &&
            !is_writable($template_dir)) {
         $S->template_dir = $template_dir;
      }
   }
}

Comme le serveur de test n'a pas forcément la même structure, il faut pouvoir utiliser les répertoires internes et cela permet aux personnes sans compétence technique spécifique de mettre en service à l'aide d'un ou deux droits.

Inclure des bibliothèques

Les bibliothèques devraient être accessible grâce au chemin d'inclusion automatique, mais pas forcément. Une solution pourrait être :

/* index.php */
 
@include('myLib/myLib.php');
if(!function_exists('my_lib_function')) {
   require(dirname(__FILE__) . '/../ro/lib/myLib/myLib.php');
}

Structure sur le serveur de production

Les données servies par le serveur web devraient être localisées dans /srv. Comme c'est du web, elles devraient être dans /srv/www ou /srv/web. Une structure simple pourrait être :

/srv/web
  |
  +- projects
  |   |
  |   +- httpd-includes
  |   |   |
  |   |   +- project1.conf -> /srv/web/projects/project1/httpd-project1.conf
  |   |   +- project2.conf -> /srv/web/projects/project2/httpd-project2.conf
  |   |
  |   +- project1
  |   |   |
  |   |   +- tools # Outils de l'administrateur
  |   |   +- RELEASE1 # Projet respectant la structure définie
  |   |   +- httpd-project1.conf
  |   |
  |   +- project2
  |       |
  |       +- tools
  |       +- RELEASE1
  |       +- RELEASE2
  |       +- RELEASE3
  |       +- httpd-project2.conf
  |
  +- webroot # juste root ressemble trop à /root
      |
      +- project1 -> /srv/web/projects/project1/RELEASE1/content/
      +- project2 -> /srv/web/projects/project2/RELEASE3/content/

Avec la simple modification d'un lien symbolique (ou physique), tout le site passe en production et il est toujours possible de faire des testes de pré-production.

Spool, cache, ...

Spool

Le répertoire pour les fichiers de “spool” devrait être dans /var/local/spool :

/var/local/spool/
  |
  +- webapps
      |
      +- project1
      +- project2

Cache

Les fichiers tampons dans /var/local/cache

/var/local/cache/
  |
  +- webapps
      |
      +- project1
      +- project2

Configurations

Les fichiers de configuration dans /usr/local/etc

/usr/local/etc
  |
  +- webapps
      |
      +- project1
      +- project2

Templates

Les modèles de fichier dans /usr/local/share/misc

/usr/local/share/misc
  |
  +- webapps
      |
      +- project1
      +- project2

Data

Les données chargées dans /srv/web

/srv/web/data
  |
  +- project1
  +- project2

Bibliothèques

Les langage de développement devrait déjà avoir un répertoire prévu à cet effet, la même hiérarchie est reproduite dans /usr/local

Conclusion

Cette structure veut simplifier le travail, si ce n'est pas le cas ne l'utilisez pas.

Si vous avez uniquement des données statiques, la même structure peut être conservée, il y aura juste moins de répertoire à entrer en action.