Qu'est ce que l'Url Rewriting ?

Le but d'une réécriture d'url est principalement de leurrer les moteurs de recherche... En effet, les moteurs d’indexation du web s’arrêtent généralement de crawler un site dès qu’ils rencontrent un caractère tel que ‘ ?’, ‘=’ et ‘&’ dans l'url : ce sont ces caractères qui font apparaitre aux moteurs que le site est généré dynamiquement.

Pour obliger un robot à parcourir tout un site (et donc indexer un maximum de pages, voir toute une base de données) il convient de lui cacher les variables utilisées et lui faire croire que tout notre site est statique.

Pour résumer , les moteurs ne s'aventurent pas sur un lien du type :
<a href="http://www.serveur.com/arborescence/page.asp?param1=0¶m2=3">Recherche avancée</a>
Par contre ils exploitent ce lien-ci sans difficulté :
<a href="http://www.serveur.com/arborescence/page/motcle/param1/0/param2/3">Recherche avancée</a>
Côté serveur d'application, il convient alors de savoir réinterpréter une requête sur une url du deuxième type et la transformer en url du premier type.

Url Rewriting et IIS

Cotnrairement à Apache, la réécriture d'url 'à la volée' n'est pas chose aisée sur les environnement IIS : aucun module Microsoft n'est intégré à IIS pour permettre une réécriture sous forme d'expressions régulières ou autres.

La meilleure façon de gérer cette réécriture est d'utiliser un filte ISAPI. Ces filtres qui se présentent sous la forme d'une dll chargée sur le serveur d'application permettent de prendre la main au cours du traitement des requêtes HTTP par ce serveur web.

Les filtres ISAPI permettent de se brancher à différentes étapes du traitement, mais une seule étape nous intéresse : "OnPreprocHeaders".

C'est lors de cette étape du traitement que l'url est accessible aussi bien en lecture qu'en écriture.

Comment faire ?

Après avoir lu ce qui précède, normalement vous devez vous dire : "c'est bien joli, mais comment je mets cela en place ?". Si vous avez quelques petites compétences en C++, les outils de développement adéquats (Visual Studio C++ par exemple) et qu'une vingtaine de lignes de code ne vous font pas peur, vous allez vous rendre compte que cela est vraiment simple.

Si par contre vous n'avez rien de tout cela, je crois que vous pouvez arrêter la lecture de cet article ici...

Pour ceux qui sont restés parmis nous voici la marche à suivre (les copies d'écran sont faites avec Visual Studio .Net mais cela est très proche sous Visual Studio C++ 6)

nouveau projet sous visual studio .Net

Tout d'abord, créer un nouveau projet

création d'un filtre ISAPI

Choisir ensuite de créer un filtre et non pas une extension

callback OnPreprocHeaders

Pour finir, choisir la CallBack qui va bien.

Le principe de la réécriture de l’url, sera de rechercher un mot clef dans celle-ci. Une fois ce mot clef trouvé, on remplace tous les caractères ‘/’ rencontrés sur la droite de la chaine par alternativement un ‘=’ puis un ‘&’. Pour finir, on remplace la chaine « /motcle/ » par la chaîne « .asp ? » (ou « .aspx ? » pour un site asp .Net). Cette url réécrite au format « normal » est alors réinjectée dans IIS.

Le développement se fera dans la fonction suivante :

DWORD CexempleFilter::OnPreprocHeaders(CHttpFilterContext* pCtxt,
PHTTP_FILTER_PREPROC_HEADERS pHeaderInfo)
{
// TODO: réagissez à cette notification selon vos besoins et
// retournez le code d'état approprié
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}

Il suffit de rajouter le code suivant (fait à la main de mémoire et peut être bourré de fautes de frappes :) ) au milieu du TODO.

// tableau de char qui va servir à récupérer l'url complète

CHAR Head[2083];
DWORD cbHead = 2 083;

// Limité à 2083 caractères de façon arbitraire par Microsoft...
// Pourtant la rfc 2068 ne limite pas la taille d'une url :
/* The HTTP protocol does not place any a priori limit on the length of
    a URI. Servers MUST be able to handle the URI of any resource they
    serve, and SHOULD be able to handle URIs of unbounded length if they
    provide GET-based forms that could generate such URIs. A server
    SHOULD return 414 (Request-URI Too Long) status if a URI is longer
    than the server can handle (see section 10.4.15).

    Note: Servers should be cautious about depending on URI lengths
    above 255 bytes, because some older client or proxy implementations
    may not properly support these lengths.*/

// on récupère l'url avec les paramètress
pHeaders->GetHeader(pfc->m_pFC,"url",Head,&cbHead);
CString strPhysicalPath=Head;

// strPhysicalPath contient une url du type : http://www.serveur.com/arborescence/page/motcle/param1/0/param2/3

int nPos = strPhysicalPath.Find("/motcle/");
int nPos3 = 0;

if (nPos != -1)
{
// on a trouvé le motcle, on déclenche la réécriture de l'url

// On récupère tout ce qui est à droite du motclef et du /
CString strPath = strPhysicalPath.Right(strPhysicalPath.GetLength() - (nPos + motcle_global.GetLength()));

//Ensuite un sur deux on remplace les / en = ou en &
int un_sur_deux = 0;
while ( (nPos3=strPath.ReverseFind( '/' )) != -1)
{
strPath.SetAt(nPos3, ((un_sur_deux == 0) ? '=' : '&'));
un_sur_deux = ( un_sur_deux + 1 ) % 2;
}

// ici on a donc : param1=0¶m2=3

// pour finir on refait l'url: on prend ce qui est à gauche
// de mot clef, on y colle .asp? et la chaine qu'on vient de travailler
// on obtient une url du type :
// http://www.serveur.com/arborescence/page" + ".asp?" + "param1=0¶m2=3"
strPhysicalPath = strPhysicalPath.Left( nPos ) + ".asp?" + strPath;

// renvoyer à IIS la nouvelle URL
pHeaders->SetHeader(pfc->m_pFC,"url",strPhysicalPath.GetBuffer(0));

Une fois la dll générée et compilée l'installation se passe sans soucis :

Dans les propriétés de votre site,

Choisissez l'onglet ISAPI

Et chargez votre DLL.

Il n'y a plus qu'à tester :)