Menu Fermer

Comment utiliser if sur Nginx avec des exemples

La directive if est une directive très utile pour paramétrer un site Nginx.
En effet, elle permet d’exécuter du code conditionnel.
Il est donc important de maitriser celle-ci.
Toutefois, de bonnes pratiques sont aussi importantes car vous risquez de créer du code if non fonctionnelle ou encore l’utiliser à tort et à travers.

Dans ce tutoriel, je vous explique comment utiliser if dans Nginx avec des exemples.

Comment utiliser if sur Nginx avec des exemples

Comment utiliser if sur Nginx

La directive if permet d’exécuter du code conditionnel.
Vous pouvez effectuer une comparaison qui exécute un code spécifique, si la condition est VRAI.

La syntaxe est la suivante :

if (condition) {
code
}

Ce qu’il faut savoir :

  • On utilise des opérateurs dans la condition
  • Une variable est considérée comme fausse, si la valeur d’une variable est une chaîne vide ou «0»
  • La négation des comparaisons se fait avec un !
OPERATEURDESCRIPTION
=
!=
Comparaison d’une variable avec une chaîne
~Correspondance d’une variable contre une expression régulière
-f
!-f
Vérification d’un fichier existence
-d
!-d
Vérification d’une existence de répertoire
-e
!-e
Vérification d’un fichier, d’un répertoire ou d’une existence de liens symbolique
-x
!-x
Vérification d’un fichier exécutable avec les opérateurs
Les opérateur dans if de Nginx

Ci-dessous, on test si la méthode est POST, si oui, Nginx retourne un code 405 :

if ($request_method = POST ) {
  return 405;
}

Ci-dessous, on teste l’agent utilisateur et on effectue un rewrite de l’URL au besoin.
Ici on utilise ~ pour vérifier que le useragent contient la chaîne MSIE.

if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
}

Ou encore testez si un paramètre ?t=1065 est présent, si oui on effectue un rewrite de la requête pour un renvoie 302.
Plus de détails : Nginx : faire une redirection (301, 302, HTTP vers HTTPS, URL, …)

if ($args ~ t=1065) {  rewrite ^ https://www.malekal.com/demander-aide/ permanent;  }

Vous pouvez aussi jouer sur le code HTTP 418 pour renvoyer vers une location @cachemiss spécifique sur une série de if.
Par exemple, ci-dessous un exemple pour WordPress où on ne cache pas sur certains paramètres et en présence de cookies.

                location / {
                error_page 418 = @cachemiss;
                recursive_error_pages on;
                if ($request_method = POST) { return 418; }

                if ($arg_s != "") { return 418; }
                if ($arg_p != "") { return 418; }
                if ($args ~ "amp") { return 418; }
                if ($arg_preview = "true") { return 418; }
                if ($arg_ao_noptimize != "") { return 418; }

                if ($http_cookie ~* "wordpress_logged_in_") { return 418; }
                if ($http_cookie ~* "comment_author_") { return 418; }
                if ($http_cookie ~* "wp_postpass_") { return 418; }
                if ($uri = /) { return 418; }
}

  location @cachemiss {
                set $cacherules "max-age=0, no-store, no-cache";
                set $skip_cache 1;
                index index.php;
                try_files $uri $uri/ /index.php$is_args$args;
        }

Eviter d’utiliser if et les bonnes pratiques

La documentation Nginx recommande d’utiliser le if/else seulement avec des cas simples.
Il est aussi indiqué que l’utilisation de if/else dans les directives location de manière complexe peut avoir des comportements non voulus : If is Evil… when used in location context

Dans la mesure du possible utilisez try_else à la place.
Pensez aussi que vous pouvez utiliser une variable.
Par exemple vous initialisez la variable à 0 (Faux) en début de page puis vous faites un test cette dernière.

set $masupervariable 0;

location /pagesuperpage {
                set $masupervariable 1;
}

if ($masupervariable) {
[...]
}

Voici un autre exemple avec map qui évite un if très long.
Dans la page pour sécuriser Nginx, j’explique comment bloquer le useragent.
Pour cela, on créé une variable block_usa qiu permet défaut renvoie 0 (soit donc faux).
Mais elle renvoie 1 (vrai) pour les agents utilisateurs qui contiennent profound, scrapyproject, netcrawler, etc :

map $http_user_agent $block_ua {
        default           0;
        ~*profound        1;
        ~*scrapyproject   1;
        ~*netcrawler      1;
        ~*nmap            1;
        ~*sqlmap          1;
}

Ensuite on renvoie un code HTTP 403 si le useragent est présent dans map :

if ($block_ua) {
                return 403;
        }

Cela offre plusieurs avantages :

  • Vous évitez un if trop long qui peut générer des erreurs lors de modifications
  • Et surtout, le code peut être inclut dans un fichier que l’on peut inclure dans plusieurs server différents. Vous modifiez le fichier une fois et cela est pris en compte sur tous les sites