Approche naïve : regarder la valeur de l'entête User-Agent (variable req.http.User-Agent) mais comme c'est le client qui la fournit, il serait facile de se faire passer pour qui on veut.
Pour vraiment s'assurer que le client est bien ce qu'il prétend être, vous aurez avant tout besoin d'un module varnish (comme celui-ci) pour effectuer une résolution (inversée) DNS afin de récupérer le nom de la "machine" associée à l'adresse IP courante. En en vérifiant le suffixe par une expression régulière, on pourra affirmer si c'est le cas ou non.
Documentations :
Example pour bing :
vcl 4.0; import utils; sub vcl_recv { # le client prétend être bingbot if (req.http.user-agent ~ "bingbot") { # on vérifie si c'est vrai par une résolution inversée if (utils.resolve(client.ip) ~ "\.search\.msn\.com$") { # c'est bien bingbot } else { # il ment } } }
La réponse est simple : il ne la gère en aucune façon, du moins, de base (sans module complémentaire). Dès lors, 2 query string différentes, même simplement sur l'ordre des paramètres (?foo&bar et ?bar&foo), seront 2 "pages" différentes aux yeux de Varnish. Il faut potentiellement faire attention à ce niveau, car il est facile de multiplier les objets cachés à cause de la query string (pensez aux petits malins qui joueraient avec vos URL). Le plus simple, aussi brutal que ça puisse paraître, c'est tout bonnement de la supprimer complètement, si tant est que ce soit possible, ce qui l'est généralement avec des applications développées en MVC.
Pour supprimer la query string, il existe des modules qui réalise cette tâche sans passer par une expression régulière mais on peut le faire directement, sans module, par :
set req.url = regsub(req.url, "\?.*", ""); # à placer dans la fonction vcl_recv
Certains modules proposent d'autres fonctions, comme réaliser un tri (limité ? - quid des sous-tableaux), ce qui permettrait dans mon exemple précédent (?foo&bar vs ?bar&foo) de n'obtenir qu'un objet caché au lieux de deux.
Dans la fonction vcl_recv, renvoyer un code HTTP bidon (701 ci-dessous) et placer en guise de réponse la nouvelle adresse. Ce qui donne, par exemple :
sub vcl_recv { # ... if ("/foo" == req.url) { return (synth(701, "/bar")); } # ... }
C'est par la fonction vcl_synth, que les entêtes sont rectifiées :
sub vcl_synth { if (701 == resp.status) { set resp.http.Location = resp.reason; set resp.status = 301; set resp.reason = "Moved Permanently"; } else { # ... } }
Exemples :
Redirection sans www ⇒ avec www :
sub vcl_recv { if ("y.z" = req.http.host) { return (synth(701, "http://www." + req.http.host + req.url)); } # ... }
Forcer l'usage de https :
sub vcl_recv { if (80 == std.port(local.ip)) { return (synth(701, "https://" + req.http.host + req.url)); } # ... }
Ce sont quelques commandes à saisir en CLI via l'utilitaire varnishadm :
varnisadm … vcl.load <nom mnémonique à associer à cette configuration> <chemin de votre configuration>
varnisadm … vcl.use <nom mnémonique précédemment attribué à cette configuration>
varnisadm … vcl.list
) par la commande varnishadm … vcl.discard <nom mnémonique donné à la configuration ciblée>
(remplacer les … par vos éventuelles options comme -T et -S)
La plupart des distributions/systèmes intègre ça sous la sous-commande reload du script qui gère le démon varnishd.