Nginx fastcgi_cache med url-parametrar

Vanligtvis vill man undvika att cacha url:er som innehåller parametrar, men det finns tillfällen då man ändå vill att en sida ska cachas, till exempel vid inkommande trafik från annonser som har tracking-parametrar.

fastcgi_cache i Nginx är ett kraftfullt verktyg när det används på rätt sätt. Om du får till en bra konfiguration kan du hantera nästan obegränsat med trafik med små resurser.

Problemet med url-parametrar

Det vanliga antagandet är att de parametrar i url:en som står efter ?-tecknet tolkas av backend och styr vilket innehåll som ska visas på sidan. Därför behöver hela url:en, inklusive alla parametrar hanteras som en unik url i cachen. Tyvärr är ofta kombinationen parametrar oändlig, vilket dels gör att cachen skulle bli oändligt stor, men också att chansen för att två besökare frågar efter samma url väldigt liten.

Därför bör man exkludera sidor med url:er som innehåller url-parametrar från att cachas, t.ex. med följande konfiguration:

...
if ($query_string != "") {
  set $skip_cache 1;
}
...
fastcgi_cache_bypass $skip_cache;
...

Tracking-parametrar

När användare klickar på annonser hos t.ex. Google eller Facebook, läggs det på tracking-parametrar på länken, så att besökare kan komma in på en länk som ser ut så här:

https://www.frukt.se/gurka/?utm_source=youtube&utm_medium=cpm&utm_campaign=gurkan

I det här fallet används URL-parametrarna endast av frontend-kod, t.ex. Facebook-pixel eller Google Analytics. Backend är helt ointresserad av parametrarna, och besökarna kommer få samma innehåll oavsett vad parametrarna innehåller.

Undantag för vissa parametrar

Här är ett exempel på hur man kan göra för att göra ett undantag för vissa parametrar.

Spara path i en variabel

Börja med att skapa en egen variabel som innehåller sökväg från url:en, men utan parametrar. Det görs med map-funktionen i Nginx. Tänk på att den ska ligga utanför server-definitionen, i http-kontexten.

http {
...
  map $request_uri $request_path {
    ~(?<captured_path>[^?]*) $captured_path;
  }
...
}

Intern rewrite som tar bort parametrar

Om url-parametrarna innehåller texten ”utm_” eller ”gclid=” kapas alla parametrar bort.

  if ($args ~* "utm_|gclid=") {
    rewrite ^(.*)$ $uri? ;
  }

Använda rätt cache key

Sista pusselbiten är att använda variabeln vi tidigare skapat för att definiera vilken kombination av variabler som gör att en post i cachen är unik, och får levereras till framtida besökare som har samma variabler i sin request.

  fastcgi_cache_key $scheme$request_method$host$request_path;

Anledningen till att vi inte använder $uri, som man kan tycka borde ha lämpligt innehåll efter vår tidigare rewrite, är för att det ofta kommer ytterligare rewrites när man kör WordPress, Drupal eller något ramverk som skriver om allting till index.php.