One place for hosting & domains

      Comprendre

      Comprendre la date et l’heure en JavaScript


      Introduction

      La date et l’heure font partie de nos vies quotidiennes et occupent donc une place importante dans la programmation informatique. En JavaScript, vous aurez éventuellement à créer un site Internet avec un calendrier, un programme de formation ou une interface de prise de rendez-vous. Ces applications doivent afficher des heures applicables en fonction de la zone horaire actuelle de l’utilisateur, ou effectuer des calculs sur les heures d’arrivée et de départ ou de démarrage et de fin. En outre, vous devrez utiliser JavaScript pour générer un rapport quotidien à un certain moment la journée ou appliquer un filtre pour obtenir les restaurants et les établissements actuellement ouverts.

      Pour atteindre tous ces objectifs et plus encore, JavaScript intègre l’objet Date et les méthodes connexes. Dans ce tutoriel, vous allez apprendre à formater et utiliser la date et l’heure en JavaScript.

      L’objet Date

      L’objet Date est un objet intégré en JavaScript qui stocke la date et l’heure. Il offre un certain nombre de méthodes intégrées de formater et de gérer ces données.

      Par défaut, une nouvelle instance Date sans arguments crée un objet correspondant à la date et à l’heure actuelle. Il sera créé en fonction des paramètres du système de l’ordinateur actuellement utilisé.

      Pour expliquer l’objet Date en JavaScript, créons une variable et attribuons-lui la date du jour. Cet article a été rédigé le mercredi 18 octobre à Londres (GMT). Il s’agit donc de la date, de l’heure et du fuseau horaire actuels qui sont utilisés ci-dessous.

      now.js

      
      // Set variable to current date and time
      const now = new Date();
      
      // View the output
      now;
      

      Output

      Wed Oct 18 2017 12:41:34 GMT+0000 (UTC)

      En examinant la sortie, nous voyons que nous disposons d’une chaîne de date contenant les éléments suivants :

      Jour de la semaine mois Jour Année heure minute seconde Fuseau horaire
      Mer. Oct 18 2017 12 41 34 GMT+0000 (UTC)

      La date et l’heure sont décomposées et imprimées de manière compréhensible par l’humain.

      Cependant, JavaScript comprend la date en se basant sur un timestamp dérivé d’Unix time qui est une valeur composée du nombre de millisecondes passées depuis le 1er janvier 1970. Nous pouvons obtenir the en utilisant la méthode getTime().

      // Get the current timestamp
      now.getTime()
      

      Output

      1508330494000

      Le grand nombre qui apparaît dans notre résultat pour l’horodatage actuel représente la même valeur que celle ci-dessus, le 18 octobre 2017.

      L’heure Epoch est également appelée notice nemo, représentée par la chaîne de date 01 janvier, 1970 00:00:00 Universal Time (UTC) et par la 0. Nous pouvons tester cela dans le navigateur en créant une nouvelle variable et en l’assignant à une nouvelle instance Date sur la base d’un horadatage de 0.

      epoch.js

      
      // Assign the timestamp 0 to a new variable
      const epochTime = new Date(0);
      
      epochTime;
      

      Output

      01 January, 1970 00:00:00 Universal Time (UTC)

      L’heure Epoch a été choisie comme standard pour les ordinateurs qui permettent de mesurer le temps par les jours précédents de la programmation. Il est important de comprendre le concept de l’horodatage et de la chaîne de date, car les deux peuvent être utilisés en fonction des paramètres et de l’objectif d’une application.

      Pour le moment, nous avons appris à créer une nouvelle instance Date en fonction de l’heure actuelle et à en créer une en fonction d’un horodatage. Au total, il existe quatre formats par lesquels vous pouvez créer une nouvelle Date en JavaScript. En plus de l’heure par défaut et de l’horodatage actuelle, vous pouvez également utiliser une chaîne de date ou spécifier des dates et des heures particulières.

      Création résultat
      new Date() La date et l’heure actuelles
      new Date(timestamp) Crée la date en fonction de millisecondes
      new Date(date string) Crée la date en fonction de la chaîne de date
      new Date(year, month, day, hours, minutes, seconds, milliseconds) Crée la date en fonction de la date et de l’heure spécifiées

      Pour expliquer les différentes manières de faire référence à une date spécifique, nous allons créer de nouveaux objets Date qui représenteront le 4 juillet 1776, 12 h 30 GMT de trois manières différentes.

      usa.js

      
      // Timestamp method
      new Date(-6106015800000);
      
      // Date string method
      new Date("January 31 1980 12:30");
      
      // Date and time method
      new Date(1776, 6, 4, 12, 30, 0, 0);
      

      Les trois exemples ci-dessus créent une date contenant les mêmes informations.

      Vous remarquerez que la méthode de l’horodatage a un numéro négatif.

      Dans la méthode date et time, nos secondes et millisecondes sont configurées sur 0. Si un numéro est absent de la création de Date, un 0 sera renseigné par défaut. Cependant, l’ordre ne peut être modifié. Gardez donc cela en tête si vous décidez de retirer un numéro. Vous remarquerez également que le mois de juillet est représenté par un 6, non pas par le 7 habituel. En effet, les numéros pour la date et l’heure commencent à partir du 0, comme la plupart des éléments de programmation. Consultez le tableau détaillé donné à la section suivante.

      Récupérer la Date avec get

      Une fois que nous avons une date, nous pouvons accéder à tous les composants de la date avec diverses méthodes intégrées. Les méthodes retourneront chaque partie de la date en fonction du fuseau horaire local. Chacune de ces méthodes commence par get et renvoie le numéro correspondant. Le tableau ci-dessous détaille les méthodes get de l’objet Date.

      Date/Heure Méthode Plage Exemple
      Année getFullYear() AAAA 1970
      mois getMonth() 0-11 0 = janvier
      Jour (du mois) getDate() 1-31 1 = 1er du mois
      Jour (de la semaine) getDay() 0-6 0 = dimanche
      heure getHours() 0-23 0 = minuit
      minute getMinutes() 0-59
      Seconde getSeconds() 0-59
      Milliseconde getMilliseconds() 0-999
      Horadatage getTime() Millisecondes depuis l’heure Epoch

      Créons une nouvelle date, sur la base du 31 juillet 1980 et attribuons-lui une variable.

      harryPotter.js

      
      // Initialize a new birthday instance
      const birthday = new Date(1980, 6, 31);
      

      Maintenant, nous pouvons utiliser toutes nos méthodes pour obtenir chaque composant de la date, de l’année à la milliseconde.

      getDateComponents.js

      
      birthday.getFullYear();      // 1980
      birthday.getMonth();         // 6
      birthday.getDate();          // 31
      birthday.getDay();           // 4
      birthday.getHours();         // 0
      birthday.getMinutes();       // 0
      birthday.getSeconds();       // 0
      birthday.getMilliseconds();  // 0
      birthday.getTime();          // 333849600000 (for GMT)
      

      Vous aurez parfois besoin d’extraire une seule partie d’une date. Pour cela, vous pouvez utiliser les méthodes get intégrées, les outils que vous pouvez utiliser pour y remédier.

      Pour illustrer cela par un exemple, nous pouvons tester la date actuelle par rapport au jour et au mois du 3 octobre pour vérifier s’il s’agit bien du 3 octobre ou pas.

      oct3.js

      
      // Get today's date
      const today = new Date();
      
      // Compare today with October 3rd
      if (today.getDate() === 3 && today.getMonth() === 9) {
        console.log("It's October 3rd.");
      } else {
        console.log("It's not October 3rd.");
      }
      

      Output

      It's not October 3rd.

      Étant donné qu’au moment de l’écriture nous ne sommes pas le 3 octobre, la console l’indique.

      Les méthodes Date intégrées qui commencent par nous get nous permettent d’accéder aux composants de la date qui renvoient le numéro associé à ce que nous récupérons à partir de l’objet instancié.

      Modifier la Date avec set

      Pour toutes les méthodes get que nous avons abordées ci-dessus, il existe une méthode set correspondante. Lorsque vous utilisez get pour récupérer un composant spécifique à partir d’une date, set vous permet de modifier les composants d’une date. Le tableau ci-dessous détaille les méthodes set de l’objet Date.

      Date/Heure Méthode Plage Exemple
      Année setFullYear() AAAA 1970
      mois setMonth() 0-11 0 = janvier
      Jour (du mois) setDate() 1-31 1 = 1er du mois
      Jour (de la semaine) setDay() 0-6 0 = dimanche
      heure setHours() 0-23 0 = minuit
      minute setMinutes() 0-59
      Seconde setSeconds() 0-59
      Milliseconde setMilliseconds() 0-999
      Horadatage setTime() Millisecondes depuis l’heure Epoch

      Nous pouvons utiliser ces méthodes set pour modifier un, plusieurs ou tous les composants d’une date. Par exemple, nous pouvons modifier l’année de notre variable birthday ci-dessus en remplaçant 1980 par 1997.

      harryPotter.js

      
      // Change year of birthday date
      birthday.setFullYear(1997);
      
      birthday;
      

      Output

      Thu Jul 31 1997 00:00:00 GMT+0000 (UTC)

      Dans l’exemple ci-dessus, nous pouvons voir que lorsqu’on appelle la variable birthday, le résultat que nous recevons comporte la nouvelle année.

      Les méthodes intégrées commençant par set nous permettent de modifier différentes parties d’un objet Date.

      Méthodes de Date avec UTC

      Les méthodes get discutées ci-dessus récupèrent les composants de la date en fonction des paramètres du fuseau horaire de l’utilisateur. Pour avoir un meilleur contrôle sur les dates et les heures, vous pouvez utiliser les méthodes getUTC, qui sont exactement les mêmes que les méthodes get, à la différence qu’elles calculent l’heure en fonction de la norme UTC (Coordinated Universal Time). Le tableau ci-dessous répertorie les méthodes UTC pour l’objet Date en JavaScript.

      Date/Heure Méthode Plage Exemple
      Année getUTCFullYear() AAAA 1970
      mois getUTCMonth() 0-11 0 = janvier
      Jour (du mois) getUTCDate() 1-31 1 = 1er du mois
      Jour (de la semaine) getUTCDay() 0-6 0 = dimanche
      heure getUTCHours() 0-23 0 = minuit
      minute getUTCMinutes() 0-59
      Seconde getUTCSeconds() 0-59
      Milliseconde getUTCMilliseconds() 0-999

      Vous pouvez exécuter le code suivant pour tester la différence entre les méthodes Get locales et UTC.

      UTC.js

      
      // Assign current time to a variable
      const now = new Date();
      
      // Print local and UTC timezones
      console.log(now.getHours());
      console.log(now.getUTCHours());
      

      En exécutant ce code, le système imprimera l’heure actuelle et l’heure au fuseau horaire UTC. Si vous êtes actuellement dans le fuseau horaire UTC, les valeurs que vous obtiendrez après l’exécution du programme ci-dessus seront les mêmes.

      UTC est utile dans le sens où il offre une référence internationale standard de l’heure et vous permet de préserver une certaine cohérence dans les codes utilisés par rapport aux fuseaux horaires si cela est applicable à ce que vous développez.

      Conclusion

      Au cours de ce tutoriel, nous avons appris à créer une instance de l’objet Date et à utiliser ses méthodes intégrées pour accéder et modifier les composants d’une date spécifique. Pour mieux comprendre les dates et les heures en JavaScript, vous pouvez lire la référence Date sur le réseau de développement Mozilla.

      Pour exécuter de nombreuses tâches courantes en JavaScript, il est essentiel que vous sachiez comment travailler avec les dates. Vous pourrez alors faire plusieurs choses, que ce soit pour configurer l’exécution répétitive de rapports ou afficher les dates et les calendriers dans le fuseau horaire applicable.



      Source link

      Comprendre le serveur Nginx et les algorithmes de sélection de blocs de localisation


      Introduction

      Nginx fait partie des serveurs Web les plus populaires au monde. C’est avec succès qu’il peut gérer de grandes charges avec plusieurs connexions clients concurrentes et être facilement utilisé comme un serveur web, un serveur de courrier ou un serveur proxy inverse.

      Dans ce guide, nous allons traiter de quelques-uns des détails en coulisses qui déterminent la manière dont Nginx traite les requêtes clients. En ayant une compréhension de ces idées, vous n’aurez plus à faire autant de devinettes quant à la conception du serveur et des blocs de localisation et vous serez alors en mesure de rendre la manipulation des requêtes moins imprévisible.

      Configurations de bloc Nginx

      Nginx divise de manière logique les configurations destinées à servir différents contenus dans des blocs qui se trouvent dans une structure hiérarchique. Chaque fois qu’un client fait une requête, Nginx entame un processus pour sélectionner les blocs de configuration qui seront utilisés pour gérer la requête. C’est ce processus de décision que nous allons aborder dans ce guide.

      Les principaux blocs que nous allons aborder sont les suivants : le bloc server et le bloc location.

      Un bloc de serveur est un sous-ensemble de la configuration de Nginx qui définit le serveur virtuel avec lequel les requêtes d’un type donné seront gérées. Les administrateurs configurent souvent plusieurs blocs de serveur et décident ensuite du bloc qui sera chargé de la connexion en fonction du nom du domaine, du port et de l’adresse IP demandés.

      Un bloc de localisation se trouve dans un bloc de serveur. Il permet de définir la façon dont Nginx doit gérer les requêtes pour différentes ressources et URI du serveur parent. L’administrateur peut subdiviser l’espace URI de toutes les manières qu’il le souhaite en utilisant ces blocs. Il s’agit d’un modèle extrêmement flexible.

      Étant donné que Nginx permet à l’administrateur de définir plusieurs blocs de serveur qui fonctionnent comme des instances de serveur virtuel distinctes, il lui faut une procédure qui lui permette de déterminer lesquels de ces blocs utiliser pour satisfaire une requête.

      Pour cela, il passe par un système de vérifications utilisées pour trouver la meilleure correspondance possible. Les directives de bloc de serveur principal que Nginx prend en considération pendant ce processus sont les directives listen et server_name.

      Analyser la directive « listen » pour trouver des correspondances possibles

      Tout d’abord, Nginx examine l’adresse IP et le port de la requête. Il les fait ensuite correspondre avec la directive listen de chaque serveur pour créer une liste des blocs du serveur qui peuvent éventuellement résoudre la requête.

      La directive listen définit généralement l’adresse IP et le port auxquels le bloc de serveur répondra. Par défaut, tout bloc de serveur qui n’inclut pas une directive listen se voit attribuer les paramètres d’écoute de 0.0.0.0:80 (ou 0.0.0.0:8080 si Nginx est exécuté par un non-root user normal). Ces blocs peuvent ainsi répondre aux requêtes sur toute interface sur le port 80. Mais cette valeur par défaut n’a pas beaucoup de poids dans le processus de sélection de serveur.

      La directive listen peut être configurée sur :

      • Un combo adresse IP/port.
      • Une adresse IP unique qui écoutera ensuite le port 80 par défaut.
      • Un port unique qui écoutera chaque interface sur ce port.
      • Le chemin vers une socket Unix.

      La dernière option aura généralement des implications lorsque les requêtes passeront entre les différents serveurs.

      Lorsque Nginx tentera de déterminer le bloc de serveur qui enverra une requête, il tentera d’abord de décider en fonction de la spécificité de la directive listen en utilisant les règles suivantes :

      • Nginx traduit toutes les directives listen « incomplètes » en substituant les valeurs manquantes par leurs valeurs par défaut afin que chaque bloc puisse être évalué par son adresse IP et son port. Voici quelques exemples de ces traductions :
        • Un bloc sans directive listen utilise la valeur 0.0.0.0:80.
        • Un bloc configuré sur une adresse IP 111.111.111.111 sans aucun port devient 111.111.111.111:80
        • Un bloc configuré sur le port 8888 sans adresse IP devient 0.0.0.0:8888
      • Nginx tente ensuite de recueillir une liste des blocs du serveur qui correspondent à la requête de manière plus spécifique en fonction de l’adresse IP et du port. Cela signifie que tout bloc qui utilise fonctionnellement son adresse IP 0.0.0.0 (pour correspondre à toute interface) ne sera pas sélectionné s’il existe des blocs correspondants qui répertorient une adresse IP spécifique. Dans tous les cas, la correspondance avec le port doit être exacte.
      • S’il n’existe qu’une correspondance plus spécifique, la requête sera servie par ce bloc de serveur. En présence de plusieurs blocs de serveur avec le même niveau de spécificité, Nginx commence ensuite à évaluer la directive server_name de chaque bloc de serveur.

      Il est important de comprendre que Nginx évaluera la directive server_name uniquement au moment où il devra faire la distinction entre les blocs de serveur qui correspondent au même niveau de spécificité dans la directive listen. Par exemple, si example.com est hébergé sur le port 80 de 192.168.1.10, le premier bloc servira toujours la requête example.com de cet exemple, malgré la présence de la directive server_name dans le second bloc.

      server {
          listen 192.168.1.10;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name example.com;
      
          . . .
      
      }
      

      Dans le cas où plusieurs blocs de serveur correspondent à une spécificité égale, l’étape suivante consistera à vérifier la directive server_name.

      Analyser la directive « server_name » pour choisir une correspondance

      Ensuite, pour évaluer les requêtes qui disposent de directives listen également spécifiques, Nginx vérifie l’en-tête « Host » de la requête. Cette valeur contient le domaine ou l’adresse IP que le client a réellement tenté d’atteindre.

      Nginx tente de trouver la meilleure correspondance pour la valeur qu’il trouve en examinant la directive server_name dans chacun des blocs de serveur toujours sélectionnés. Nginx les évalue en utilisant la formule suivante :

      • Nginx tentera d’abord de trouver un bloc de serveur avec un server_name qui correspond à la valeur dans l’en-tête « Host » de la requête exactly. S’il la trouve, la requête sera servie par le bloc associé. S’il trouve plusieurs correspondances exactes, la première est utilisée.
      • S’il ne trouve aucune correspondance exacte, Nginx tentera ensuite de trouver un bloc de serveur avec un server_name correspondant à l’aide d’un métacaractère principal (indiqué par un * au début du nom dans la config). S’il en trouve un, la requête sera servie par ce bloc. S’il trouve plusieurs correspondances, la requête sera servie par la correspondance longest.
      • S’il ne trouve aucune correspondance en utilisant un métacaractère principal, Nginx recherchera ensuite un bloc de serveur avec un server_name correspondant à l’aide d’un métacaractère secondaire (indiqué par un nom de serveur qui se termine par un * dans la config). S’il en trouve un, la requête sera servie par ce bloc. S’il trouve plusieurs correspondances, la requête sera servie par la correspondance longest.
      • S’il ne trouve aucune correspondance en utilisant un métacaractère secondaire, Nginx évalue ensuite les blocs de serveur qui définissent le server_name en utilisant des expressions régulières (indiquées par un ~ avant le nom). Le first server_name avec une expression régulière qui correspond à l’en-tête « Host » sera utilisé pour servir la requête.
      • S’il ne trouve aucune correspondance d’expression régulière, Nginx sélectionne alors le bloc de serveur par défaut pour l’adresse IP et le port en question.

      Chaque combo adresse IP/port est doté d’un bloc de serveur par défaut qui sera utilisé lorsqu’aucun cours d’action ne pourra pas être déterminé avec les méthodes ci-dessus. Pour un combo adresse IP/port, il s’agira soit du premier bloc de la configuration ou du bloc qui contient l’option default_server dans la directive listen (qui remplacera le premier algorithme trouvé). Il ne peut y avoir qu’une seule déclaration default_server pour chaque combinaison adresse IP/port.

      Exemples

      S’il existe un server_name défini qui correspond exactement à la valeur de l’en-tête « Host », ce bloc de serveur sera sélectionné pour traiter la requête.

      Dans cet exemple, si l’en-tête « Host » de la requête est configuré sur « host1.example.com », c’est le second serveur qui sera sélectionné :

      server {
          listen 80;
          server_name *.example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name host1.example.com;
      
          . . .
      
      }
      

      S’il ne trouve aucune correspondance exacte, Nginx vérifie alors s’il existe un server_name qui commence avec un métacaractère qui convient. Ce sera la correspondance la plus longue et qui commence par un métacaractère qui sera sélectionnée pour répondre à la requête.

      Dans cet exemple, si l’en-tête de la requête indique « Host » pour « www.example.org », c’est le second bloc de serveur qui sera sélectionné :

      server {
          listen 80;
          server_name www.example.*;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name *.example.org;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name *.org;
      
          . . .
      
      }
      

      S’il ne trouve aucune correspondance qui commence par un métacaractère, Nginx verra alors s’il existe une correspondance en utilisant un métacaractère à la fin de l’expression. À ce stade, la requête sera servie par la correspondance la plus longue et qui contient un métacaractère.

      Par exemple, si l’en-tête de la requête est configuré sur « www.example.com », ce sera le troisième bloc de serveur qui sera sélectionné :

      server {
          listen 80;
          server_name host1.example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name www.example.*;
      
          . . .
      
      }
      

      S’il ne trouve aucune correspondance avec un métacaractère, Nginx tentera alors de faire correspondre les directives server_name qui utilisent des expressions régulières. C’est la first expression régulière correspondante qui sera sélectionnée pour répondre à la requête.

      Par exemple, si l’en-tête « Host » de la requête est configuré sur « www.example.com », c’est alors le second serveur qui sera sélectionné pour satisfaire la requête :

      server {
          listen 80;
          server_name example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name ~^(www|host1).*.example.com$;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name ~^(subdomain|set|www|host1).*.example.com$;
      
          . . .
      
      }
      

      Si aucune des étapes ci-dessus ne permet de satisfaire la requête, la requête sera alors transmise au serveur par default de l’adresse IP et le port correspondants.

      Mise en correspondance des blocs de localisation

      Tout comme le processus que Nginx utilise pour sélectionner le bloc de serveur qui traitera une requête, Nginx dispose également d’un algorithme établi pour décider du bloc de localisation du serveur qui servira au traitement des requêtes.

      Syntaxe de bloc de localisation

      Avant de voir de quelle manière Nginx procède pour décider du bloc de localisation qui sera utilisé pour traiter les requêtes, étudions un peu la syntaxe que vous êtes susceptible de rencontrer dans les définitions de bloc de localisation. Les blocs de localisation se trouvent dans les blocs serveur (ou autresblocs de localisation) et servent à décider de quelle manière traité l’URl de la requête (la partie de la demande qui se trouve après le nom du domaine ou l’adresse IP/port).

      Les blocs de localisation ont généralement cette forme :

      location optional_modifier location_match {
      
          . . .
      
      }
      

      Le location_match ci-dessus définit avec quel élément Nginx devrait comparer l’URl de la requête. Dans l’exemple ci-dessus, l’existence ou l’absence du modificateur affecte la façon dont Nginx tente de faire correspondre le bloc de localisation. Les modificateurs donnés ci-dessous entraîneront l’interprétation suivante du bloc de localisation associé :

      • (none) : si aucun modificateur n’est présent, l’emplacement est interprété comme une correspondance de prefix. Cela signifie que la localisation donnée sera comparée avec le début de l’URI de la requête pour voir s’il y a une correspondance.
      • = : si le signe égal est utilisé, ce bloc sera considéré comme une correspondance si l’URI de la requête correspond exactement à la localisation indiquée.
      • ~ : la présence d’un modificateur tilde indique que cet emplacement sera interprété comme une correspondance d’expression régulière sensible à la casse.
      • ~* : si un modificateur tilde et astérisque est utilisé, le bloc de localisation sera interprété comme une correspondance d’expression régulière insensible à la casse.
      • ^~ : si un modificateur de carat et tilde est présent et que ce bloc est sélectionné comme la meilleure correspondance d’expression non régulière, la mise en correspondance des expressions régulières n’aura pas lieu.

      Exemples de la syntaxe d’un bloc de localisation

      Pour vous donner un exemple de correspondance de préfixe, vous pouvez sélectionner le bloc de localisation suivant pour répondre aux URl de requête qui ressemblent à /site, /site/page1/index.html ou /site/index.html:

      location /site {
      
          . . .
      
      }
      

      Pour démontrer une correspondance exacte de l’URI, ce bloc sera toujours utilisé pour répondre à une URI de la requête qui ressemble à /page1. Il ne sera pas utilisé pour répondre à une URI de requête /page1/index.html. N’oubliez pas que, si ce bloc est sélectionné et que la requête est renseignée à l’aide d’une page d’index, le système procédera à une redirection interne vers un autre emplacement qui correspondra au gestionnaire réel de la requête :

      location = /page1 {
      
          . . .
      
      }
      

      Pour vous donner un exemple du type de localisation qui doit être interprétée comme une expression régulière sensible à la casse, vous pouvez utiliser ce bloc pour gérer les requêtes de /tortoise.jpg, mais pas pour /FLOWER.PNG :

      location ~ .(jpe?g|png|gif|ico)$ {
      
          . . .
      
      }
      

      Voici un bloc qui permettrait de faire une mise en correspondance insensible à la casse similaire à ce qui précède : Ici, ce bloc peut gérer /tortoise.jpg et /FLOWER.PNG à la fois :

      location ~* .(jpe?g|png|gif|ico)$ {
      
          . . .
      
      }
      

      Enfin, ce bloc empêchera l’affichage de la correspondance avec l’expression régulière, s’il est configuré de manière à être mis en correspondance avec la meilleure expression non régulière. Il peut gérer les requêtes de /costumes/ninja.html :

      location ^~ /costumes {
      
          . . .
      
      }
      

      Comme vous le voyez, les modificateurs indiquent de quelle manière le bloc de localisation doit être interprété. Cependant, cela ne nous indique pas l’algorithme que Nginx utilise pour décider du bloc de localisation qui enverra la requête. C’est ce que nous allons voir maintenant.

      Nginx choisit la localisation qui sera utilisée pour servir une requête de manière similaire à la façon dont il sélectionne un bloc de serveur. Il passe par un processus qui détermine le meilleur bloc de localisation pour toute requête donnée. Il est vraiment crucial d’avoir une bonne compréhension de ce processus afin de pouvoir configurer Nginx de manière fiable et précise.

      Tout en gardant à l’esprit les types de déclarations de localisation que nous avons décrites ci-dessus, Nginx évalue les contextes de localisation possibles en comparant l’URI de la requête avec chacun des emplacements. Pour cela, il utilise l’algorithme suivant :

      • Nginx commence par vérifier tous les correspondances de localisation sur la base des préfixes (tous les types de localisation qui n’impliquent pas une expression régulière). Il vérifie chaque localisation en fonction de l’URI complet de la requête.
      • Nginx recherche tout d’abord une correspondance exacte. S’il trouve qu’un bloc de localisation qui utilise le modificateur = correspond exactement à l’URI de la requête, ce bloc de localisation est immédiatement sélectionné pour servir la requête.
      • S’il ne trouve aucun bloc de localisation (avec le modificateur =) qui corresponde exactement, Nginx passe alors à l’évaluation des préfixes inexacts. Il trouve la localisation préfixée la plus longue qui correspond à l’URI de la requête donnée, qu’il évalue ensuite de la manière suivante :
        • Si la localisation préfixée la plus longue correspondante contient le modificateur ^~, Nginx arrête immédiatement sa recherche et sélectionnera cette localisation pour servir la requête.
        • Si la localisation préfixée la plus longue correspondante n’utilise pas le modificateur ^~, Nginx enregistre la correspondance pour le moment afin que le focus de la recherche puisse être déplacé.
      • Après avoir déterminé et stocké la localisation préfixée la plus longue correspondante, Nginx passe à l’évaluation des localisations d’expressions régulières (à la fois sensible et insensible à la casse). S’il existe des localisations d’expression régulière à l’intérieur de la localisation préfixée la plus longue correspondante, Nginx les déplacera en haut de la liste des localisations de regex pour procéder à une vérification. Nginx tente ensuite de faire une correspondance avec les localisations d’expression régulières de manière séquentielle. La première localisation d’expressions régulières qui correspond à l’URI de la requête est immédiatement sélectionnée pour servir la requête.
      • S’il ne trouve aucune localisation d’expressions régulières qui corresponde à l’URI de la requête, la localisation préfixée précédemment stockée sera alors sélectionnée pour servir la requête.

      Il est important de comprendre que, par défaut, Nginx préférera servir des correspondances d’expression régulière que des correspondances de préfixe. Cependant, il évalue d’abord les localisations préfixées pour que l’administration puisse écraser cette tendance en spécifiant les localisations avec les modificateurs = et ^~.

      Il est également important de noter que bien que les localisations préfixées sont généralement sélectionnées en fonction de la correspondance la plus spécifique et la plus longue, l’évaluation des expressions régulières s’arrête une fois que la première localisation correspondante est trouvée. Cela signifie que, dans la configuration, le positionnement a un grand impact sur les localisations d’expressions régulières.

      Pour finir, il est important de comprendre que les correspondances d’expressions régulières dans la correspondance de préfixe la plus longue « sauteront la ligne » lorsque Nginx procédera à l’évaluation des localisations de regex. Il procédera à l’évaluation de ces éléments, dans l’ordre, avant même qu’une des autres correspondances d’expression régulière ne soit prise en considération. Dans cet article, Maxim Dounin, un développeur Nginx incroyablement enrichissant, nous explique cette partie de l’algorithme de sélection.

      À quel moment l’évaluation des blocs de localisation passe-t-elle à d’autres localisations ?

      En règle générale, lorsqu’un bloc de localisation est sélectionné pour servir une requête, l’intégralité de la requête est traitée dans ce même contexte à partir de ce moment-là. Seules la localisation sélectionnée et les directives héritées déterminent de quelle manière la requête est traitée, sans que les blocs de localisation apparentés ne viennent interférer.

      Bien qu’il s’agisse d’une règle générale qui vous permettra de concevoir vos blocs de localisation de manière prévisible, il est important que vous sachiez que, parfois, certaines directives dans la localisation sélectionnée déclenchent une nouvelle recherche de localisation. Les exceptions à la règle « seulement un bloc de localisation » peuvent avoir un impact sur la façon dont la requête est effectivement servie et ne seront pas en accord avec les attentes que vous aviez lors de la conception de vos blocs de localisation.

      Voici quelques-unes des directives qui peuvent conduire à ce type de redirection interne :

      • index
      • try_files
      • rewrite
      • error_page

      Examinons-les brièvement.

      La directive index entraîne toujours une redirection interne si elle est utilisée pour gérer la requête. Les correspondances de localisation exactes permettent souvent d’accélérer le processus de sélection en mettant immédiatement fin à l’exécution de l’algorithme. Cependant, si vous effectuez une correspondance de localisation exacte qui est un répertoire, il est possible que la requête soit redirigée vers un autre emplacement pour le traitement en tant que tel.

      Dans cet exemple, la mise en correspondance de la première localisation se fait par un URI de requête /exact, mais pour gérer la requête, la directive index héritée du bloc initialise une redirection interne vers le second bloc :

      index index.html;
      
      location = /exact {
      
          . . .
      
      }
      
      location / {
      
          . . .
      
      }
      

      Dans le cas précédent, si vous souhaitez vraiment que l’exécution reste dans le premier bloc, il vous faudra trouver un moyen différent de satisfaire la requête au répertoire. Par exemple, vous pouvez configurer un index non valide pour ce bloc et activer autoindex :

      location = /exact {
          index nothing_will_match;
          autoindex on;
      }
      
      location  / {
      
          . . .
      
      }
      

      Il s’agit d’un moyen d’empêcher un index de changer de contexte, mais il n’est probablement pas si pratique pour la plupart des configurations. Une correspondance exacte sur les répertoires vous permet la plupart du temps de réécrire la requête par exemple (ce qui peut également générer une nouvelle recherche de localisation).

      Il existe également une autre instance dans laquelle la localisation de traitement peut être réévaluée, avec la directive try_files Cette directive indique à Nginx de vérifier s’il existe un ensemble de fichiers ou de répertoires nommés. Le dernier paramètre peut être un URI vers lequel Nginx procédera à une redirection interne.

      Prenons le cas de la configuration suivante :

      root /var/www/main;
      location / {
          try_files $uri $uri.html $uri/ /fallback/index.html;
      }
      
      location /fallback {
          root /var/www/another;
      }
      

      Dans l’exemple ci-dessus, si une requête est exécutée pour /blahblah, la première localisation obtiendra initialement la requête. Il tentera de trouver un fichier nommé blahblah dans le répertoire /var/www/main. S’il ne peut en trouver, il redirigera sa recherche sur un fichier nommé blahblah.html. Il tentera ensuite de voir s’il existe un répertoire appelé blahblah/ dans le répertoire /var/www/main. Si toutes ces tentatives son un échec, il se redirigera vers /fallback/index.html. Cela déclenchera une autre recherche de localisation que le deuxième bloc de localisation détectera. Cela servira le fichier /var/www/another/fallback/index.html.

      La directive rewrite est également une des autres directives qui permettent de passer un bloc de localisation. Lorsque Nginx utilise le paramètre last avec la directive rewrite, ou n’utilise aucun paramètre du tout, il recherchera une nouvelle localisation correspondante en fonction des résultats de la réécriture.

      Par exemple, si nous modifions le dernier exemple pour y inclure une réécriture, nous pouvons voir que la requête est parfois transmise directement à la seconde localisation sans s’appuyer sur la directive try_files :

      root /var/www/main;
      location / {
          rewrite ^/rewriteme/(.*)$ /$1 last;
          try_files $uri $uri.html $uri/ /fallback/index.html;
      }
      
      location /fallback {
          root /var/www/another;
      }
      

      Dans l’exemple ci-dessus, une requête /rewriteme/hello sera initialement gérée par le premier bloc de localisation. Elle sera réécrite /hello, puis la recherche de la localisation sera déclenchée. Dans ce cas, elle correspondra à nouveau à la première localisation et sera traité par le try_files comme d’habitude, peut même redirigé sur /fallback/index.html si la recherche est infructueuse (en utilisant la redirection interne try_files discutée plus haut).

      Cependant, si une requête /rewriteme/fallback/hello est effectuée, le premier bloc sera à nouveau une correspondance. La réécriture est à nouveau appliquée, ce qui génère cette fois-ci /fallback/hello. La requête sera ensuite servie par le second bloc de localisation.

      La situation est connexe avec la directive return lorsque vous envoyez les codes de statut 301 ou 302. La différence ici est que la requête obtenue et une requête entièrement nouvelle qui prend la forme d’une redirection visible à l’extérieur. Cette même situation peut se produire avec la directive rewrite si vous utilisez les balises redirect ou permanent. Cependant, ces recherches de localisation ne devraient pas être fortuites, car les redirections visibles en externe entraînent toujours une nouvelle requête.

      La directive error_page peut générer une redirection interne similaire à celle créée par try_files. Cette directive permet de définir ce qui devrait se passer si le système rencontre certains codes de statut. Cela ne sera probablement jamais exécuté si try_files est configuré. En effet, cette directive gère l’intégralité du cycle de vie d’une requête.

      Prenons l’exemple suivant :

      root /var/www/main;
      
      location / {
          error_page 404 /another/whoops.html;
      }
      
      location /another {
          root /var/www;
      }
      

      Chaque requête (autres que celles qui commencent par /another) sera traitée par le premier bloc, qui servira les fichiers /var/www/main. Cependant, si un fichier est introuvable (un statut 404), vous verrez se produire une redirection interne vers /another/whoops.html, générant une nouvelle recherche de localisation qui attérira éventuellement sur le second bloc. Ce fichier sera servi à partir de /var/www/another/whoops.html.

      Comme vous pouvez le voir, en comprenant les circonstances dans lesquelles Nginx déclenche une recherche de nouvelle localisation, vous serez plus à même de prévoir le comportement que vous verrez lorsque vous ferez des requêtes.

      Conclusion

      Le fait de comprendre de quelle manière Nginx traite les requêtes clients peut vraiment vous faciliter la tâche en tant qu’administrateur. Vous pourrez savoir quel bloc de serveur Nginx sélectionnera en fonction de chaque requête clients. Vous pourrez également deviner de quelle manière le bloc de localisation sera sélectionné en fonction de l’URI de la requête. Dans l’ensemble, en sachant de quelle manière Nginx sélectionne les différents blocs, vous serez en capacité de reconnaître les contextes que Nginx appliquera pour servir chaque requête.



      Source link

      Comprendre les actions asynchrones de Redux avec Redux Thunk


      Introduction

      Par défaut, les actions de Redux sont expédiées de façon synchrone, ce qui pose un problème pour toute application non triviale qui doit communiquer avec une application externe ou effectuer des effets secondaires. Redux permet également au middleware qui se trouve au milieu d’une action d’être distribué et à l’action d’atteindre les réducteurs.

      Il existe deux bibliothèques de middleware très populaires qui prennent en charge les effets spéciaux et les actions asynchrones : Redux Thunk et Redux Saga. Cette publication vous emmène à la découverte de Redux Thunk.

      Thunk est un concept de programmation dans lequel une fonction est utilisée pour retarder l’évaluation/le calcul d’une opération.

      Redux Thunk est un middleware qui vous permet de faire un appel à l’action auprès des créateurs qui renvoie une fonction au lieu d’un objet d’action. Cette fonction reçoit la méthode de distribution du store. Elle permet donc d’envoyer des actions synchrones régulières dans le corps de la fonction une fois que les opérations asynchrones ont été terminées.

      Dans cet article vous allez apprendre à ajouter Redux Thunk et découvrir de quelle manière il peut s’adapter à une application hypothétique de Todo.

      Conditions préalables

      Cet article suppose que vous disposez de certaines connaissances de base sur React et Redux. Vous pouvez consulter cet article si vous débutez avec Redux.

      Ce tutoriel est construit autour d’une hypothétique application de Todo qui est supposée assurer le suivi des tâches à faire et des tâches accomplies. Nous présumons que create-react-app a été utilisée pour générer une nouvelle application React. Cependant, redux, react-redux et axios ont déjà été installés.

      Cet article ne vous donne pas d’informations plus détaillées sur la manière de créer une application de Todo de zéro. Nous la présentons ici comme un paramètre conceptuel pour mettre en avant Redux Thunk.

      Ajout de redux-thunk

      Tout d’abord, utilisez le terminal pour naviguer vers le répertoire de projets et installez le paquet redux-thunk dans votre projet :

      • npm install redux-thunk@2.3.0

      Remarque : Redux Thunk ne dispose que de 14 lignes de code. Consultez la source ici pour en savoir plus sur le fonctionnement en arrière-plan d’un middleware Redux.

      Maintenant, utilisez le middleware pour créer le store de votre application en utilisant applyMiddleware de Redux. Avec une application React intégrant redux et react-redux, votre fichier index.js devrait ressembler à ce qui suit :

      src/index.js

      import React from 'react';
      import ReactDOM from 'react-dom';
      import { Provider } from 'react-redux';
      import { createStore, applyMiddleware } from 'redux';
      import thunk from 'redux-thunk';
      import './index.css';
      import rootReducer from './reducers';
      import App from './App';
      import * as serviceWorker from './serviceWorker';
      
      // use applyMiddleware to add the thunk middleware to the store
      const store = createStore(rootReducer, applyMiddleware(thunk));
      
      ReactDOM.render(
        <Provider store={store}>
          <App />
        </Provider>,
        document.getElementById('root')
      );
      

      Maintenant, Redux Thunk a été importé et appliqué dans votre application.

      Utilisation de Redux Thunk dans un exemple d’application

      Redux Thunk est le plus couramment utilisé pour communiquer de manière asynchrone avec une application externe afin de récupérer ou de sauvegarder des données. Redux Thunk vous permet de facilement distribuer des actions qui suivent le cycle de vie d’une requête à une application externe.

      En règle générale, pour créer un nouvel élément de todo, il faut lancer une action pour indiquer qu’une création d’un élément todo a commencé. Ensuite, si l’élément todo est bien créé et renvoyé par le serveur externe, une autre action est distribuée avec le nouvel élément todo. Si une erreur survient et le serveur ne sauvegarde pas le todo, une action accompagnée d’une erreur risque d’être déclenchée.

      Voyons comment nous pourrions le faire avec Redux Thunk.

      Importez et distribuez l’action dans votre composant de conteneur :

      src/containers/AddTodo.js

      import { connect } from 'react-redux';
      import { addTodo } from '../actions';
      import NewTodo from '../components/NewTodo';
      
      const mapDispatchToProps = dispatch => {
        return {
          onAddTodo: todo => {
            dispatch(addTodo(todo));
          }
        };
      };
      
      export default connect(
        null,
        mapDispatchToProps
      )(NewTodo);
      

      L’action utilisera Axios pour envoyer une requête POST au terminal, au niveau de JSONPlaceholder (https://jsonplaceholder.typicode.com/todos) :

      src/actions/index.js

      import {
        ADD_TODO_SUCCESS,
        ADD_TODO_FAILURE,
        ADD_TODO_STARTED,
        DELETE_TODO
      } from './types';
      
      import axios from 'axios';
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(`https://jsonplaceholder.typicode.com/todos`, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              dispatch(addTodoSuccess(res.data));
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      const addTodoSuccess = todo => ({
        type: ADD_TODO_SUCCESS,
        payload: {
          ...todo
        }
      });
      
      const addTodoStarted = () => ({
        type: ADD_TODO_STARTED
      });
      
      const addTodoFailure = error => ({
        type: ADD_TODO_FAILURE,
        payload: {
          error
        }
      });
      

      Notez que le créateur d’action addTodo renvoie une fonction au lieu de l’objet d’action habituel. Cette fonction reçoit la méthode d’envoi du store.

      À l’intérieur du corps de la fonction, envoyez tout d’abord une action synchrone immédiate au store pour indiquer que vous avez commencé à enregistrer le todo avec l’application externe. Ensuite, vous devez envoyer la requête POST en elle-même au serveur, en utilisant Axios. Si le serveur vous envoie une réponse positive, vous distribuez une action synchrone probante avec les données reçues via la réponse. Mais, si la réponse est un échec, nous distribuons une action synchrone différente avec le message d’erreur.

      Lorsque vous utilisez une API externe, comme JSONPlaceholder dans le cas présent, il est possible qu’il y ait un retard au niveau du réseau. Cependant, si vous travaillez avec un serveur de backend local, il se peut que les réponses du réseau soient trop rapides pour pouvoir constater le retard de réseau qu’un utilisateur réel devrait subir. Vous pouvez donc ajouter un retard artificiel au cours du développement :

      src/actions/index.js

      // ...
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(ENDPOINT, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              setTimeout(() => {
                dispatch(addTodoSuccess(res.data));
              }, 2500);
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      // ...
      

      Pour tester les scénarios d’erreur, vous pouvez lancer une erreur manuellement :

      src/actions/index.js

      // ...
      
      export const addTodo = ({ title, userId }) => {
        return dispatch => {
          dispatch(addTodoStarted());
      
          axios
            .post(ENDPOINT, {
              title,
              userId,
              completed: false
            })
            .then(res => {
              throw new Error('addToDo error!');
              // dispatch(addTodoSuccess(res.data));
            })
            .catch(err => {
              dispatch(addTodoFailure(err.message));
            });
        };
      };
      
      // ...
      

      Pour compléter, voici un exemple de ce à quoi le réducteur de todo pourrait ressembler pour prendre en charge l’intégralité du cycle de vie de la requête :

      src/reducers/todosReducer.js

      import {
        ADD_TODO_SUCCESS,
        ADD_TODO_FAILURE,
        ADD_TODO_STARTED,
        DELETE_TODO
      } from '../actions/types';
      
      const initialState = {
        loading: false,
        todos: [],
        error: null
      };
      
      export default function todosReducer(state = initialState, action) {
        switch (action.type) {
          case ADD_TODO_STARTED:
            return {
              ...state,
              loading: true
            };
          case ADD_TODO_SUCCESS:
            return {
              ...state,
              loading: false,
              error: null,
              todos: [...state.todos, action.payload]
            };
          case ADD_TODO_FAILURE:
            return {
              ...state,
              loading: false,
              error: action.payload.error
            };
          default:
            return state;
        }
      }
      

      Découverte de getState

      Non seulement la méthode de distribution de l’état est reçue, mais la fonction renvoyée par un créateur d’action asynchrone avec Redux Thunk reçoit également la méthode getState du store pour pouvoir lire les valeurs réelles du store :

      src/actions/index.js

      export const addTodo = ({ title, userId }) => {
        return (dispatch, getState) => {
          dispatch(addTodoStarted());
      
          console.log('current state:', getState());
      
          // ...
        };
      };
      

      Avec ce qui précède, l’état actuel s’imprimera sur la console.

      Par exemple :

      {loading: true, todos: Array(1), error: null}
      

      Il peut s’avérer utile d’utiliser getState pour gérer les choses différemment en fonction de l’état actuel. Par exemple, si vous souhaitez limiter l’application à quatre éléments de todo à la fois, vous pouvez les renvoyer à partir de la fonction, si l’état contient déjà le nombre maximum d’éléments todo :

      src/actions/index.js

      export const addTodo = ({ title, userId }) => {
        return (dispatch, getState) => {
          const { todos } = getState();
      
          if (todos.length > 4) return;
      
          dispatch(addTodoStarted());
      
          // ...
        };
      };
      

      Compte tenu de ce qui précède, l’app sera limitée à quatre éléments de todo.

      Conclusion

      Au cours de ce tutoriel, vous avez appris à ajouter Redux Thunk à une application React pour pouvoir exécuter des actions de manière asynchrone. Ceci est utile si vous utilisez un store Redux et que vous vous appuyez sur des API externes.

      Si vous souhaitez en savoir plus sur React, consultez notre série Comment coder dans React.js ou consultez notre page thématique React pour des exercices et des projets de programmation.



      Source link