Created by potrace 1.13, written by Peter Selinger 2001-2015 image/svg+xml Site Yann
  • Archives
  • Documents
  • Aide

Blog statique de type jekyll sur site cinay.xyz

  • yunohost
  •  23 déc.  2019 26 déc.  2019

Blog statique de type jekyll

CLONER un thème de blog jekyll dans “basicblog”

Les droits sur le dossier

sudo chown   $USER. -R /srv/basicblog

Lancement “bundle” dans le dossier /srv/basicblog

cd /srv/basicblog
bundle install

En cas d’erreur “Following files may not be writable …“

Using concurrent-ruby 1.1.5
Following files may not be writable, so sudo is needed:
  /usr/local/bin
  /var/lib/gems/2.3.0
  /var/lib/gems/2.3.0/build_info
  /var/lib/gems/2.3.0/cache
  /var/lib/gems/2.3.0/doc
  /var/lib/gems/2.3.0/extensions
  /var/lib/gems/2.3.0/gems
  /var/lib/gems/2.3.0/specifications

En cas d’erreur, il faut modifier les droits

sudo chown root.staff -R /var/lib/gems/2.3.0/
sudo chmod 775 -R /var/lib/gems/2.3.0/
sudo usermod -a -G staff $USER

Créer service basicblog
Le script /srv/start_basicblog.sh contenu dans le service

#!/bin/sh
#lancement basicblog
cd /srv/basicblog/
# Attente et construction
/usr/local/bin/bundle exec jekyll build --watch

Droits sur le bash

sudo chown $USER. /srv/start_basicblog.sh
chmod +x /srv/start_basicblog.sh

Pour lancer le serveur basicblog au démarrage, utilisation d’un service systemd
ATTENTION! , remplacer User=utilisateur par votre nom d’utilisateur (echo $USER)

Création d’un service basicblog sous systemd

sudo nano /etc/systemd/system/basicblog.service

Contenu du fichier

[Unit]
Description=basicblog Service
After=network.target

[Service]
Type=simple
User=debadm
ExecStart=/bin/sh /srv/start_basicblog.sh
Restart=on-abort


[Install]
WantedBy=multi-user.target

Lancer le service basicblog :

sudo systemctl daemon-reload
sudo systemctl start basicblog
# Valider le lancement du service basicblog au démarrage
sudo systemctl enable basicblog
#Vérifier
sudo systemctl status basicblog

basicblog génére un dossier statique /srv/basicblog/_site

Pour un accès via le lien https://blog.cinay.xyz, il faut modifier le dossier “root” du site pour qu’il pointe sur **/srv/basicblog/site**
Le dossier “root” actuel est /var/www/webapp_yannick/blog.cinay.xyz
/
On le déplace sudo mv /var/www/webapp_yannick/blog.cinay.xyz_/ . ou efface : sudo rm -r /var/www/webapp_yannick/blog.cinay.xyz_/

Créer le lien avec le dossier /srv/basicblog/_site du site statique

sudo ln -s /srv/basicblog/_site /var/www/webapp_yannick/blog.cinay.xyz_

basicblog-web
Accès site statique https://blog.cinay.xyz

Changer de thème
Les différents thèmes jekyll qui seront testés doivent respecter la procédure suivante

  1. Si un thème présent, il faut le supprimer ou le sauvegarder
    sudo rm -r /srv/basicblog ou sudo mv /srv/basicblog .
    • Les thèmes seront “clonés” en /srv/basicblog
      ex: git clone https://github.com/dbtek/dbyll.git /srv/basicblog
    • Aller au dossier : cd /srv/basicblog
    • Effacer le .lock : rm Gemfile.lock
    • Installer : bundle install
    • Redémarrer le service sudo systemctl restart basicblog

basicblog-web
Tester le nouveau thème https://blog.cinay.xyz

Personalisation thème, style et plugins

favicon

Image dans le répertoire “images”
Définir une constante pour le fichier image favicon_ico: ym01.png dans le fichier _config.yml
Modifier le fichier _includes/default.html

<link rel="icon" type="image/png" href="/images/">

jekyll-toc

jekyll-toc : Un plugin de filtrage pour Jekyll qui génère une table des matières.

Installation

Ajouter le plugin jekyll-toc dans le Gemfile de votre site.

gem install jekyll-toc

Ajouter la ligne suivante au fichier Gemfile:
gem 'jekyll-toc'

Et ajouter le jekyll-toc au fichier _config.yml de votre site.

plugins:
  - jekyll-toc

Ecrire toc: true dans vos publications (posts).

---
layout: article
title: "Welcome to Jekyll!"
toc: true
---

Ajouter en fin du fichier assets/css/style.css

.section-nav {
  background-color: #FFF;
  margin: 5px 0;
  padding: 10px 30px;
  border-radius: 3px;
}

.toc-entry.toc-h1 { list-style-type: none;}
.toc-entry.toc-h2 { padding-left: 15px; list-style-type: none;}
.toc-entry.toc-h3 { padding-left: 30px; list-style-type: none;}
.toc-entry.toc-h4 { padding-left: 45px; list-style-type: none;}
.toc-entry.toc-h5 { padding-left: 60px; list-style-type: none;}
.toc-entry.toc-h6 { padding-left: 75px; list-style-type: none;}

Actualiser l’installation

bundle update

Usage

Il y a trois filtres liquid disponibles aujourd’hui, qui devraient tous être appliqué à un contenu HTML, par exemple le contenu de la variable liquid disponible dans les modèles de Jekyll.

Utilisation de base (PAR DEFAUT)

filtre toc

Remplacer {{ content }} par {{ content | toc }} dans le fichier _includes/post.html

Ce filtre met la table des matières directement au-dessus du contenu.

Modifier la ligne 42 dans le fichier _includes/post.html


...
          <div class="article_body">
          <!-- {{ content | toc }} -->
          </div>

...

Relancer le service

sudo systemctl restart basicblog

Utilisation avancée

Si vous souhaitez séparer le TOC et son contenu, vous pouvez utiliser les filtres toc_only et inject_anchors .

**filtre **toc_only

Génère le TOC lui-même comme décrit ci-dessous. Surtout utile dans les cas où la table des matières ne doit pas être placée immédiatement au-dessus du contenu, mais à un autre endroit de la page, à savoir un côté.

filtre inject_anchors

Injecte les “ancres” HTML dans le contenu sans réellement créer la table des matières elle-même. Ils sont de la forme:

<a id="heading11" class="anchor" href="#heading1-1" aria-hidden="true">
  <span class="octicon octicon-link"></span>
</a>

Ceci est seulement utile lorsque le TOC lui-même doit être placé à un autre endroit avec le filtre toc_only.

Ajout d’un champ date de modification

Champ date de modification , ajouter la ligne suivante au fichier Gemfile

gem 'jekyll-last-modified-at'

Mise à jour

bundle update

Coder en dur last_modified_at sur chaque billet

---
layout:             post
title:              "An awesome blog post"
create: 2019-12-23
modif:   2019-03-25 8:30:00 +0000
---

Je veux seulement spécifier last_modified_at si le post est en cours de mise à jour. Lorsque j’écris un nouveau message, je laisse ce champ vide. Afin de faire ce travail, j’ai ajouté une logique conditionnelle au modèle de publication.

Avec cette disposition en place, j’ai ajouté la logique conditionnelle:

{%- assign date_format = site.minima.date_format | default: '%b %-d, %Y' -%}

{%- if page.last_modified_at -%}
{%- else -%}
{%- endif -%}

Si la publication a une date last_modified_at elle sera affichée, sinon elle affichera la date de publication d’origine.

Dans mon cas, je veux afficher la date last_modified_at en haut du post et avoir également la date de publication d’origine en bas. De cette façon, les lecteurs savent si le message a été mis à jour récemment et aussi la date de sa publication initiale. Mon fichier de disposition de publication ressemble à ceci:

---
layout: default
---
<article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">

  <header class="post-header">
    <h1 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>
    <p class="post-meta">
      <time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
        {%- assign date_format = site.minima.date_format | default: '%b %-d, %Y' -%}

        {%- if page.last_modified_at -%}
        {%- else -%}
        {%- endif -%}
      </time>
      {%- if page.author -%}
        • <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">{{ page.author | escape }}</span></span>
      {%- endif -%}
  </header>

  <div class="post-content e-content" itemprop="articleBody">
    {{ content }}
  </div>

  <p class="post-meta">
    <time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
      </time>
  </p>

  {%- if site.disqus.shortname -%}
    {%- include disqus_comments.html -%}
  {%- endif -%}

  <a class="u-url" href="{{ page.url | relative_url }}" hidden></a>
</article>

Ajoutez Syntax Highlighting à votre site Jekyll avec Rouge

  • Add Syntax Highlighting to your Jekyll site with Rouge

La mise en évidence de la syntaxe est importante (en particulier pour la programmation de blogs) car elle améliore la lisibilité des articles. Il permet aux lecteurs de localiser rapidement les extraits de code (qui sont généralement la raison pour laquelle les gens visitent votre page en premier lieu) dont ils ont besoin.

Rouge est un surligneur de syntaxe pur rubis et a été le surligneur par défaut pour Jekyll depuis Jekyll 3 (en remplacement des pygments). Vous pouvez ajouter la syntaxe highlihting en utilisant rouge à votre site Jekyll en quelques étapes seulement.

1 - Installez les gemmes kramdown et rouge
Assurez-vous que les gemmes kramdown et rouge sont installées.

gem install kramdown rouge 

2 - Modifiez vos paramètres _config.yml
Ajoutez les lignes suivantes à votre fichier _config.yml si elles ne s’y trouvent pas déjà.

markdown: kramdown

kramdown:
  input: GFM
  syntax_highlighter: rouge

Si cela ne fonctionne pas, vous pouvez essayer:

markdown: kramdown
highlighter: rouge

Par expérience, mes temps de génération lors de l’utilisation de la première option sont généralement plus rapides.

3 - Créez un fichier css pour le style de surbrillance que vous souhaitez

Rouge est intégré à rougify , un outil en ligne de commande qui convertit un thème de style en fichier css.

Vous pouvez voir les thèmes disponibles en entrant:

rougify help style 

Depuis rouge 1.11.1, les thèmes disponibles sont:
base16, base16.dark, base16.monokai, base16.monokai.light, base16.solarized, base16.solarized.dark, coloré, github, gruvbox, gruvbox.light, molokai, monokai, monokai.sublime, thankful_eyes

Par exemple, si vous souhaitez utiliser le thème monokai, vous devez d’abord créer un fichier css dans votre dossier css à l’aide de rougify:

rougify style monokai > /path/to/css/file.css

Le répertoire habituel pour les fichiers css est assets / css tandis que le nom habituel pour le fichier css est syntax.css donc à partir de votre racine, vous pouvez taper:

rougify style monokai > assets/css/syntax.css

N’oubliez pas ensuite d’inclure la feuille de style dans votre modèle HTML (généralement dans <head> </head>):

<link href= "path-to-syntax-highlighter-stylesheet" rel= "stylesheet" >

Si vous avez enregistré la feuille de style du surligneur de syntaxe en tant que assets/css/syntax.css, vous pouvez ajouter les éléments suivants dans votre modèle HTML nommé _include/default.html:

<link href= "/assets/css/syntax.css" rel= "stylesheet" >
ou
<link href="/assets/css/syntax.css" rel="stylesheet">

4 - Ajoutez une coloration syntaxique à vos articles

Si vous utilisez markdown pour créer vos publications, vous pouvez ajouter une coloration syntaxique en joignant l’extrait de code précédé er suivi de trois backticks ( `` `).
De plus, vous pouvez définir la langue de l’extrait de code après les trois backticks d’ouverture.

Par exemple, si vous souhaitez mettre en évidence du code python

def function():
  print('Yes')

Vous pouvez vérifier les langues prises en charge en entrant:

rougify list 

5 - Que faire si je veux afficher ( `` `) dans mes blocs de code?

Disons que vous voulez afficher ` ` dans votre bloc de code Ce que vous devez faire est de mettre en retrait le ` ` dans votre fichier markdown d’au moins 4 espaces.

The line below is indented by at least 4 spaces.

```python
def function():
  print('Yes')
```
  1. Comment puis-je faire fonctionner des blocs de code ou des extraits de code dans les listes GFM (Github Flavored Markdown)?

Les blocs de code peuvent parfois casser des listes ordonnées (c’est-à-dire que la liste revient toujours à 1). Pour éviter cela, vous pouvez procéder comme suit.

si vous ajoutez un saut de ligne après l’élément de campagne, faites en sorte que le bloc de code soit en retrait d’au moins 4 espaces de l’élément de campagne.

1. Number 1

    ```python
    print("Hello World")
    ```

2. Number 2

    ```ruby
    puts 'Hello World'
    ```

3. Number 3

    ```c
    printf("Hello World");
    ```

ce qui donne:

Numéro 1

 print ( "Hello World" ) 

Numéro 2

 puts 'Hello World' 

Numéro 3

 printf ( "Hello World" ); 

Position des éléments “barre latéral gauche”

Contenu de la barre latérale alligné vers le haut (1% au lieu de 10%)
Directive .sidebar , l’attribut padding-top: 10%; passe à padding-top: 1%; dans le fichier assets/css/style.css

Largeur des colonnes

Modifier la largeur en respectant la proportionnalité , fichier _includes/default.html dans les lignes suivantes


...
	<div class="col-sm-2 sidebar hidden-xs" style="{% if site.sidebar_background_image %}background: url({{site.sidebar_background_image}}) no-repeat center center !important;{% endif %}">
		{% include sidebar.html %}
	</div>

	<div class="col-sm-10 col-sm-offset-2"> 
...

Haut de page (sur écran en bas à droite)

Dans le fichier _includes/default.html insérer les lignes suivantes avant <div class="col-sm-2 sidebar hidden-xs" de la modification précédente


...
   <!-- nav-menu-haut -->
   <div id="nav-haut-page">
   	<a href="#" title="Haut de Page"><i class="fa fa-arrow-circle-up fa-2x"></i></a>
   </div>
...

Modifications autres

Fichier tags.html
Ligne 4 -> title: Etiquettes
Ligne 29 -> Billets étiquettés

Fichier _includes/default.html
Ligne 73 et 87 -> Etiquettes remplace Mots clés

Fichier categories.html
Ligne 3 -> Catégories

Recherche rapide avec fichier json et lunr.js

Actuellement , à chaque recherche, il est généré des données indexées au format json qui représentent le contenu du site.Suivant le volume des données ,la durée de la génération peut être assez longue…

Fichier basicblog.json

Pour rendre la recherche plus rapide , il faut utiliser un fichier json qui sera construit à chaque compilation.
Créez un fichier /basicblog.json à la racine de votre site Jekyll /srv/basicblog/, et remplissez-le avec ce qui suit:

---
layout: null
---
[
{% assign count = 0 %}
 {% assign sortedPosts = site.posts | sort: 'date' %}
  {% for post in sortedPosts %}

    {
      "id": {{count}},
      "title": {{ post.title | jsonify }},
      "url":  {{ post.url | jsonify }},
      "tags": "{% for tag in post.tags %}{{ tag }}{% unless forloop.last %}, {% endunless %}{% endfor %}",
      "categories": "{% for category in post.categories %}{{ category }}{% unless forloop.last %}, {% endunless %}{% endfor %}",
      "content"	 : {{post.content | strip_html | truncatewords: 20 | jsonify }}
    }
    {% unless forloop.last %},{% endunless %}
   {% assign count = count | plus: 1 %}
  {% endfor %}
]

Chaque fois que vous exécutez le processus de compilation de Jekyll, Jekyll utilisera /basicblog.json pour déterminer où chercher et ce qu’il faut saisir et il génèrera un fichier _site/basicblog.json.

Analyse json via lunr

Chargement et indexation du fichier pour la recherche , fichier javascript searchplus.js dans le dossier js/

$(document).ready(function () {
var idx ;
var nbart = 0;
var fichier_json = 'basicblog.json';

//http://www.pureexample.com/jquery/get-json.html
function executerRequete(callback) {
   if (nbart === 0) {
        /* set no cache */
        $.ajaxSetup({ cache: false });

			  idx = lunr(function () {
			    this.field('id');
			    this.field('title');
             this.field('content', { boost: 10 });
			    this.field('url');
			    this.field('date');
			    this.field('modif');
			  });

           var html = [];

	  // Get the generated search_data.json file so lunr.js can search it locally.
	  datas = $.getJSON(fichier_json);
	  // Wait for the data to load and add it to lunr
	  datas.then(function(loaded_data){
		    $.each(loaded_data, function(index, d){
		             idx.add({
						    id: index,
						    title: d.title,
						    content: d.content,
						    url: d.url,
						    modif: d.modif
						  });
						  nbart=nbart + 1;
						/*	//stockage item du fichier	
		                html.push("Titre : ", d.title, ", ",
		                          "URL : ", d.url, ", ", 
		                          "Catégorie : ", d.categories, "<br>");
		               // fin */
		    });
 				
  			  /* // affichage des items
            $("#div381").html(html.join('')).css("background-color", "orange");
            */
            // on lance la fonction de callback, le json est chargé et indexé pour la recherche
            callback();

        });
        $.error(function(jqXHR, textStatus, errorThrown){ /* assign handler */
            /* alert(jqXHR.responseText) */
            alert("error occurred!");
        });
    } else {
        // on lance la fonction de callback avec le json déjà récupéré précédemment
        callback();
    }
 }

 $('input#search').focus();
  
	  // Event when the key
	  $('input#search').on('keyup', function () {
	      //event.preventDefault();
	      //var query = $("input#search").val(); // Get the value for the text field
	      var query = $(this).val();
	      var results = idx.search(query); // Get lunr to perform a search
	      display_search_results(results); // Hand the results off to be displayed
	  });

	  /*  fonction affichage des résultats   */
	  function display_search_results(results) {
	    var $search_results = $("#results");
	    // Wait for data to load
	    datas.then(function(loaded_data) {
	
	      // Are there any results?
	      if (results.length) {
	        $search_results.empty(); // Clear any old results
	
	        // Itération sur les résultats
	        results.forEach(function(result) {
	          var item = loaded_data[result.ref];

	          // Création d'une chaîne HTML pour ce résultat
            if (item.modif == null) {
                var datemodif='';  // date de modification identique à la date de création du post , on ajoute rien
            } else {
                var datemodif='<span class="badge" style="background-color: #FF8C00;"><small>Modifié le '+item.modif+'</small></span>'; // ajout date de modification
            }
	          //var appendString = '';
		      var appendString = '<div class="result"><div class="result-body"><a href="'+item.url+'" class="post-title">'+item.title+'</a>&nbsp;<span class="badge" style="background-color: #32CD32;"><small>'+item.date+'&nbsp;</small></span>'+datemodif+'<p>'+item.content+'</p></div>'
	          // Add the snippet to the collection of results.
	          $search_results.append(appendString);
	        });
	      } else {
	        // Si aucun résultat dans la recherche ,on efface les résultats précédents 
	        $search_results.html('');
	      }

	      
	    });
	  }
  function lecture() {
    //$("#nombre").html(nbart);
  }

 // on initialise la lecture au premier élément
 executerRequete(lecture);
   
});

Ajouter le formulaire de recherche

Modifier le fichier _includes/default.html pour y inclure les 2 fichiers javascript lunr.min.js et searchplus.js sous js/

   <script src="/js/lunr.min.js"></script>
   <script src="/js/searchplus.js"></script>

Le formulaire de recherche dans le fichier _includes/page.html

<div class="page-header"> 
  <!-- <span>Blog statique de type jekyll sur site cinay.xyz </span> -->
	<div class="form-group">
		<input placeholder="Rechercher" type="search" id="search" class="form-control input-lg">
	</div>
	<div class="btn-group hidden-xs" id="nav-menu">
		<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
			<i class="fa fa-bars"></i>
		</button>
		<ul class="dropdown-menu" role="menu">
			<li><a href="/"><i class="fa fa-home"></i>Accueil</a></li>
			<li><a href="/"><i class="fa fa-folder"></i>Catégories</a></li>
			<li><a href="/"><i class="fa fa-tags"></i>Balises</a></li>
			<li class="divider"></li>
			<li><a href="#"><i class="fa fa-arrow-up"></i>Haut de la Page</a></li>
		</ul>
	</div>
	<div id="results" class="all-posts results"></div>  
  
</div>

<!DOCTYPE html><html lang="fr">
  <head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>Nginx personnalisation des pages d'erreur - Site Yann</title>

<meta name="description" content="Configurer Nginx pour utiliser des pages d’erreur personnaliséesIntroductionNginx est un serveur Web haute performance capable de servir du contenu avec flex...">
<link rel="canonical" href="https://static.cinay.eu/2019/12/21/Nginx-personnalisation-page-erreur.html"><link rel="alternate" type="application/rss+xml" title="Site Yann" href="/feed.xml"><!-- start favicons snippet, use https://realfavicongenerator.net/ --><link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16x16.png"><link rel="manifest" href="/assets/site.webmanifest"><link rel="mask-icon" href="/assets/safari-pinned-tab.svg" color="#fc4d50"><link rel="shortcut icon" href="/assets/favicon.ico">

<meta name="msapplication-TileColor" content="#ffc40d"><meta name="msapplication-config" content="/assets/browserconfig.xml">

<meta name="theme-color" content="#ffffff">
<!-- end favicons snippet --><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets -->
<!-- end custom head snippets -->
<script>(function() {
  window.isArray = function(val) {
    return Object.prototype.toString.call(val) === '[object Array]';
  };
  window.isString = function(val) {
    return typeof val === 'string';
  };

  window.hasEvent = function(event) {
    return 'on'.concat(event) in window.document;
  };

  window.isOverallScroller = function(node) {
    return node === document.documentElement || node === document.body || node === window;
  };

  window.isFormElement = function(node) {
    var tagName = node.tagName;
    return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
  };

  window.pageLoad = (function () {
    var loaded = false, cbs = [];
    window.addEventListener('load', function () {
      var i;
      loaded = true;
      if (cbs.length > 0) {
        for (i = 0; i < cbs.length; i++) {
          cbs[i]();
        }
      }
    });
    return {
      then: function(cb) {
        cb && (loaded ? cb() : (cbs.push(cb)));
      }
    };
  })();
})();
(function() {
  window.throttle = function(func, wait) {
    var args, result, thisArg, timeoutId, lastCalled = 0;

    function trailingCall() {
      lastCalled = new Date;
      timeoutId = null;
      result = func.apply(thisArg, args);
    }
    return function() {
      var now = new Date,
        remaining = wait - (now - lastCalled);

      args = arguments;
      thisArg = this;

      if (remaining <= 0) {
        clearTimeout(timeoutId);
        timeoutId = null;
        lastCalled = now;
        result = func.apply(thisArg, args);
      } else if (!timeoutId) {
        timeoutId = setTimeout(trailingCall, remaining);
      }
      return result;
    };
  };
})();
(function() {
  var Set = (function() {
    var add = function(item) {
      var i, data = this._data;
      for (i = 0; i < data.length; i++) {
        if (data[i] === item) {
          return;
        }
      }
      this.size ++;
      data.push(item);
      return data;
    };

    var Set = function(data) {
      this.size = 0;
      this._data = [];
      var i;
      if (data.length > 0) {
        for (i = 0; i < data.length; i++) {
          add.call(this, data[i]);
        }
      }
    };
    Set.prototype.add = add;
    Set.prototype.get = function(index) { return this._data[index]; };
    Set.prototype.has = function(item) {
      var i, data = this._data;
      for (i = 0; i < data.length; i++) {
        if (this.get(i) === item) {
          return true;
        }
      }
      return false;
    };
    Set.prototype.is = function(map) {
      if (map._data.length !== this._data.length) { return false; }
      var i, j, flag, tData = this._data, mData = map._data;
      for (i = 0; i < tData.length; i++) {
        for (flag = false, j = 0; j < mData.length; j++) {
          if (tData[i] === mData[j]) {
            flag = true;
            break;
          }
        }
        if (!flag) { return false; }
      }
      return true;
    };
    Set.prototype.values = function() {
      return this._data;
    };
    return Set;
  })();

  window.Lazyload = (function(doc) {
    var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
    var createNode = function(name, attrs) {
      var node = doc.createElement(name), attr;
      for (attr in attrs) {
        if (attrs.hasOwnProperty(attr)) {
          node.setAttribute(attr, attrs[attr]);
        }
      }
      return node;
    };
    var end = function(type, url) {
      var s, q, qi, cbs, i, j, cur, val, flag;
      if (type === 'js' || type ==='css') {
        s = sources[type], q = queue[type];
        s[url] = true;
        for (i = 0; i < q.length; i++) {
          cur = q[i];
          if (cur.urls.has(url)) {
            qi = cur, val = qi.urls.values();
            qi && (cbs = qi.callbacks);
            for (flag = true, j = 0; j < val.length; j++) {
              cur = val[j];
              if (!s[cur]) {
                flag = false;
              }
            }
            if (flag && cbs && cbs.length > 0) {
              for (j = 0; j < cbs.length; j++) {
                cbs[j].call(context);
              }
              qi.load = true;
            }
          }
        }
      }
    };
    var load = function(type, urls, callback) {
      var s, q, qi, node, i, cur,
        _urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
      if (type === 'js' || type ==='css') {
        s = sources[type], q = queue[type];
        for (i = 0; i < q.length; i++) {
          cur = q[i];
          if (_urls.is(cur.urls)) {
            qi = cur;
            break;
          }
        }
        val = _urls.values();
        if (qi) {
          callback && (qi.load || qi.callbacks.push(callback));
          callback && (qi.load && callback());
        } else {
          q.push({
            urls: _urls,
            callbacks: callback ? [callback] : [],
            load: false
          });
          for (i = 0; i < val.length; i++) {
            node = null, url = val[i];
            if (s[url] === undefined) {
              (type === 'js' ) && (node = createNode('script', { src: url }));
              (type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
              if (node) {
                node.onload = (function(type, url) {
                  return function() {
                    end(type, url);
                  };
                })(type, url);
                (doc.head || doc.body).appendChild(node);
                s[url] = false;
              }
            }
          }
        }
      }
    };
    return {
      js: function(url, callback) {
        load('js', url, callback);
      },
      css: function(url, callback) {
        load('css', url, callback);
      }
    };
  })(this.document);
})();
</script><script>
  (function() {
    var TEXT_VARIABLES = {
      version: '2.2.6',
      sources: {
        font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
        jquery: '/assets/js/jquery.min.js',
        leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
        chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
        gitalk: {
          js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
          css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
        },
        valine: 'https://unpkg.com/valine/dist/Valine.min.js',
        mathjax: 'https://cdn.bootcss.com/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_CHTML',
        mermaid: 'https://cdn.bootcss.com/mermaid/8.0.0-rc.8/mermaid.min.js'
      },
      site: {
        toc: {
          selectors: 'h1,h2,h3'
        }
      },
      paths: {
        search_js: '/assets/search.js'
      }
    };
    window.TEXT_VARIABLES = TEXT_VARIABLES;
  })();
</script>
</head>
  <body>
    <div class="root" data-is-touch="false">
      <div class="layout--page js-page-root"><div class="page__main js-page-main page__viewport hide-footer has-aside cell cell--auto">

      <div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
      <div class="header__title">
        <div class="header__brand"><?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   sodipodi:docname="yannick-white.svg"
   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
   id="svg2"
   preserveAspectRatio="xMidYMid meet"
   viewBox="0 0 53.000000 64.000000"
   height="64.000000pt"
   width="53.000000pt"
   version="1.0">
  <defs
     id="defs12" />
  <sodipodi:namedview
     inkscape:document-rotation="0"
     inkscape:current-layer="svg2"
     inkscape:window-maximized="0"
     inkscape:window-y="322"
     inkscape:window-x="304"
     inkscape:cy="39.661017"
     inkscape:cx="-28.739407"
     inkscape:zoom="2.95"
     showgrid="false"
     id="namedview10"
     inkscape:window-height="625"
     inkscape:window-width="1226"
     inkscape:pageshadow="2"
     inkscape:pageopacity="0"
     guidetolerance="10"
     gridtolerance="10"
     objecttolerance="10"
     borderopacity="1"
     bordercolor="#666666"
     pagecolor="#ffffff" />
  <metadata
     id="metadata4">
Created by potrace 1.13, written by Peter Selinger 2001-2015
<rdf:RDF>
  <cc:Work
     rdf:about="">
    <dc:format>image/svg+xml</dc:format>
    <dc:type
       rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
    <dc:title />
  </cc:Work>
</rdf:RDF>
</metadata>
  <g
     style="fill:#ffffff;fill-opacity:1"
     id="g6"
     stroke="none"
     fill="#000000"
     transform="matrix(0.1,0,0,-0.1,0,64)">
    <path
       style="fill:#ffffff;fill-opacity:1"
       id="path8"
       d="M 115,539 C 68,487 46,436 59,411 c 12,-21 93,-36 138,-25 26,7 27,6 13,-12 -8,-10 -17,-21 -20,-24 -26,-26 -92,-169 -94,-204 -1,-23 6,-33 32,-49 39,-23 52,-14 52,38 0,45 53,149 89,174 38,28 39,20 2,-55 -42,-86 -45,-101 -22,-107 24,-6 32,0 58,43 12,19 38,51 58,70 38,37 38,29 -2,-45 -27,-52 -56,-152 -48,-165 4,-7 22,3 46,25 21,19 44,35 49,35 6,0 10,5 10,10 0,6 -9,10 -20,10 -11,0 -20,4 -20,8 0,5 18,54 40,111 22,56 40,107 40,112 0,21 -22,5 -89,-63 -39,-40 -71,-68 -71,-63 0,4 8,32 17,61 9,30 14,57 10,61 -8,7 -38,-7 -77,-34 -29,-22 -22,-8 28,54 37,46 72,69 145,97 41,15 47,21 47,46 0,57 -44,52 -118,-15 -58,-52 -123,-84 -169,-85 -26,0 -33,4 -33,20 0,10 10,25 23,31 36,18 67,51 67,70 0,16 -44,39 -75,39 -7,0 -29,-18 -50,-41 z" />
  </g>
</svg>
<a title="Expérimentations et tests
" href="/">Site Yann</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
            <!-- Champ de recherche -->
					<div id="searchbox" class="search search--dark" style="visibility: visible">
					  <div class="main">
					    <div class="search__header"></div>
					    <div class="search-bar">
					      <div class="search-box js-search-box">
					        <div class="search-box__icon-search"><i class="fas fa-search"></i></div>
					        <input id="search-input" type="text" />
					        <!-- <div class="search-box__icon-clear js-icon-clear">
					          <a><i class="fas fa-times"></i></a>
					        </div> -->
					      </div>
					    </div>
					    
					  </div>
					</div>
					<!-- Script pointing to search-script.js -->
					<script>/*!
  * Simple-Jekyll-Search
  * Copyright 2015-2020, Christian Fei
  * Licensed under the MIT License.
  */
  
!function(){"use strict";var i={compile:function(r){return o.template.replace(o.pattern,function(t,e){var n=o.middleware(e,r[e],o.template);return void 0!==n?n:r[e]||t})},setOptions:function(t){o.pattern=t.pattern||o.pattern,o.template=t.template||o.template,"function"==typeof t.middleware&&(o.middleware=t.middleware)}},o={};o.pattern=/\{(.*?)\}/g,o.template="",o.middleware=function(){};var n=function(t,e){var n=e.length,r=t.length;if(n<r)return!1;if(r===n)return t===e;t:for(var i=0,o=0;i<r;i++){for(var u=t.charCodeAt(i);o<n;)if(e.charCodeAt(o++)===u)continue t;return!1}return!0},e=new function(){this.matches=function(t,e){return n(e.toLowerCase(),t.toLowerCase())}};var r=new function(){this.matches=function(e,t){return!!e&&(e=e.trim().toLowerCase(),(t=t.trim().toLowerCase()).split(" ").filter(function(t){return 0<=e.indexOf(t)}).length===t.split(" ").length)}};var u={put:function(t){if(f(t))return p(t);if(function(t){return Boolean(t)&&"[object Array]"===Object.prototype.toString.call(t)}(t))return function(t){var e=[];l();for(var n=0,r=t.length;n<r;n++)f(t[n])&&e.push(p(t[n]));return e}(t);return undefined},clear:l,search:function(t){return t?function(t,e,n,r){for(var i=[],o=0;o<t.length&&i.length<r.limit;o++){var u=function(t,e,n,r){for(var i in t)if(!function(t,e){for(var n=!1,r=0,i=(e=e||[]).length;r<i;r++){var o=e[r];!n&&new RegExp(t).test(o)&&(n=!0)}return n}(t[i],r.exclude)&&n.matches(t[i],e))return t}(t[o],e,n,r);u&&i.push(u)}return i}(s,t,c.searchStrategy,c).sort(c.sort):[]},setOptions:function(t){(c=t||{}).fuzzy=t.fuzzy||!1,c.limit=t.limit||10,c.searchStrategy=t.fuzzy?e:r,c.sort=t.sort||a}};function a(){return 0}var s=[],c={};function l(){return s.length=0,s}function f(t){return Boolean(t)&&"[object Object]"===Object.prototype.toString.call(t)}function p(t){return s.push(t),s}c.fuzzy=!1,c.limit=10,c.searchStrategy=c.fuzzy?e:r,c.sort=a;var d={load:function(t,e){var n=window.XMLHttpRequest?new window.XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");n.open("GET",t,!0),n.onreadystatechange=function(e,n){return function(){if(4===e.readyState&&200===e.status)try{n(null,JSON.parse(e.responseText))}catch(t){n(t,null)}}}(n,e),n.send()}};var h={merge:function(t,e){var n={};for(var r in t)n[r]=t[r],"undefined"!=typeof e[r]&&(n[r]=e[r]);return n},isJSON:function(t){try{return t instanceof Object&&JSON.parse(JSON.stringify(t))?!0:!1}catch(e){return!1}}};var t,m,v,w;function y(t){u.put(t),m.searchInput.addEventListener("input",function(t){-1===[13,16,20,37,38,39,40,91].indexOf(t.which)&&(g(),z(t.target.value))})}function g(){m.resultsContainer.innerHTML=""}function O(t){m.resultsContainer.innerHTML+=t}function z(t){var e;(e=t)&&0<e.length&&(g(),function(t,e){var n=t.length;if(0===n)return O(m.noResultsText);for(var r=0;r<n;r++)t[r].query=e,O(i.compile(t[r]))}(u.search(t),t))}function S(t){throw new Error("SimpleJekyllSearch --- "+t)}t=window,m={searchInput:null,resultsContainer:null,json:[],success:Function.prototype,searchResultTemplate:'<li><a href="{url}" title="{desc}">{title}</a></li>',templateMiddleware:Function.prototype,sortMiddleware:function(){return 0},noResultsText:"No results found",limit:10,fuzzy:!1,exclude:[]},w=function j(t){if(!((e=t)&&"undefined"!=typeof e.required&&e.required instanceof Array))throw new Error("-- OptionsValidator: required options missing");var e;if(!(this instanceof j))return new j(t);var r=t.required;this.getRequiredOptions=function(){return r},this.validate=function(e){var n=[];return r.forEach(function(t){"undefined"==typeof e[t]&&n.push(t)}),n}}({required:v=["searchInput","resultsContainer","json"]}),t.SimpleJekyllSearch=function(t){var n;0<w.validate(t).length&&S("You must specify the following required options: "+v),m=h.merge(m,t),i.setOptions({template:m.searchResultTemplate,middleware:m.templateMiddleware}),u.setOptions({fuzzy:m.fuzzy,limit:m.limit,sort:m.sortMiddleware}),h.isJSON(m.json)?y(m.json):(n=m.json,d.load(n,function(t,e){t&&S("failed to get JSON ("+n+")"),y(e)}));var e={search:z};return"function"==typeof m.success&&m.success.call(e),e}}();
</script>
					
					<!-- Configuration -->
					<script>
					SimpleJekyllSearch({
					  searchInput: document.getElementById('search-input'),
					  resultsContainer: document.getElementById('results-container'),
					  json: '/search.json',
					  //searchResultTemplate: '<li><a href="https://static.cinay.eu{url}">{date}&nbsp;{title}</a></li>'
					  searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
					})
					</script>
            <!-- Fin déclaration champ de recherche --></div><nav class="navigation">
        <ul><li class="navigation__item"><a href="/archive.html">Archives</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
      </nav></div>
  </header>

</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">

              <div class="col-aside d-print-none js-col-aside"><aside class="page__aside js-page-aside"><div class="toc-aside js-toc-root"></div>
</aside></div>

              <div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1>Nginx personnalisation des pages d'erreur</h1></header></div><meta itemprop="headline" content="Nginx personnalisation des pages d'erreur"><div class="article__info clearfix"><ul class="left-col menu"><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=nginx">nginx</a>
            </li></ul><ul class="right-col menu"><li>
            <i class="far fa-calendar-alt"></i>&nbsp;<span title="Création">21&nbsp;déc.&nbsp;&nbsp;2019</span></li></ul></div><meta itemprop="author" content="Yann M"/><meta itemprop="datePublished" content="2019-12-21T00:00:00+01:00">
    <meta itemprop="keywords" content="nginx"><div class="js-article-content"><div class="layout--article"><!-- start custom article top snippet -->
<style>
#myBtn {
  display: none;
  position: fixed;
  bottom: 20px;
  right: 110px;
  z-index: 99;
  font-size: 18px;
  border: none;
  outline: none;
  background-color: #0000;
  color: white;
  cursor: pointer;
  padding: 15px;
  border-radius: 4px;
}

#myBtn:hover {
  background-color: #555;
}
</style>

<button onclick="topFunction()" id="myBtn" title="Haut de page"><img src="data:image/png;base64,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"></button>

<script>
//Get the button
var mybutton = document.getElementById("myBtn");

// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};

function scrollFunction() {
  if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
    mybutton.style.display = "block";
  } else {
    mybutton.style.display = "none";
  }
}

// When the user clicks on the button, scroll to the top of the document
function topFunction() {
  document.body.scrollTop = 0;
  document.documentElement.scrollTop = 0;
}
</script>


<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><h2 id="configurer-nginx-pour-utiliser-des-pages-derreur-personnalisées">Configurer Nginx pour utiliser des pages d’erreur personnalisées</h2>

<p><img src="/images/nginx-logo.png" alt="" /></p>

<h3 id="introduction">Introduction</h3>

<p>Nginx est un serveur Web haute performance capable de servir du contenu avec flexibilité et puissance. Lors de la conception de vos pages Web, il est souvent utile de personnaliser chaque élément de contenu que vos utilisateurs verront. Cela inclut les pages d’erreur pour quand ils demandent du contenu qui n’est pas disponible.</p>

<h3 id="création-de-vos-pages-derreur-personnalisées">Création de vos pages d’erreur personnalisées</h3>

<p>Nous mettrons nos pages d’erreur personnalisées dans le <strong>/usr/share/nginx/html</strong> où Nginx définit sa racine de document par défaut. Nous créerons une page pour les erreurs 404 appelée <strong>custom_404.html</strong> et une autre pour les erreurs générales de niveau 500 appelée <strong>custom_50x.html</strong><br />
Vous pouvez utiliser les lignes suivantes si vous ne faites que tester. Sinon, mettez votre propre contenu dans ces emplacements:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "&lt;h1 style='color:red'&gt;Error 404: Not found :-(&lt;/h1&gt;" | sudo tee /usr/share/nginx/html/custom_404.html
echo "&lt;p&gt;I have no idea where that file is, sorry.  Are you sure you typed in the correct URL?&lt;/p&gt;" | sudo tee -a /usr/share/nginx/html/custom_404.html
echo "&lt;h1&gt;Oops! Something went wrong...&lt;/h1&gt;" | sudo tee /usr/share/nginx/html/custom_50x.html
echo "&lt;p&gt;We seem to be having some technical difficulties. Hang tight.&lt;/p&gt;" | sudo tee -a /usr/share/nginx/html/custom_50x.html
</code></pre></div></div>

<p>Nous avons maintenant deux pages d’erreur personnalisées que nous pouvons diffuser lorsque les demandes des clients entraînent des erreurs différentes.</p>

<h3 id="configuration-de-nginx-pour-utiliser-vos-pages-derreur">Configuration de Nginx pour utiliser vos pages d’erreur</h3>

<p>Maintenant, nous devons simplement dire à Nginx qu’il devrait utiliser ces pages chaque fois que les conditions d’erreur correctes se produisent. Ouvrez le fichier de blocage du serveur dans le répertoire /etc/nginx/sites-enabled que vous souhaitez configurer. Nous utiliserons le fichier de blocage de serveur par default appelé default , mais vous devez ajuster vos propres blocs de serveur si vous utilisez un fichier non par défaut:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/nginx/sites-enabled/default
</code></pre></div></div>

<p>Nous pouvons maintenant pointer Nginx vers nos pages d’erreur personnalisées.</p>

<h3 id="diriger-les-erreurs-404-vers-la-page-404-personnalisée">Diriger les erreurs 404 vers la page 404 personnalisée</h3>

<p>Utilisez la directive error_page pour que lorsqu’une erreur 404 se produit (lorsqu’un fichier demandé n’est pas trouvé), la page personnalisée que vous avez créée soit servie. Nous allons créer un bloc d’emplacement pour le fichier, où nous pouvons nous assurer que la racine correspond à l’emplacement de notre système de fichiers et que le fichier est uniquement accessible via les redirections Nginx internes (non directement demandables par les clients):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/nginx/sites-enabled/default
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        . . .

        error_page 404 /custom_404.html;
        location = /custom_404.html {
                root /usr/share/nginx/html;
                internal;
        }
}
</code></pre></div></div>

<p>Habituellement, nous n’aurions pas à définir la root dans le nouveau bloc d’emplacement car elle correspond à la racine dans le bloc serveur. Cependant, nous sommes explicites ici afin que nos pages d’erreur soient servies même si nous déplaçons notre contenu Web normal et la racine du document associé vers un emplacement différent.</p>

<h3 id="diriger-les-erreurs-de-niveau-500-vers-la-page-50x-personnalisée">Diriger les erreurs de niveau 500 vers la page 50x personnalisée</h3>

<p>Ensuite, nous pouvons ajouter les directives pour nous assurer que lorsque Nginx rencontre des erreurs de niveau 500 (problèmes liés au serveur), il servira l’autre page personnalisée que nous avons créée. Cela suivra exactement la même formule que nous avons utilisée dans la dernière section. Cette fois, nous avons défini plusieurs erreurs de niveau 500 pour utiliser toutes la page custom_50x.html :</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/nginx/sites-enabled/default
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        . . .

        error_page 404 /custom_404.html;
        location = /custom_404.html {
                root /usr/share/nginx/html;
                internal;
        }

        error_page 500 502 503 504 /custom_50x.html;
        location = /custom_50x.html {
                root /usr/share/nginx/html;
                internal;
        }

        location /testing {
                fastcgi_pass unix:/does/not/exist;
        }
}
</code></pre></div></div>

<p>En bas, nous avons également ajouté une passe fictive FastCGI afin que nous puissions tester notre page d’erreur de niveau 500 . Cela ne fonctionnera pas correctement car le backend n’existe pas. Demander une page ici nous permettra de tester que les erreurs de niveau 500 servent notre page personnalisée.</p>

<p>Enregistrez et fermez le fichier lorsque vous avez terminé.</p>

<h3 id="redémarrer-nginx-et-tester-vos-pages">Redémarrer Nginx et tester vos pages</h3>

<p>Testez la syntaxe de votre fichier de configuration en tapant:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  sudo nginx -t
</code></pre></div></div>

<p>Si des erreurs ont été signalées, corrigez-les avant de continuer. Lorsqu’aucune erreur de syntaxe n’est renvoyée, redémarrez Nginx en tapant:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  sudo service nginx restart
</code></pre></div></div>

<p>Maintenant, lorsque vous allez sur le domaine ou l’adresse IP de votre serveur et demandez un fichier inexistant, vous devriez voir la page 404 que nous avons configurée:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://server_domain_or_IP/thiswillerror 
</code></pre></div></div>

<p><img src="/images/custom_404.png" alt="nginx custom 404" /></p>

<p>Lorsque vous vous rendrez à l’emplacement que nous avons configuré pour le pass FastCGI, nous recevrons une erreur 502 Bad Gateway avec notre page personnalisée de niveau 500:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://server_domain_or_IP/testing
</code></pre></div></div>

<p><img src="/images/custom_50x.png" alt="nginx custom 50x" /></p>

<p>Vous pouvez maintenant revenir en arrière et supprimer le faux emplacement de passe FastCGI de votre configuration Nginx.</p>

<h3 id="conclusion">Conclusion</h3>

<p>Vous devez maintenant diffuser des pages d’erreur personnalisées pour votre site. Il s’agit d’un moyen simple de personnaliser l’expérience de vos utilisateurs même lorsqu’ils rencontrent des problèmes. Une suggestion pour ces pages est d’inclure des liens vers des endroits où ils peuvent aller pour obtenir de l’aide ou plus d’informations. Si vous procédez ainsi, assurez-vous que les destinations des liens sont accessibles même lorsque les erreurs associées se produisent.</p>

</div><section class="article__sharing d-print-none"></section><div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-12-21T00:00:00+01:00"><!-- start custom article footer snippet -->

<!-- end custom article footer snippet -->
<!--
  <div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>

&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2019/12/19/Grub.html">Grub "Configure GRUB2 Boot Loader settings", clavier FR et un mot de passe</a></div><div class="next"><span>SUIVANT</span><a href="/2019/12/23/Blog-statique-jekyll-Yunohost-cinay.xyz.html">Blog statique de type jekyll sur site cinay.xyz</a></div></div></div>

</div>

<script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    $(function() {
      var $this ,$scroll;
      var $articleContent = $('.js-article-content');
      var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
      var scroll = hasSidebar ? '.js-page-main' : 'html, body';
      $scroll = $(scroll);

      $articleContent.find('.highlight').each(function() {
        $this = $(this);
        $this.attr('data-lang', $this.find('code').attr('data-lang'));
      });
      $articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
        $this = $(this);
        $this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
      });
      $articleContent.on('click', '.anchor', function() {
        $scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
      });
    });
  });
})();
</script>
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
<!-- end custom main bottom snippet -->
</div>
            </div></div></div></div>
    </div><script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $body = $('body'), $window = $(window);
    var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
    var activeCount = 0;
    function modal(options) {
      var $root = this, visible, onChange, hideWhenWindowScroll = false;
      var scrollTop;
      function setOptions(options) {
        var _options = options || {};
        visible = _options.initialVisible === undefined ? false : show;
        onChange = _options.onChange;
        hideWhenWindowScroll = _options.hideWhenWindowScroll;
      }
      function init() {
        setState(visible);
      }
      function setState(isShow) {
        if (isShow === visible) {
          return;
        }
        visible = isShow;
        if (visible) {
          activeCount++;
          scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
          $root.addClass('modal--show');
          $pageMain.scrollTop(scrollTop);
          activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
          hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
          $window.on('keyup', handleKeyup);
        } else {
          activeCount > 0 && activeCount--;
          $root.removeClass('modal--show');
          $window.scrollTop(scrollTop);
          activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
          hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
          $window.off('keyup', handleKeyup);
        }
        onChange && onChange(visible);
      }
      function show() {
        setState(true);
      }
      function hide() {
        setState(false);
      }
      function handleKeyup(e) {
        // Char Code: 27  ESC
        if (e.which ===  27) {
          hide();
        }
      }
      setOptions(options);
      init();
      return {
        show: show,
        hide: hide,
        $el: $root
      };
    }
    $.fn.modal = modal;
  });
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    // search panel
    var search = (window.search || (window.search = {}));
    var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
      true : window.useDefaultSearchBox ;

    var $searchModal = $('.js-page-search-modal');
    var $searchToggle = $('.js-search-toggle');
    var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
    var modalVisible = false;
    search.searchModal = searchModal;

    var $searchBox = null;
    var $searchInput = null;
    var $searchClear = null;

    function getModalVisible() {
      return modalVisible;
    }
    search.getModalVisible = getModalVisible;

    function handleModalChange(visible) {
      modalVisible = visible;
      if (visible) {
        search.onShow && search.onShow();
        useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
      } else {
        search.onShow && search.onHide();
        useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
        setTimeout(function() {
          useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
          search.clear && search.clear();
          window.pageAsideAffix && window.pageAsideAffix.refresh();
        }, 400);
      }
    }

    $searchToggle.on('click', function() {
      modalVisible ? searchModal.hide() : searchModal.show();
    });
    // Char Code: 83  S, 191 /
    $(window).on('keyup', function(e) {
      if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
        modalVisible || searchModal.show();
      }
    });

    if (useDefaultSearchBox) {
      $searchBox = $('.js-search-box');
      $searchInput = $searchBox.children('input');
      $searchClear = $searchBox.children('.js-icon-clear');
      search.getSearchInput = function() {
        return $searchInput.get(0);
      };
      search.getVal = function() {
        return $searchInput.val();
      };
      search.setVal = function(val) {
        $searchInput.val(val);
      };

      $searchInput.on('focus', function() {
        $(this).addClass('focus');
      });
      $searchInput.on('blur', function() {
        $(this).removeClass('focus');
      });
      $searchInput.on('input', window.throttle(function() {
        var val = $(this).val();
        if (val === '' || typeof val !== 'string') {
          search.clear && search.clear();
        } else {
          $searchBox.addClass('not-empty');
          search.onInputNotEmpty && search.onInputNotEmpty(val);
        }
      }, 400));
      $searchClear.on('click', function() {
        $searchInput.val(''); $searchBox.removeClass('not-empty');
        search.clear && search.clear();
      });
    }
  });
})();
</script><div class="search search--dark">
  <div class="main">
    <div class="search__header">Recherche</div>
    <div class="search-bar">
      <div class="search-box js-search-box">
        <div class="search-box__icon-search"><i class="fas fa-search"></i></div>
        <input id="search-input" type="text" />
        <div class="search-box__icon-clear js-icon-clear">
          <a><i class="fas fa-times"></i></a>
        </div>
      </div>
      <button class="button button--theme-dark button--pill search__cancel js-search-toggle">
        Annuler</button>
    </div>
    <div id="results-container" class="search-result js-search-result"></div>
  </div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
  * Simple-Jekyll-Search
  * Copyright 2015-2020, Christian Fei
  * Licensed under the MIT License.
  */
  
!function(){"use strict";var i={compile:function(r){return o.template.replace(o.pattern,function(t,e){var n=o.middleware(e,r[e],o.template);return void 0!==n?n:r[e]||t})},setOptions:function(t){o.pattern=t.pattern||o.pattern,o.template=t.template||o.template,"function"==typeof t.middleware&&(o.middleware=t.middleware)}},o={};o.pattern=/\{(.*?)\}/g,o.template="",o.middleware=function(){};var n=function(t,e){var n=e.length,r=t.length;if(n<r)return!1;if(r===n)return t===e;t:for(var i=0,o=0;i<r;i++){for(var u=t.charCodeAt(i);o<n;)if(e.charCodeAt(o++)===u)continue t;return!1}return!0},e=new function(){this.matches=function(t,e){return n(e.toLowerCase(),t.toLowerCase())}};var r=new function(){this.matches=function(e,t){return!!e&&(e=e.trim().toLowerCase(),(t=t.trim().toLowerCase()).split(" ").filter(function(t){return 0<=e.indexOf(t)}).length===t.split(" ").length)}};var u={put:function(t){if(f(t))return p(t);if(function(t){return Boolean(t)&&"[object Array]"===Object.prototype.toString.call(t)}(t))return function(t){var e=[];l();for(var n=0,r=t.length;n<r;n++)f(t[n])&&e.push(p(t[n]));return e}(t);return undefined},clear:l,search:function(t){return t?function(t,e,n,r){for(var i=[],o=0;o<t.length&&i.length<r.limit;o++){var u=function(t,e,n,r){for(var i in t)if(!function(t,e){for(var n=!1,r=0,i=(e=e||[]).length;r<i;r++){var o=e[r];!n&&new RegExp(t).test(o)&&(n=!0)}return n}(t[i],r.exclude)&&n.matches(t[i],e))return t}(t[o],e,n,r);u&&i.push(u)}return i}(s,t,c.searchStrategy,c).sort(c.sort):[]},setOptions:function(t){(c=t||{}).fuzzy=t.fuzzy||!1,c.limit=t.limit||10,c.searchStrategy=t.fuzzy?e:r,c.sort=t.sort||a}};function a(){return 0}var s=[],c={};function l(){return s.length=0,s}function f(t){return Boolean(t)&&"[object Object]"===Object.prototype.toString.call(t)}function p(t){return s.push(t),s}c.fuzzy=!1,c.limit=10,c.searchStrategy=c.fuzzy?e:r,c.sort=a;var d={load:function(t,e){var n=window.XMLHttpRequest?new window.XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");n.open("GET",t,!0),n.onreadystatechange=function(e,n){return function(){if(4===e.readyState&&200===e.status)try{n(null,JSON.parse(e.responseText))}catch(t){n(t,null)}}}(n,e),n.send()}};var h={merge:function(t,e){var n={};for(var r in t)n[r]=t[r],"undefined"!=typeof e[r]&&(n[r]=e[r]);return n},isJSON:function(t){try{return t instanceof Object&&JSON.parse(JSON.stringify(t))?!0:!1}catch(e){return!1}}};var t,m,v,w;function y(t){u.put(t),m.searchInput.addEventListener("input",function(t){-1===[13,16,20,37,38,39,40,91].indexOf(t.which)&&(g(),z(t.target.value))})}function g(){m.resultsContainer.innerHTML=""}function O(t){m.resultsContainer.innerHTML+=t}function z(t){var e;(e=t)&&0<e.length&&(g(),function(t,e){var n=t.length;if(0===n)return O(m.noResultsText);for(var r=0;r<n;r++)t[r].query=e,O(i.compile(t[r]))}(u.search(t),t))}function S(t){throw new Error("SimpleJekyllSearch --- "+t)}t=window,m={searchInput:null,resultsContainer:null,json:[],success:Function.prototype,searchResultTemplate:'<li><a href="{url}" title="{desc}">{title}</a></li>',templateMiddleware:Function.prototype,sortMiddleware:function(){return 0},noResultsText:"No results found",limit:10,fuzzy:!1,exclude:[]},w=function j(t){if(!((e=t)&&"undefined"!=typeof e.required&&e.required instanceof Array))throw new Error("-- OptionsValidator: required options missing");var e;if(!(this instanceof j))return new j(t);var r=t.required;this.getRequiredOptions=function(){return r},this.validate=function(e){var n=[];return r.forEach(function(t){"undefined"==typeof e[t]&&n.push(t)}),n}}({required:v=["searchInput","resultsContainer","json"]}),t.SimpleJekyllSearch=function(t){var n;0<w.validate(t).length&&S("You must specify the following required options: "+v),m=h.merge(m,t),i.setOptions({template:m.searchResultTemplate,middleware:m.templateMiddleware}),u.setOptions({fuzzy:m.fuzzy,limit:m.limit,sort:m.sortMiddleware}),h.isJSON(m.json)?y(m.json):(n=m.json,d.load(n,function(t,e){t&&S("failed to get JSON ("+n+")"),y(e)}));var e={search:z};return"function"==typeof m.success&&m.success.call(e),e}}();
</script>

<!-- Configuration -->
<script>
SimpleJekyllSearch({
  searchInput: document.getElementById('search-input'),
  resultsContainer: document.getElementById('results-container'),
  json: '/search.json',
  //searchResultTemplate: '<li><a href="https://static.cinay.eu{url}">{date}&nbsp;{title}</a></li>'
  searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
})
</script>

</div></div>


<script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function scrollToAnchor(anchor, duration, callback) {
      var $root = this;
      $root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
        window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
        callback && callback();
      });
    }
    $.fn.scrollToAnchor = scrollToAnchor;
  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function affix(options) {
      var $root = this, $window = $(window), $scrollTarget, $scroll,
        offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
        rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
        hasInit = false, curState;

      function setOptions(options) {
        var _options = options || {};
        _options.offsetBottom && (offsetBottom = _options.offsetBottom);
        _options.scrollTarget && (scrollTarget = _options.scrollTarget);
        _options.scroll && (scroll = _options.scroll);
        _options.disabled !== undefined && (disabled = _options.disabled);
        $scrollTarget = $(scrollTarget);
        isOverallScroller = window.isOverallScroller($scrollTarget[0]);
        $scroll = $(scroll);
      }
      function preCalc() {
        top();
        rootHeight = $root.outerHeight();
        rootTop = $root.offset().top + (isOverallScroller ? 0 :  $scrollTarget.scrollTop());
        rootLeft = $root.offset().left;
      }
      function calc(needPreCalc) {
        needPreCalc && preCalc();
        scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
        rootBottomTop = scrollBottom - rootTop;
      }
      function top() {
        if (curState !== 'top') {
          $root.removeClass('fixed').css({
            left: 0,
            top: 0
          });
          curState = 'top';
        }
      }
      function fixed() {
        if (curState !== 'fixed') {
          $root.addClass('fixed').css({
            left: rootLeft + 'px',
            top: 0
          });
          curState = 'fixed';
        }
      }
      function bottom() {
        if (curState !== 'bottom') {
          $root.removeClass('fixed').css({
            left: 0,
            top: rootBottomTop + 'px'
          });
          curState = 'bottom';
        }
      }
      function setState() {
        var scrollTop = $scrollTarget.scrollTop();
        if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
          fixed();
        } else if (scrollTop < rootTop) {
          top();
        } else {
          bottom();
        }
      }
      function init() {
        if(!hasInit) {
          var interval, timeout;
          calc(true); setState();
          // run calc every 100 millisecond
          interval = setInterval(function() {
            calc();
          }, 100);
          timeout = setTimeout(function() {
            clearInterval(interval);
          }, 45000);
          window.pageLoad.then(function() {
            setTimeout(function() {
              clearInterval(interval);
              clearTimeout(timeout);
            }, 3000);
          });
          $scrollTarget.on('scroll', function() {
            disabled || setState();
          });
          $window.on('resize', function() {
            disabled || (calc(true), setState());
          });
          hasInit = true;
        }
      }

      setOptions(options);
      if (!disabled) {
        init();
      }
      $window.on('resize', window.throttle(function() {
        init();
      }, 200));
      return {
        setOptions: setOptions,
        refresh: function() {
          calc(true, { animation: false }); setState();
        }
      };
    }
    $.fn.affix = affix;
  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function toc(options) {
      var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
        selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
        headingsPos, scrolling = false, hasRendered = false, hasInit = false;

      function setOptions(options) {
        var _options = options || {};
        _options.selectors && (selectors = _options.selectors);
        _options.container && (container = _options.container);
        _options.scrollTarget && (scrollTarget = _options.scrollTarget);
        _options.scroller && (scroller = _options.scroller);
        _options.disabled !== undefined && (disabled = _options.disabled);
        $headings = $(container).find(selectors).filter('[id]');
        $scrollTarget = $(scrollTarget);
        $scroller = $(scroller);
      }
      function calc() {
        headingsPos = [];
        $headings.each(function() {
          headingsPos.push(Math.floor($(this).position().top));
        });
      }
      function setState(element, disabled) {
        var scrollTop = $scrollTarget.scrollTop(), i;
        if (disabled || !headingsPos || headingsPos.length < 1) { return; }
        if (element) {
          $activeCur = element;
        } else {
          for (i = 0; i < headingsPos.length; i++) {
            if (scrollTop >= headingsPos[i]) {
              $activeCur = $tocLi.eq(i);
            } else {
              $activeCur || ($activeCur = $tocLi.eq(i));
              break;
            }
          }
        }
        $activeLast && $activeLast.removeClass('active');
        ($activeLast = $activeCur).addClass('active');
      }
      function render() {
        if(!hasRendered) {
          $root.append($tocUl);
          $headings.each(function() {
            var $this = $(this);
            $tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
              .append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
          });
          $tocLi = $tocUl.children('li');
          $tocUl.on('click', 'a', function(e) {
            e.preventDefault();
            var $this = $(this);
            scrolling = true;
            setState($this.parent());
            $scroller.scrollToAnchor($this.attr('href'), 400, function() {
              scrolling = false;
            });
          });
        }
        hasRendered = true;
      }
      function init() {
        var interval, timeout;
        if(!hasInit) {
          render(); calc(); setState(null, scrolling);
          // run calc every 100 millisecond
          interval = setInterval(function() {
            calc();
          }, 100);
          timeout = setTimeout(function() {
            clearInterval(interval);
          }, 45000);
          window.pageLoad.then(function() {
            setTimeout(function() {
              clearInterval(interval);
              clearTimeout(timeout);
            }, 3000);
          });
          $scrollTarget.on('scroll', function() {
            disabled || setState(null, scrolling);
          });
          $window.on('resize', window.throttle(function() {
            if (!disabled) {
              render(); calc(); setState(null, scrolling);
            }
          }, 100));
        }
        hasInit = true;
      }

      setOptions(options);
      if (!disabled) {
        init();
      }
      $window.on('resize', window.throttle(function() {
        init();
      }, 200));
      return {
        setOptions: setOptions
      };
    }
    $.fn.toc = toc;
  });
})();
/*(function () {

})();*/
</script><script>
  /* toc must before affix, since affix need to konw toc' height. */(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $window = $(window);
    var $articleContent = $('.js-article-content');
    var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
    var toc;
    var tocDisabled = false;
    var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
    var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;

    function disabled() {
      return $col2.css('display') === 'none' || !hasToc;
    }

    tocDisabled = disabled();

    toc = $tocRoot.toc({
      selectors: TOC_SELECTOR,
      container: $articleContent,
      scrollTarget: hasSidebar ? '.js-page-main' : null,
      scroller: hasSidebar ? '.js-page-main' : null,
      disabled: tocDisabled
    });

    $window.on('resize', window.throttle(function() {
      tocDisabled = disabled();
      toc && toc.setOptions({
        disabled: tocDisabled
      });
    }, 100));

  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $window = $(window), $pageFooter = $('.js-page-footer');
    var $pageAside = $('.js-page-aside');
    var affix;
    var tocDisabled = false;
    var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');

    affix = $pageAside.affix({
      offsetBottom: $pageFooter.outerHeight(),
      scrollTarget: hasSidebar ? '.js-page-main' : null,
      scroller: hasSidebar ? '.js-page-main' : null,
      scroll: hasSidebar ? $('.js-page-main').children() : null,
      disabled: tocDisabled
    });

    $window.on('resize', window.throttle(function() {
      affix && affix.setOptions({
        disabled: tocDisabled
      });
    }, 100));

    window.pageAsideAffix = affix;
  });
})();
</script>
    </div>
    <script>(function () {
  var $root = document.getElementsByClassName('root')[0];
  if (window.hasEvent('touchstart')) {
    $root.dataset.isTouch = true;
    document.addEventListener('touchstart', function(){}, false);
  }
})();
</script>
  </body>
</html>

search.html situé sous la racine /srv/basicblog/ du site statique dans le dossier _layouts

---
layout: default
---
<div class="search">
	<!DOCTYPE html><html lang="fr">
  <head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>Nginx personnalisation des pages d'erreur - Site Yann</title>

<meta name="description" content="Configurer Nginx pour utiliser des pages d’erreur personnaliséesIntroductionNginx est un serveur Web haute performance capable de servir du contenu avec flex...">
<link rel="canonical" href="https://static.cinay.eu/2019/12/21/Nginx-personnalisation-page-erreur.html"><link rel="alternate" type="application/rss+xml" title="Site Yann" href="/feed.xml"><!-- start favicons snippet, use https://realfavicongenerator.net/ --><link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16x16.png"><link rel="manifest" href="/assets/site.webmanifest"><link rel="mask-icon" href="/assets/safari-pinned-tab.svg" color="#fc4d50"><link rel="shortcut icon" href="/assets/favicon.ico">

<meta name="msapplication-TileColor" content="#ffc40d"><meta name="msapplication-config" content="/assets/browserconfig.xml">

<meta name="theme-color" content="#ffffff">
<!-- end favicons snippet --><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets -->
<!-- end custom head snippets -->
<script>(function() {
  window.isArray = function(val) {
    return Object.prototype.toString.call(val) === '[object Array]';
  };
  window.isString = function(val) {
    return typeof val === 'string';
  };

  window.hasEvent = function(event) {
    return 'on'.concat(event) in window.document;
  };

  window.isOverallScroller = function(node) {
    return node === document.documentElement || node === document.body || node === window;
  };

  window.isFormElement = function(node) {
    var tagName = node.tagName;
    return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
  };

  window.pageLoad = (function () {
    var loaded = false, cbs = [];
    window.addEventListener('load', function () {
      var i;
      loaded = true;
      if (cbs.length > 0) {
        for (i = 0; i < cbs.length; i++) {
          cbs[i]();
        }
      }
    });
    return {
      then: function(cb) {
        cb && (loaded ? cb() : (cbs.push(cb)));
      }
    };
  })();
})();
(function() {
  window.throttle = function(func, wait) {
    var args, result, thisArg, timeoutId, lastCalled = 0;

    function trailingCall() {
      lastCalled = new Date;
      timeoutId = null;
      result = func.apply(thisArg, args);
    }
    return function() {
      var now = new Date,
        remaining = wait - (now - lastCalled);

      args = arguments;
      thisArg = this;

      if (remaining <= 0) {
        clearTimeout(timeoutId);
        timeoutId = null;
        lastCalled = now;
        result = func.apply(thisArg, args);
      } else if (!timeoutId) {
        timeoutId = setTimeout(trailingCall, remaining);
      }
      return result;
    };
  };
})();
(function() {
  var Set = (function() {
    var add = function(item) {
      var i, data = this._data;
      for (i = 0; i < data.length; i++) {
        if (data[i] === item) {
          return;
        }
      }
      this.size ++;
      data.push(item);
      return data;
    };

    var Set = function(data) {
      this.size = 0;
      this._data = [];
      var i;
      if (data.length > 0) {
        for (i = 0; i < data.length; i++) {
          add.call(this, data[i]);
        }
      }
    };
    Set.prototype.add = add;
    Set.prototype.get = function(index) { return this._data[index]; };
    Set.prototype.has = function(item) {
      var i, data = this._data;
      for (i = 0; i < data.length; i++) {
        if (this.get(i) === item) {
          return true;
        }
      }
      return false;
    };
    Set.prototype.is = function(map) {
      if (map._data.length !== this._data.length) { return false; }
      var i, j, flag, tData = this._data, mData = map._data;
      for (i = 0; i < tData.length; i++) {
        for (flag = false, j = 0; j < mData.length; j++) {
          if (tData[i] === mData[j]) {
            flag = true;
            break;
          }
        }
        if (!flag) { return false; }
      }
      return true;
    };
    Set.prototype.values = function() {
      return this._data;
    };
    return Set;
  })();

  window.Lazyload = (function(doc) {
    var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
    var createNode = function(name, attrs) {
      var node = doc.createElement(name), attr;
      for (attr in attrs) {
        if (attrs.hasOwnProperty(attr)) {
          node.setAttribute(attr, attrs[attr]);
        }
      }
      return node;
    };
    var end = function(type, url) {
      var s, q, qi, cbs, i, j, cur, val, flag;
      if (type === 'js' || type ==='css') {
        s = sources[type], q = queue[type];
        s[url] = true;
        for (i = 0; i < q.length; i++) {
          cur = q[i];
          if (cur.urls.has(url)) {
            qi = cur, val = qi.urls.values();
            qi && (cbs = qi.callbacks);
            for (flag = true, j = 0; j < val.length; j++) {
              cur = val[j];
              if (!s[cur]) {
                flag = false;
              }
            }
            if (flag && cbs && cbs.length > 0) {
              for (j = 0; j < cbs.length; j++) {
                cbs[j].call(context);
              }
              qi.load = true;
            }
          }
        }
      }
    };
    var load = function(type, urls, callback) {
      var s, q, qi, node, i, cur,
        _urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
      if (type === 'js' || type ==='css') {
        s = sources[type], q = queue[type];
        for (i = 0; i < q.length; i++) {
          cur = q[i];
          if (_urls.is(cur.urls)) {
            qi = cur;
            break;
          }
        }
        val = _urls.values();
        if (qi) {
          callback && (qi.load || qi.callbacks.push(callback));
          callback && (qi.load && callback());
        } else {
          q.push({
            urls: _urls,
            callbacks: callback ? [callback] : [],
            load: false
          });
          for (i = 0; i < val.length; i++) {
            node = null, url = val[i];
            if (s[url] === undefined) {
              (type === 'js' ) && (node = createNode('script', { src: url }));
              (type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
              if (node) {
                node.onload = (function(type, url) {
                  return function() {
                    end(type, url);
                  };
                })(type, url);
                (doc.head || doc.body).appendChild(node);
                s[url] = false;
              }
            }
          }
        }
      }
    };
    return {
      js: function(url, callback) {
        load('js', url, callback);
      },
      css: function(url, callback) {
        load('css', url, callback);
      }
    };
  })(this.document);
})();
</script><script>
  (function() {
    var TEXT_VARIABLES = {
      version: '2.2.6',
      sources: {
        font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
        jquery: '/assets/js/jquery.min.js',
        leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
        chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
        gitalk: {
          js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
          css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
        },
        valine: 'https://unpkg.com/valine/dist/Valine.min.js',
        mathjax: 'https://cdn.bootcss.com/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_CHTML',
        mermaid: 'https://cdn.bootcss.com/mermaid/8.0.0-rc.8/mermaid.min.js'
      },
      site: {
        toc: {
          selectors: 'h1,h2,h3'
        }
      },
      paths: {
        search_js: '/assets/search.js'
      }
    };
    window.TEXT_VARIABLES = TEXT_VARIABLES;
  })();
</script>
</head>
  <body>
    <div class="root" data-is-touch="false">
      <div class="layout--page js-page-root"><div class="page__main js-page-main page__viewport hide-footer has-aside cell cell--auto">

      <div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
      <div class="header__title">
        <div class="header__brand"><?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   sodipodi:docname="yannick-white.svg"
   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
   id="svg2"
   preserveAspectRatio="xMidYMid meet"
   viewBox="0 0 53.000000 64.000000"
   height="64.000000pt"
   width="53.000000pt"
   version="1.0">
  <defs
     id="defs12" />
  <sodipodi:namedview
     inkscape:document-rotation="0"
     inkscape:current-layer="svg2"
     inkscape:window-maximized="0"
     inkscape:window-y="322"
     inkscape:window-x="304"
     inkscape:cy="39.661017"
     inkscape:cx="-28.739407"
     inkscape:zoom="2.95"
     showgrid="false"
     id="namedview10"
     inkscape:window-height="625"
     inkscape:window-width="1226"
     inkscape:pageshadow="2"
     inkscape:pageopacity="0"
     guidetolerance="10"
     gridtolerance="10"
     objecttolerance="10"
     borderopacity="1"
     bordercolor="#666666"
     pagecolor="#ffffff" />
  <metadata
     id="metadata4">
Created by potrace 1.13, written by Peter Selinger 2001-2015
<rdf:RDF>
  <cc:Work
     rdf:about="">
    <dc:format>image/svg+xml</dc:format>
    <dc:type
       rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
    <dc:title />
  </cc:Work>
</rdf:RDF>
</metadata>
  <g
     style="fill:#ffffff;fill-opacity:1"
     id="g6"
     stroke="none"
     fill="#000000"
     transform="matrix(0.1,0,0,-0.1,0,64)">
    <path
       style="fill:#ffffff;fill-opacity:1"
       id="path8"
       d="M 115,539 C 68,487 46,436 59,411 c 12,-21 93,-36 138,-25 26,7 27,6 13,-12 -8,-10 -17,-21 -20,-24 -26,-26 -92,-169 -94,-204 -1,-23 6,-33 32,-49 39,-23 52,-14 52,38 0,45 53,149 89,174 38,28 39,20 2,-55 -42,-86 -45,-101 -22,-107 24,-6 32,0 58,43 12,19 38,51 58,70 38,37 38,29 -2,-45 -27,-52 -56,-152 -48,-165 4,-7 22,3 46,25 21,19 44,35 49,35 6,0 10,5 10,10 0,6 -9,10 -20,10 -11,0 -20,4 -20,8 0,5 18,54 40,111 22,56 40,107 40,112 0,21 -22,5 -89,-63 -39,-40 -71,-68 -71,-63 0,4 8,32 17,61 9,30 14,57 10,61 -8,7 -38,-7 -77,-34 -29,-22 -22,-8 28,54 37,46 72,69 145,97 41,15 47,21 47,46 0,57 -44,52 -118,-15 -58,-52 -123,-84 -169,-85 -26,0 -33,4 -33,20 0,10 10,25 23,31 36,18 67,51 67,70 0,16 -44,39 -75,39 -7,0 -29,-18 -50,-41 z" />
  </g>
</svg>
<a title="Expérimentations et tests
" href="/">Site Yann</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
            <!-- Champ de recherche -->
					<div id="searchbox" class="search search--dark" style="visibility: visible">
					  <div class="main">
					    <div class="search__header"></div>
					    <div class="search-bar">
					      <div class="search-box js-search-box">
					        <div class="search-box__icon-search"><i class="fas fa-search"></i></div>
					        <input id="search-input" type="text" />
					        <!-- <div class="search-box__icon-clear js-icon-clear">
					          <a><i class="fas fa-times"></i></a>
					        </div> -->
					      </div>
					    </div>
					    
					  </div>
					</div>
					<!-- Script pointing to search-script.js -->
					<script>/*!
  * Simple-Jekyll-Search
  * Copyright 2015-2020, Christian Fei
  * Licensed under the MIT License.
  */
  
!function(){"use strict";var i={compile:function(r){return o.template.replace(o.pattern,function(t,e){var n=o.middleware(e,r[e],o.template);return void 0!==n?n:r[e]||t})},setOptions:function(t){o.pattern=t.pattern||o.pattern,o.template=t.template||o.template,"function"==typeof t.middleware&&(o.middleware=t.middleware)}},o={};o.pattern=/\{(.*?)\}/g,o.template="",o.middleware=function(){};var n=function(t,e){var n=e.length,r=t.length;if(n<r)return!1;if(r===n)return t===e;t:for(var i=0,o=0;i<r;i++){for(var u=t.charCodeAt(i);o<n;)if(e.charCodeAt(o++)===u)continue t;return!1}return!0},e=new function(){this.matches=function(t,e){return n(e.toLowerCase(),t.toLowerCase())}};var r=new function(){this.matches=function(e,t){return!!e&&(e=e.trim().toLowerCase(),(t=t.trim().toLowerCase()).split(" ").filter(function(t){return 0<=e.indexOf(t)}).length===t.split(" ").length)}};var u={put:function(t){if(f(t))return p(t);if(function(t){return Boolean(t)&&"[object Array]"===Object.prototype.toString.call(t)}(t))return function(t){var e=[];l();for(var n=0,r=t.length;n<r;n++)f(t[n])&&e.push(p(t[n]));return e}(t);return undefined},clear:l,search:function(t){return t?function(t,e,n,r){for(var i=[],o=0;o<t.length&&i.length<r.limit;o++){var u=function(t,e,n,r){for(var i in t)if(!function(t,e){for(var n=!1,r=0,i=(e=e||[]).length;r<i;r++){var o=e[r];!n&&new RegExp(t).test(o)&&(n=!0)}return n}(t[i],r.exclude)&&n.matches(t[i],e))return t}(t[o],e,n,r);u&&i.push(u)}return i}(s,t,c.searchStrategy,c).sort(c.sort):[]},setOptions:function(t){(c=t||{}).fuzzy=t.fuzzy||!1,c.limit=t.limit||10,c.searchStrategy=t.fuzzy?e:r,c.sort=t.sort||a}};function a(){return 0}var s=[],c={};function l(){return s.length=0,s}function f(t){return Boolean(t)&&"[object Object]"===Object.prototype.toString.call(t)}function p(t){return s.push(t),s}c.fuzzy=!1,c.limit=10,c.searchStrategy=c.fuzzy?e:r,c.sort=a;var d={load:function(t,e){var n=window.XMLHttpRequest?new window.XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");n.open("GET",t,!0),n.onreadystatechange=function(e,n){return function(){if(4===e.readyState&&200===e.status)try{n(null,JSON.parse(e.responseText))}catch(t){n(t,null)}}}(n,e),n.send()}};var h={merge:function(t,e){var n={};for(var r in t)n[r]=t[r],"undefined"!=typeof e[r]&&(n[r]=e[r]);return n},isJSON:function(t){try{return t instanceof Object&&JSON.parse(JSON.stringify(t))?!0:!1}catch(e){return!1}}};var t,m,v,w;function y(t){u.put(t),m.searchInput.addEventListener("input",function(t){-1===[13,16,20,37,38,39,40,91].indexOf(t.which)&&(g(),z(t.target.value))})}function g(){m.resultsContainer.innerHTML=""}function O(t){m.resultsContainer.innerHTML+=t}function z(t){var e;(e=t)&&0<e.length&&(g(),function(t,e){var n=t.length;if(0===n)return O(m.noResultsText);for(var r=0;r<n;r++)t[r].query=e,O(i.compile(t[r]))}(u.search(t),t))}function S(t){throw new Error("SimpleJekyllSearch --- "+t)}t=window,m={searchInput:null,resultsContainer:null,json:[],success:Function.prototype,searchResultTemplate:'<li><a href="{url}" title="{desc}">{title}</a></li>',templateMiddleware:Function.prototype,sortMiddleware:function(){return 0},noResultsText:"No results found",limit:10,fuzzy:!1,exclude:[]},w=function j(t){if(!((e=t)&&"undefined"!=typeof e.required&&e.required instanceof Array))throw new Error("-- OptionsValidator: required options missing");var e;if(!(this instanceof j))return new j(t);var r=t.required;this.getRequiredOptions=function(){return r},this.validate=function(e){var n=[];return r.forEach(function(t){"undefined"==typeof e[t]&&n.push(t)}),n}}({required:v=["searchInput","resultsContainer","json"]}),t.SimpleJekyllSearch=function(t){var n;0<w.validate(t).length&&S("You must specify the following required options: "+v),m=h.merge(m,t),i.setOptions({template:m.searchResultTemplate,middleware:m.templateMiddleware}),u.setOptions({fuzzy:m.fuzzy,limit:m.limit,sort:m.sortMiddleware}),h.isJSON(m.json)?y(m.json):(n=m.json,d.load(n,function(t,e){t&&S("failed to get JSON ("+n+")"),y(e)}));var e={search:z};return"function"==typeof m.success&&m.success.call(e),e}}();
</script>
					
					<!-- Configuration -->
					<script>
					SimpleJekyllSearch({
					  searchInput: document.getElementById('search-input'),
					  resultsContainer: document.getElementById('results-container'),
					  json: '/search.json',
					  //searchResultTemplate: '<li><a href="https://static.cinay.eu{url}">{date}&nbsp;{title}</a></li>'
					  searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
					})
					</script>
            <!-- Fin déclaration champ de recherche --></div><nav class="navigation">
        <ul><li class="navigation__item"><a href="/archive.html">Archives</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
      </nav></div>
  </header>

</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">

              <div class="col-aside d-print-none js-col-aside"><aside class="page__aside js-page-aside"><div class="toc-aside js-toc-root"></div>
</aside></div>

              <div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1>Nginx personnalisation des pages d'erreur</h1></header></div><meta itemprop="headline" content="Nginx personnalisation des pages d'erreur"><div class="article__info clearfix"><ul class="left-col menu"><li>
              <a class="button button--secondary button--pill button--sm"
                href="/archive.html?tag=nginx">nginx</a>
            </li></ul><ul class="right-col menu"><li>
            <i class="far fa-calendar-alt"></i>&nbsp;<span title="Création">21&nbsp;déc.&nbsp;&nbsp;2019</span></li></ul></div><meta itemprop="author" content="Yann M"/><meta itemprop="datePublished" content="2019-12-21T00:00:00+01:00">
    <meta itemprop="keywords" content="nginx"><div class="js-article-content"><div class="layout--article"><!-- start custom article top snippet -->
<style>
#myBtn {
  display: none;
  position: fixed;
  bottom: 20px;
  right: 110px;
  z-index: 99;
  font-size: 18px;
  border: none;
  outline: none;
  background-color: #0000;
  color: white;
  cursor: pointer;
  padding: 15px;
  border-radius: 4px;
}

#myBtn:hover {
  background-color: #555;
}
</style>

<button onclick="topFunction()" id="myBtn" title="Haut de page"><img src="data:image/png;base64,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"></button>

<script>
//Get the button
var mybutton = document.getElementById("myBtn");

// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};

function scrollFunction() {
  if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
    mybutton.style.display = "block";
  } else {
    mybutton.style.display = "none";
  }
}

// When the user clicks on the button, scroll to the top of the document
function topFunction() {
  document.body.scrollTop = 0;
  document.documentElement.scrollTop = 0;
}
</script>


<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><h2 id="configurer-nginx-pour-utiliser-des-pages-derreur-personnalisées">Configurer Nginx pour utiliser des pages d’erreur personnalisées</h2>

<p><img src="/images/nginx-logo.png" alt="" /></p>

<h3 id="introduction">Introduction</h3>

<p>Nginx est un serveur Web haute performance capable de servir du contenu avec flexibilité et puissance. Lors de la conception de vos pages Web, il est souvent utile de personnaliser chaque élément de contenu que vos utilisateurs verront. Cela inclut les pages d’erreur pour quand ils demandent du contenu qui n’est pas disponible.</p>

<h3 id="création-de-vos-pages-derreur-personnalisées">Création de vos pages d’erreur personnalisées</h3>

<p>Nous mettrons nos pages d’erreur personnalisées dans le <strong>/usr/share/nginx/html</strong> où Nginx définit sa racine de document par défaut. Nous créerons une page pour les erreurs 404 appelée <strong>custom_404.html</strong> et une autre pour les erreurs générales de niveau 500 appelée <strong>custom_50x.html</strong><br />
Vous pouvez utiliser les lignes suivantes si vous ne faites que tester. Sinon, mettez votre propre contenu dans ces emplacements:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "&lt;h1 style='color:red'&gt;Error 404: Not found :-(&lt;/h1&gt;" | sudo tee /usr/share/nginx/html/custom_404.html
echo "&lt;p&gt;I have no idea where that file is, sorry.  Are you sure you typed in the correct URL?&lt;/p&gt;" | sudo tee -a /usr/share/nginx/html/custom_404.html
echo "&lt;h1&gt;Oops! Something went wrong...&lt;/h1&gt;" | sudo tee /usr/share/nginx/html/custom_50x.html
echo "&lt;p&gt;We seem to be having some technical difficulties. Hang tight.&lt;/p&gt;" | sudo tee -a /usr/share/nginx/html/custom_50x.html
</code></pre></div></div>

<p>Nous avons maintenant deux pages d’erreur personnalisées que nous pouvons diffuser lorsque les demandes des clients entraînent des erreurs différentes.</p>

<h3 id="configuration-de-nginx-pour-utiliser-vos-pages-derreur">Configuration de Nginx pour utiliser vos pages d’erreur</h3>

<p>Maintenant, nous devons simplement dire à Nginx qu’il devrait utiliser ces pages chaque fois que les conditions d’erreur correctes se produisent. Ouvrez le fichier de blocage du serveur dans le répertoire /etc/nginx/sites-enabled que vous souhaitez configurer. Nous utiliserons le fichier de blocage de serveur par default appelé default , mais vous devez ajuster vos propres blocs de serveur si vous utilisez un fichier non par défaut:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/nginx/sites-enabled/default
</code></pre></div></div>

<p>Nous pouvons maintenant pointer Nginx vers nos pages d’erreur personnalisées.</p>

<h3 id="diriger-les-erreurs-404-vers-la-page-404-personnalisée">Diriger les erreurs 404 vers la page 404 personnalisée</h3>

<p>Utilisez la directive error_page pour que lorsqu’une erreur 404 se produit (lorsqu’un fichier demandé n’est pas trouvé), la page personnalisée que vous avez créée soit servie. Nous allons créer un bloc d’emplacement pour le fichier, où nous pouvons nous assurer que la racine correspond à l’emplacement de notre système de fichiers et que le fichier est uniquement accessible via les redirections Nginx internes (non directement demandables par les clients):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/nginx/sites-enabled/default
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        . . .

        error_page 404 /custom_404.html;
        location = /custom_404.html {
                root /usr/share/nginx/html;
                internal;
        }
}
</code></pre></div></div>

<p>Habituellement, nous n’aurions pas à définir la root dans le nouveau bloc d’emplacement car elle correspond à la racine dans le bloc serveur. Cependant, nous sommes explicites ici afin que nos pages d’erreur soient servies même si nous déplaçons notre contenu Web normal et la racine du document associé vers un emplacement différent.</p>

<h3 id="diriger-les-erreurs-de-niveau-500-vers-la-page-50x-personnalisée">Diriger les erreurs de niveau 500 vers la page 50x personnalisée</h3>

<p>Ensuite, nous pouvons ajouter les directives pour nous assurer que lorsque Nginx rencontre des erreurs de niveau 500 (problèmes liés au serveur), il servira l’autre page personnalisée que nous avons créée. Cela suivra exactement la même formule que nous avons utilisée dans la dernière section. Cette fois, nous avons défini plusieurs erreurs de niveau 500 pour utiliser toutes la page custom_50x.html :</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/nginx/sites-enabled/default
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        . . .

        error_page 404 /custom_404.html;
        location = /custom_404.html {
                root /usr/share/nginx/html;
                internal;
        }

        error_page 500 502 503 504 /custom_50x.html;
        location = /custom_50x.html {
                root /usr/share/nginx/html;
                internal;
        }

        location /testing {
                fastcgi_pass unix:/does/not/exist;
        }
}
</code></pre></div></div>

<p>En bas, nous avons également ajouté une passe fictive FastCGI afin que nous puissions tester notre page d’erreur de niveau 500 . Cela ne fonctionnera pas correctement car le backend n’existe pas. Demander une page ici nous permettra de tester que les erreurs de niveau 500 servent notre page personnalisée.</p>

<p>Enregistrez et fermez le fichier lorsque vous avez terminé.</p>

<h3 id="redémarrer-nginx-et-tester-vos-pages">Redémarrer Nginx et tester vos pages</h3>

<p>Testez la syntaxe de votre fichier de configuration en tapant:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  sudo nginx -t
</code></pre></div></div>

<p>Si des erreurs ont été signalées, corrigez-les avant de continuer. Lorsqu’aucune erreur de syntaxe n’est renvoyée, redémarrez Nginx en tapant:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  sudo service nginx restart
</code></pre></div></div>

<p>Maintenant, lorsque vous allez sur le domaine ou l’adresse IP de votre serveur et demandez un fichier inexistant, vous devriez voir la page 404 que nous avons configurée:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://server_domain_or_IP/thiswillerror 
</code></pre></div></div>

<p><img src="/images/custom_404.png" alt="nginx custom 404" /></p>

<p>Lorsque vous vous rendrez à l’emplacement que nous avons configuré pour le pass FastCGI, nous recevrons une erreur 502 Bad Gateway avec notre page personnalisée de niveau 500:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://server_domain_or_IP/testing
</code></pre></div></div>

<p><img src="/images/custom_50x.png" alt="nginx custom 50x" /></p>

<p>Vous pouvez maintenant revenir en arrière et supprimer le faux emplacement de passe FastCGI de votre configuration Nginx.</p>

<h3 id="conclusion">Conclusion</h3>

<p>Vous devez maintenant diffuser des pages d’erreur personnalisées pour votre site. Il s’agit d’un moyen simple de personnaliser l’expérience de vos utilisateurs même lorsqu’ils rencontrent des problèmes. Une suggestion pour ces pages est d’inclure des liens vers des endroits où ils peuvent aller pour obtenir de l’aide ou plus d’informations. Si vous procédez ainsi, assurez-vous que les destinations des liens sont accessibles même lorsque les erreurs associées se produisent.</p>

</div><section class="article__sharing d-print-none"></section><div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2019-12-21T00:00:00+01:00"><!-- start custom article footer snippet -->

<!-- end custom article footer snippet -->
<!--
  <div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>

&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2019/12/19/Grub.html">Grub "Configure GRUB2 Boot Loader settings", clavier FR et un mot de passe</a></div><div class="next"><span>SUIVANT</span><a href="/2019/12/23/Blog-statique-jekyll-Yunohost-cinay.xyz.html">Blog statique de type jekyll sur site cinay.xyz</a></div></div></div>

</div>

<script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    $(function() {
      var $this ,$scroll;
      var $articleContent = $('.js-article-content');
      var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
      var scroll = hasSidebar ? '.js-page-main' : 'html, body';
      $scroll = $(scroll);

      $articleContent.find('.highlight').each(function() {
        $this = $(this);
        $this.attr('data-lang', $this.find('code').attr('data-lang'));
      });
      $articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
        $this = $(this);
        $this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
      });
      $articleContent.on('click', '.anchor', function() {
        $scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
      });
    });
  });
})();
</script>
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
<!-- end custom main bottom snippet -->
</div>
            </div></div></div></div>
    </div><script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $body = $('body'), $window = $(window);
    var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
    var activeCount = 0;
    function modal(options) {
      var $root = this, visible, onChange, hideWhenWindowScroll = false;
      var scrollTop;
      function setOptions(options) {
        var _options = options || {};
        visible = _options.initialVisible === undefined ? false : show;
        onChange = _options.onChange;
        hideWhenWindowScroll = _options.hideWhenWindowScroll;
      }
      function init() {
        setState(visible);
      }
      function setState(isShow) {
        if (isShow === visible) {
          return;
        }
        visible = isShow;
        if (visible) {
          activeCount++;
          scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
          $root.addClass('modal--show');
          $pageMain.scrollTop(scrollTop);
          activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
          hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
          $window.on('keyup', handleKeyup);
        } else {
          activeCount > 0 && activeCount--;
          $root.removeClass('modal--show');
          $window.scrollTop(scrollTop);
          activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
          hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
          $window.off('keyup', handleKeyup);
        }
        onChange && onChange(visible);
      }
      function show() {
        setState(true);
      }
      function hide() {
        setState(false);
      }
      function handleKeyup(e) {
        // Char Code: 27  ESC
        if (e.which ===  27) {
          hide();
        }
      }
      setOptions(options);
      init();
      return {
        show: show,
        hide: hide,
        $el: $root
      };
    }
    $.fn.modal = modal;
  });
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    // search panel
    var search = (window.search || (window.search = {}));
    var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
      true : window.useDefaultSearchBox ;

    var $searchModal = $('.js-page-search-modal');
    var $searchToggle = $('.js-search-toggle');
    var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
    var modalVisible = false;
    search.searchModal = searchModal;

    var $searchBox = null;
    var $searchInput = null;
    var $searchClear = null;

    function getModalVisible() {
      return modalVisible;
    }
    search.getModalVisible = getModalVisible;

    function handleModalChange(visible) {
      modalVisible = visible;
      if (visible) {
        search.onShow && search.onShow();
        useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
      } else {
        search.onShow && search.onHide();
        useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
        setTimeout(function() {
          useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
          search.clear && search.clear();
          window.pageAsideAffix && window.pageAsideAffix.refresh();
        }, 400);
      }
    }

    $searchToggle.on('click', function() {
      modalVisible ? searchModal.hide() : searchModal.show();
    });
    // Char Code: 83  S, 191 /
    $(window).on('keyup', function(e) {
      if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
        modalVisible || searchModal.show();
      }
    });

    if (useDefaultSearchBox) {
      $searchBox = $('.js-search-box');
      $searchInput = $searchBox.children('input');
      $searchClear = $searchBox.children('.js-icon-clear');
      search.getSearchInput = function() {
        return $searchInput.get(0);
      };
      search.getVal = function() {
        return $searchInput.val();
      };
      search.setVal = function(val) {
        $searchInput.val(val);
      };

      $searchInput.on('focus', function() {
        $(this).addClass('focus');
      });
      $searchInput.on('blur', function() {
        $(this).removeClass('focus');
      });
      $searchInput.on('input', window.throttle(function() {
        var val = $(this).val();
        if (val === '' || typeof val !== 'string') {
          search.clear && search.clear();
        } else {
          $searchBox.addClass('not-empty');
          search.onInputNotEmpty && search.onInputNotEmpty(val);
        }
      }, 400));
      $searchClear.on('click', function() {
        $searchInput.val(''); $searchBox.removeClass('not-empty');
        search.clear && search.clear();
      });
    }
  });
})();
</script><div class="search search--dark">
  <div class="main">
    <div class="search__header">Recherche</div>
    <div class="search-bar">
      <div class="search-box js-search-box">
        <div class="search-box__icon-search"><i class="fas fa-search"></i></div>
        <input id="search-input" type="text" />
        <div class="search-box__icon-clear js-icon-clear">
          <a><i class="fas fa-times"></i></a>
        </div>
      </div>
      <button class="button button--theme-dark button--pill search__cancel js-search-toggle">
        Annuler</button>
    </div>
    <div id="results-container" class="search-result js-search-result"></div>
  </div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
  * Simple-Jekyll-Search
  * Copyright 2015-2020, Christian Fei
  * Licensed under the MIT License.
  */
  
!function(){"use strict";var i={compile:function(r){return o.template.replace(o.pattern,function(t,e){var n=o.middleware(e,r[e],o.template);return void 0!==n?n:r[e]||t})},setOptions:function(t){o.pattern=t.pattern||o.pattern,o.template=t.template||o.template,"function"==typeof t.middleware&&(o.middleware=t.middleware)}},o={};o.pattern=/\{(.*?)\}/g,o.template="",o.middleware=function(){};var n=function(t,e){var n=e.length,r=t.length;if(n<r)return!1;if(r===n)return t===e;t:for(var i=0,o=0;i<r;i++){for(var u=t.charCodeAt(i);o<n;)if(e.charCodeAt(o++)===u)continue t;return!1}return!0},e=new function(){this.matches=function(t,e){return n(e.toLowerCase(),t.toLowerCase())}};var r=new function(){this.matches=function(e,t){return!!e&&(e=e.trim().toLowerCase(),(t=t.trim().toLowerCase()).split(" ").filter(function(t){return 0<=e.indexOf(t)}).length===t.split(" ").length)}};var u={put:function(t){if(f(t))return p(t);if(function(t){return Boolean(t)&&"[object Array]"===Object.prototype.toString.call(t)}(t))return function(t){var e=[];l();for(var n=0,r=t.length;n<r;n++)f(t[n])&&e.push(p(t[n]));return e}(t);return undefined},clear:l,search:function(t){return t?function(t,e,n,r){for(var i=[],o=0;o<t.length&&i.length<r.limit;o++){var u=function(t,e,n,r){for(var i in t)if(!function(t,e){for(var n=!1,r=0,i=(e=e||[]).length;r<i;r++){var o=e[r];!n&&new RegExp(t).test(o)&&(n=!0)}return n}(t[i],r.exclude)&&n.matches(t[i],e))return t}(t[o],e,n,r);u&&i.push(u)}return i}(s,t,c.searchStrategy,c).sort(c.sort):[]},setOptions:function(t){(c=t||{}).fuzzy=t.fuzzy||!1,c.limit=t.limit||10,c.searchStrategy=t.fuzzy?e:r,c.sort=t.sort||a}};function a(){return 0}var s=[],c={};function l(){return s.length=0,s}function f(t){return Boolean(t)&&"[object Object]"===Object.prototype.toString.call(t)}function p(t){return s.push(t),s}c.fuzzy=!1,c.limit=10,c.searchStrategy=c.fuzzy?e:r,c.sort=a;var d={load:function(t,e){var n=window.XMLHttpRequest?new window.XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");n.open("GET",t,!0),n.onreadystatechange=function(e,n){return function(){if(4===e.readyState&&200===e.status)try{n(null,JSON.parse(e.responseText))}catch(t){n(t,null)}}}(n,e),n.send()}};var h={merge:function(t,e){var n={};for(var r in t)n[r]=t[r],"undefined"!=typeof e[r]&&(n[r]=e[r]);return n},isJSON:function(t){try{return t instanceof Object&&JSON.parse(JSON.stringify(t))?!0:!1}catch(e){return!1}}};var t,m,v,w;function y(t){u.put(t),m.searchInput.addEventListener("input",function(t){-1===[13,16,20,37,38,39,40,91].indexOf(t.which)&&(g(),z(t.target.value))})}function g(){m.resultsContainer.innerHTML=""}function O(t){m.resultsContainer.innerHTML+=t}function z(t){var e;(e=t)&&0<e.length&&(g(),function(t,e){var n=t.length;if(0===n)return O(m.noResultsText);for(var r=0;r<n;r++)t[r].query=e,O(i.compile(t[r]))}(u.search(t),t))}function S(t){throw new Error("SimpleJekyllSearch --- "+t)}t=window,m={searchInput:null,resultsContainer:null,json:[],success:Function.prototype,searchResultTemplate:'<li><a href="{url}" title="{desc}">{title}</a></li>',templateMiddleware:Function.prototype,sortMiddleware:function(){return 0},noResultsText:"No results found",limit:10,fuzzy:!1,exclude:[]},w=function j(t){if(!((e=t)&&"undefined"!=typeof e.required&&e.required instanceof Array))throw new Error("-- OptionsValidator: required options missing");var e;if(!(this instanceof j))return new j(t);var r=t.required;this.getRequiredOptions=function(){return r},this.validate=function(e){var n=[];return r.forEach(function(t){"undefined"==typeof e[t]&&n.push(t)}),n}}({required:v=["searchInput","resultsContainer","json"]}),t.SimpleJekyllSearch=function(t){var n;0<w.validate(t).length&&S("You must specify the following required options: "+v),m=h.merge(m,t),i.setOptions({template:m.searchResultTemplate,middleware:m.templateMiddleware}),u.setOptions({fuzzy:m.fuzzy,limit:m.limit,sort:m.sortMiddleware}),h.isJSON(m.json)?y(m.json):(n=m.json,d.load(n,function(t,e){t&&S("failed to get JSON ("+n+")"),y(e)}));var e={search:z};return"function"==typeof m.success&&m.success.call(e),e}}();
</script>

<!-- Configuration -->
<script>
SimpleJekyllSearch({
  searchInput: document.getElementById('search-input'),
  resultsContainer: document.getElementById('results-container'),
  json: '/search.json',
  //searchResultTemplate: '<li><a href="https://static.cinay.eu{url}">{date}&nbsp;{title}</a></li>'
  searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
})
</script>

</div></div>


<script>(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function scrollToAnchor(anchor, duration, callback) {
      var $root = this;
      $root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
        window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
        callback && callback();
      });
    }
    $.fn.scrollToAnchor = scrollToAnchor;
  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function affix(options) {
      var $root = this, $window = $(window), $scrollTarget, $scroll,
        offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
        rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
        hasInit = false, curState;

      function setOptions(options) {
        var _options = options || {};
        _options.offsetBottom && (offsetBottom = _options.offsetBottom);
        _options.scrollTarget && (scrollTarget = _options.scrollTarget);
        _options.scroll && (scroll = _options.scroll);
        _options.disabled !== undefined && (disabled = _options.disabled);
        $scrollTarget = $(scrollTarget);
        isOverallScroller = window.isOverallScroller($scrollTarget[0]);
        $scroll = $(scroll);
      }
      function preCalc() {
        top();
        rootHeight = $root.outerHeight();
        rootTop = $root.offset().top + (isOverallScroller ? 0 :  $scrollTarget.scrollTop());
        rootLeft = $root.offset().left;
      }
      function calc(needPreCalc) {
        needPreCalc && preCalc();
        scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
        rootBottomTop = scrollBottom - rootTop;
      }
      function top() {
        if (curState !== 'top') {
          $root.removeClass('fixed').css({
            left: 0,
            top: 0
          });
          curState = 'top';
        }
      }
      function fixed() {
        if (curState !== 'fixed') {
          $root.addClass('fixed').css({
            left: rootLeft + 'px',
            top: 0
          });
          curState = 'fixed';
        }
      }
      function bottom() {
        if (curState !== 'bottom') {
          $root.removeClass('fixed').css({
            left: 0,
            top: rootBottomTop + 'px'
          });
          curState = 'bottom';
        }
      }
      function setState() {
        var scrollTop = $scrollTarget.scrollTop();
        if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
          fixed();
        } else if (scrollTop < rootTop) {
          top();
        } else {
          bottom();
        }
      }
      function init() {
        if(!hasInit) {
          var interval, timeout;
          calc(true); setState();
          // run calc every 100 millisecond
          interval = setInterval(function() {
            calc();
          }, 100);
          timeout = setTimeout(function() {
            clearInterval(interval);
          }, 45000);
          window.pageLoad.then(function() {
            setTimeout(function() {
              clearInterval(interval);
              clearTimeout(timeout);
            }, 3000);
          });
          $scrollTarget.on('scroll', function() {
            disabled || setState();
          });
          $window.on('resize', function() {
            disabled || (calc(true), setState());
          });
          hasInit = true;
        }
      }

      setOptions(options);
      if (!disabled) {
        init();
      }
      $window.on('resize', window.throttle(function() {
        init();
      }, 200));
      return {
        setOptions: setOptions,
        refresh: function() {
          calc(true, { animation: false }); setState();
        }
      };
    }
    $.fn.affix = affix;
  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    function toc(options) {
      var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
        selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
        headingsPos, scrolling = false, hasRendered = false, hasInit = false;

      function setOptions(options) {
        var _options = options || {};
        _options.selectors && (selectors = _options.selectors);
        _options.container && (container = _options.container);
        _options.scrollTarget && (scrollTarget = _options.scrollTarget);
        _options.scroller && (scroller = _options.scroller);
        _options.disabled !== undefined && (disabled = _options.disabled);
        $headings = $(container).find(selectors).filter('[id]');
        $scrollTarget = $(scrollTarget);
        $scroller = $(scroller);
      }
      function calc() {
        headingsPos = [];
        $headings.each(function() {
          headingsPos.push(Math.floor($(this).position().top));
        });
      }
      function setState(element, disabled) {
        var scrollTop = $scrollTarget.scrollTop(), i;
        if (disabled || !headingsPos || headingsPos.length < 1) { return; }
        if (element) {
          $activeCur = element;
        } else {
          for (i = 0; i < headingsPos.length; i++) {
            if (scrollTop >= headingsPos[i]) {
              $activeCur = $tocLi.eq(i);
            } else {
              $activeCur || ($activeCur = $tocLi.eq(i));
              break;
            }
          }
        }
        $activeLast && $activeLast.removeClass('active');
        ($activeLast = $activeCur).addClass('active');
      }
      function render() {
        if(!hasRendered) {
          $root.append($tocUl);
          $headings.each(function() {
            var $this = $(this);
            $tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
              .append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
          });
          $tocLi = $tocUl.children('li');
          $tocUl.on('click', 'a', function(e) {
            e.preventDefault();
            var $this = $(this);
            scrolling = true;
            setState($this.parent());
            $scroller.scrollToAnchor($this.attr('href'), 400, function() {
              scrolling = false;
            });
          });
        }
        hasRendered = true;
      }
      function init() {
        var interval, timeout;
        if(!hasInit) {
          render(); calc(); setState(null, scrolling);
          // run calc every 100 millisecond
          interval = setInterval(function() {
            calc();
          }, 100);
          timeout = setTimeout(function() {
            clearInterval(interval);
          }, 45000);
          window.pageLoad.then(function() {
            setTimeout(function() {
              clearInterval(interval);
              clearTimeout(timeout);
            }, 3000);
          });
          $scrollTarget.on('scroll', function() {
            disabled || setState(null, scrolling);
          });
          $window.on('resize', window.throttle(function() {
            if (!disabled) {
              render(); calc(); setState(null, scrolling);
            }
          }, 100));
        }
        hasInit = true;
      }

      setOptions(options);
      if (!disabled) {
        init();
      }
      $window.on('resize', window.throttle(function() {
        init();
      }, 200));
      return {
        setOptions: setOptions
      };
    }
    $.fn.toc = toc;
  });
})();
/*(function () {

})();*/
</script><script>
  /* toc must before affix, since affix need to konw toc' height. */(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $window = $(window);
    var $articleContent = $('.js-article-content');
    var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
    var toc;
    var tocDisabled = false;
    var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
    var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;

    function disabled() {
      return $col2.css('display') === 'none' || !hasToc;
    }

    tocDisabled = disabled();

    toc = $tocRoot.toc({
      selectors: TOC_SELECTOR,
      container: $articleContent,
      scrollTarget: hasSidebar ? '.js-page-main' : null,
      scroller: hasSidebar ? '.js-page-main' : null,
      disabled: tocDisabled
    });

    $window.on('resize', window.throttle(function() {
      tocDisabled = disabled();
      toc && toc.setOptions({
        disabled: tocDisabled
      });
    }, 100));

  });
})();
(function() {
  var SOURCES = window.TEXT_VARIABLES.sources;
  window.Lazyload.js(SOURCES.jquery, function() {
    var $window = $(window), $pageFooter = $('.js-page-footer');
    var $pageAside = $('.js-page-aside');
    var affix;
    var tocDisabled = false;
    var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');

    affix = $pageAside.affix({
      offsetBottom: $pageFooter.outerHeight(),
      scrollTarget: hasSidebar ? '.js-page-main' : null,
      scroller: hasSidebar ? '.js-page-main' : null,
      scroll: hasSidebar ? $('.js-page-main').children() : null,
      disabled: tocDisabled
    });

    $window.on('resize', window.throttle(function() {
      affix && affix.setOptions({
        disabled: tocDisabled
      });
    }, 100));

    window.pageAsideAffix = affix;
  });
})();
</script>
    </div>
    <script>(function () {
  var $root = document.getElementsByClassName('root')[0];
  if (window.hasEvent('touchstart')) {
    $root.dataset.isTouch = true;
    document.addEventListener('touchstart', function(){}, false);
  }
})();
</script>
  </body>
</html>

</div>

Autre solution de recherche

Recherche avec “Simple-Jekyll-Search”

  • https://christianfei.com/posts/Use-Simple-Jekyll-Search-on-your-blog-in-these-easy-steps/
  • https://github.com/christian-fei/Simple-Jekyll-Search
PRÉCÉDENTNginx personnalisation des pages d'erreur
SUIVANTAuto-Hébergement avec HomeBox
Recherche