Vous le savez sans doute, MapServer permet de réaliser du « runtime substitution », soit de la substitution dynamique de variable à l’exécution. En clair, votre requête, CGI ou WMS (ce qui revient peu ou prou au même), intègre un paramètre complémentaire dont la valeur va être interprétée au sein du fichier .map.

Pour être plus clair, imaginons que vous  cartographiez les trajets routiers effectués par des utilisateurs. Chaque utilisateur ne doit voir que ses propres trajets parce qu’on est pas chez Big Brother. En rajoutant un paramètre user_id à la requête envoyée à MapServer, on peut filtrer le contenu renvoyé par le fichier .map. La chaîne SQL de récupération des données devient alors :

DATA « the_geom from trajets WHERE user_id = %user_id% »

C’est tout simple donc. En intégrant entre pourcentages le même paramètre que celui envoyé dans la requête, MapServer lui substitue la valeur associée, et le contenu renvoyé est ainsi filtré. On peut aussi ajouter des expressions régulières pour valider les valeurs envoyées et éviter une bonne grosse SQL injection.

Tout cela est connu et très pratique. Ca tord un peu le coup à l’aspect normalisé quand c’est utilisé en WMS, mais les normes ça sert aussi à être dépassé. Néanmoins, il reste un obstacle à la mise en cache des résultats. TileCache par exemple, qui joue un rôle de proxy, ne fait suivre au serveur WMS que les attributs de la norme WMS, et génère alors une erreur car %user_id% sans rien y subsitituer n’est pas utilisable en SQL. C’est pourtant pratique de mettre aussi ce type de résultat en cache.

Mais il y a une solution ! L’Alaska Ocean Observation System publie un patch qui permet de faire suivre au travers de TileCache n’importe quel attribut complémentaire pour peu qu’il soit déclaré dans le tilecache.cfg (fichier de configuration du cache). Ils l’ont fait pour faire du WMS-T (WMS temporel, enrichi d’une variable temporelle pour récupérer des observations par exemple), et étendu à tout attribut complémentaire, ce qui mérite d’être salué.

Une des complications impliquée par ce genre de techique est la multiplication des arborescence, puisqu’un cache spécifique sera créé pour chaque valeur du paramètre. Avec des milliers d’utilisateurs dans mon exemple, ça peut rapidement poser problème. Mais pourquoi alors ne pas utiliser un cache mémoire (Tilecache avec MemCache), d’une taille pré-définie ? Avec quelques giga-octets, on pourra y stocker un bon nombre de tuiles, sans jamais surcharger le système. Les plus récemment créées remplaceront les plus anciennes quand le cache sera plein. Cette méthode s’adapte aussi assez bien au temps (presque) réel, puisqu’on peut paramétrer le durée de vie des données stockées par MemCache. Pour un suivi de conditions de circulation (bouchons…), on peut ainsi quand-même profiter d’un cache qui dure le temps de la validité de la donnée. Mais même 10 minutes, si de nombreux utilisateurs se connectent, c’est un considérable allégement de la charge système.

Petit résumé :

Dans OpenLayers :

layer = new OpenLayers.Layer.WMS("Couche dynamique en cache",
"http://serveur.com/tilecache/",
{layers: 'layer_test',format:'PNG',user_id:myUserId},
{isBaseLayer:true,visibility:true});

on a donc surchargé la définition de la couche avec un paramètre user_id qui prend la valeur de la variable javascript myUserId.

Dans Tilecache.cfg :

on ajoute à la définition du layer WMS : extra_params=user_id

Dans le MapFile :

On intègre le paramètre à la chaîne DATA (ou FILTER, ou EXPRESSION, ou CONNECTION selon les besoins) : DATA « the_geom FROM trajets WHERE user_id = %user_id% »

on ajoute une ligne dans le bloc METADATA de la couche pour valider le user_id:

‘user_id_validation_string’ ‘^[0-9]{1,2}$’ qui impose un entier fait de deux chiffres au maximum.

MapServer, substitution de variable et mise en cache.
Étiqueté avec :        

4 pesnées sur “MapServer, substitution de variable et mise en cache.

  • 12 juin 2009 à 17:26
    Permalien

    Salut,
    En l’occurrence dans ton exemple, comme j’ai la maitrise sur le code JS (coté client), rien ne m’empêche d’afficher les données de n’importe quel utilisateur en changeant l’id envoyé.
    Ce n’est pas forcément problématique, ça dépend du cas d’application mais il ne faut pas perdre cela de vue.
    Dans tous les cas effectivement, il faut ABSOLUMENT faire la validation des paramètres. Parce que des bonnes idées se transforment parfois en mauvaises en deux temps trois mouvements…
    http://blog.cleverelephant.ca/2009/05/architecture-of-evil.html

    Répondre
    • 12 juin 2009 à 17:39
      Permalien

      oui, comme pour le reste, la sécurisation des accès est indispensable. Ca peut se faire avec l’envoi d’une paire de valeurs plutôt que d’une seule, ou d’une clé suffisamment longue. Mais ça dépasse de loin le sujet de ce post et de son exemple qui se voulait uniquement illustratif.

      Répondre
  • 7 septembre 2010 à 19:02
    Permalien

    Bonjour,

    merci pour cette explication.
    Cependant, je cherchais juste à faire fonctionner cela, sans traiter la partie tilecache.

    Cela ne fonctionne pas.
    Lors de l’exécution, ma carte s’affiche avec les layers, sauf la layer sur lequel je souhaite appliquer un filtre SQL.
    Je l’ai mis dans FILTER.

    Temporairement, je fais passer cela dans l’url de mon wms, en attendant de trouver une solution clean.

    Si vous avez une idée, je suis preneur.

    Merci d’avance.

    Répondre
  • 9 septembre 2010 à 14:20
    Permalien

    Bonjour,

    Il peut y avoir un problème de majuscules. Vérifiez sous quelle forme le paramètre est envoyé, et mettez le éventuellement en majuscule partout.
    Ensuite, essayez de récupérer l’url complète et de la soumettre individuellement dans une nouvelle fenêtre et voir si MapServer ne délivre pas un message explicite.

    Cordialement,

    Guillaume

    Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.