Mise en cache de webservice avec Varnish

Publié le dimanche 28 janvier 2024 à 07:40

Le but premier est de trouver une solution pour réduire la charge d'un service web en mettant en cache ses réponses.

L'API RESTfull du webservice sert de passerelle entre un API privé HATEOAS et un client générant plus de 500 000 requêtes par jour.

La première surprise est qu'un client bien élevé, envoyant un en-tête Authorization: Bearer, ne sera pas mis en cache par Varnish par défaut !

Forçons le fonctionnement standard avec l'en-tête pour le préfixe de l'uri de notre webservice:

sub vcl_recv {
        # Force la mise en cache de la réponse même avec req.http.Authorization présent
        if (req.http.Authorization) {
                if (req.url ~ "^/webservice/uri/prefix/") {
                        return (lookup);
                }
        }
}

Ce changement a des conséquences sur la sécurité, puisque n'importe quelle personne autorisée à interroger Varnish sera en mesure de récupérer un résultat en cache sans s'identifier.

Il est important de valider la valeur de l'en-tête Authorization avant de fournir le résultat depuis le cache.

Notre webservice a trois réponses possibles :

Mettons en cache les résultats selon le code de retour :

sub vcl_fetch {
       if (req.url ~ "^/webservice/uri/prefix/") {
                if (beresp.status == 404) {
                        set beresp.ttl = 7d;
                }
                if (beresp.status == 410) {
                        set beresp.ttl = 7d;
                }
                if (beresp.status == 200) {
                        set beresp.ttl = 24h;
                }
        }
}

Avec cette configuration, on a divisé par 5 la quantité de demandes sur notre passerelle pour le client qui n'était pas en mesure de mettre en cache lui-même nos résultats.