Archives Wild Code School
ASP.Net

ASP.Net: Queue intergicielle

Quête 4 sur 7 · 1 image archivée

L'intergiciel

Objectifs

  • Connaître la définition d'un intergiciel (middleware)
  • Créer un serveur minimal
  • Comprendre comment utiliser IApplicationBuilder.Use et IApplicationBuilder.Run

La queue intergicielle (middleware pipeline)

Je suis sûr que tu connais déjà le concept d'un logiciel. Pour être précis, un logiciel est composé de multiples programmes et de procédures. Ceux-ci sont nécessaires au bon fonctionnement d'un système informatique.

Alors qu'est-ce que pourrait bien être un intergiciel ?

Middleware

Un intergiciel est un composant logiciel qui vient se placer dans une queue. Cette queue contient une suite d'intergiciels qui un à un sont exécutés à la réception d'une requête. Les intergiciels peuvent aussi exécuter du code après le traitement d'une requête.

Ainsi, les intergiciels sont exécutés l'un à la suite de l'autre dans un sens, puis dans l'autre sens lorsque le dernier intergiciel est atteint dans la queue.

↗
Intergiciel

Article expliquant ce qu'est un intergiciel et les avantages qui découlent de son utilisation

talend.com

A quoi ça sert ?

Lorsqu'un client demande une application à un ou plusieurs développeurs, il présente son besoin en fonction de son expertise, son métier. Le besoin précis du client omet souvent beaucoup d'aspects techniques que seuls les développeurs sont en capacité de mesurer. Par exemple:

Client pense: Je veux pouvoir éditer de manière sécurisée le nombre de chaussettes que je vais commander sur une application Web

Développeur pense: Il faut que j'héberge un site Web associé à un nom de domaine servant sur le port 80 et 443 une application ASP.Net qui doit pouvoir authentifier des utilisateurs grâce à une adresse électronique et un mot de passe puis de les autoriser à accéder à une partie sécurisée du site où un nombre de chaussettes va pouvoir être consulté et édité dans une base de données via une interface Web. 🧠

La seule information qu'ont en commun le client et le développeur est le fait qu'un nombre de chaussettes peut être consulté et modifié via le Web. Autour du besoin client se situent toujours des couches intermédiaires de complexité: authentifier un utilisateur, accéder à la base de données, sécuriser en HTTPS, chiffrer des transactions, valider des informations ... Toutes ces couches de complexité ne font pas partie du besoin métier.

Les développeurs, pour gagner du temps préfèrent se concentrer sur le besoin métier. Et c'est à ce besoin que répondent les intergiciels. En effet, un intergiciel se plaçant juste après la réception d'une requête, il peut réaliser énormément d'actions tout en restant faiblement couplé à la solution apportée au client, car ils s'exécutent en amont de la réponse.

En somme, les intergiciels font gagner du temps et de l'argent car ils permettent au développeur de se concentrer sur son travail de spécification du besoin du client plutôt que sur des détails techniques complexes.

Voici quelques exemples d'intergiciels utilisés en ASP.Net:

  • HttpsRedirection - Force une requête à chiffrer les communications via le protocole SSL
  • Routing - Fait correspondre une requête à un contrôleur ou une page Razor
  • Authentication - Gère l'authentification
  • Authorization - Gère les rôles
↗
Intergiciel

Vidéo présentant le concept d'intergiciel

youtube.com

Use & Run

Lorsqu'est crée un projet ASP.NET, certains fichiers de base sont générés automatiquement. Le fichier qui nous intéresse particulièrement est Startup.cs.

Startup.cs

Le fichier Startup.cs initialise la queue intergicielle d'une application ASP.Net en ajoutant et configurant une suite d'intergiciels. La classe Startup est par défaut constituée de deux méthodes:

  • void ConfigureServices(IServiceCollection)
  • void Configure(IApplicationBuilder, IWebHostEnvironment) <= La méthode qui nous intéresse

Configure

Cette méthode prend deux arguments. Un premier de type IApplicationBuilder qui permet de configurer la queue intergicielle et un deuxième de type IWebHostEnvironment qui permet de configurer l'environnement de l'application.

Voici l'exemple d'une méthode Startup.Configure:

csharp
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{

    env.ApplicationName = "MiddlewarePipelineConfigurationExample"; // Set the application name
    app.UseHttpsRedirection(); // Add HTTPS 
    app.UseRouting(); // Add routing 
    app.UseAuthorization(); // ... and so 
    // We map routes by controllers configuration
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers(); // Configure the endpoint middleware
    });
}

La code ci-dessus va ajouter quatre intergiciels à la queue. Les intergiciels sont exécutés dans l'ordre où sont exécutées les méthodes Use{Service}. Ainsi, une requête lors de sa réception sera traitée dans cet ordre:

  1. Redirection HTTPS - Mise en place de SSL par-dessous de HTTP
  2. Routing - Fait correspondre des requêtes à des actions sur le site
  3. Authorization - Vérification des informations d'authentification
  4. Endpoints - Mise en correspondance des requêtes et du code

Il faut attendre que la liste des quatre intergiciels soit parcourue dans les deux sens pour que la réponse soit fournie au client.

Use
csharp
 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.Use(async (context, next) => {
        // Code to be executed at Request reception
        await next.Invoke(); // Invoke the next middleware in the pipeline
        // Code to be executed after the end of the pipeline has been reached
    });
}

La classe IApplicationBuilder dispose d'une méthode Use qui prend en paramètre une fonction déléguée. Cette fonction déléguée contient le code de l'intergiciel. Ainsi, il est possible de rajouter un intergiciel personnalisé.

La fonction déléguée que reçoit la méthode IApplicationBuilder.Use accepte deux paramètres:

  • context - De type HttpContext, il s'agit du contexte HTTP (query string, en-têtes, URL ...)
  • next - De type Func<Task> Il s'agit du prochain intergiciel dans la queue
Run

La fonction asynchrone déléguée (delegate) passée en paramètre de la méthode IApplicationBuilder.Run contient le code exécuté lorsque tous les intergiciels de la queue sont parcourus et exécutés. Il s'agit du dernier maillon de la chaîne: c'est la méthode qui est exécutée après que le parcours en double-sens des intergiciels présents dans la queue soit terminé.

A savoir que tout appel à IApplicationBuilder.Use ou IApplicationBuilder.Run placé après un premier appel à IApplicationBuilder.Run ne sera pas exécuté.

csharp
namespace MiddlewarePipeline
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseHttpsRedirection(); // Harden the security with HTTPS enforcing
            // Adding a custom middleware
            app.Use(async (context, next) => {
                // Here goes the custom middleware post-reception behavior
                await next.Invoke();
                // Here goes the custom middleware post-treatment behavior
            });

            app.Run(async context =>
            {
                await context.Response.WriteAsync("Hello, World !");
            });
        }
    }
}

Challenge

Crée un projet ASP.Net sans MVC, configuré pour être une API. Supprime le corps de la méthode Startup.Configure. Ajoute un intergiciel qui vérifie que le paramètre allow est présent dans l'URL (ex: http://localhost:12345?allow). Si le paramètre allow est présent, la fonction déléguée paramètre de IApplicationBuilder.Run écrit "Hello, World!" dans le corps de la réponse.

Critères de validation

  • Un lien vers un dépôt hébergé sur GitHub est fourni en tant que solution de la quête
  • Le projet est une API ASP.Net générée avec Visual Studio
  • La méthode Startup.Configure ajoute un intergiciel vérifiant que le paramètre allow est présent dans l'URL
  • Si le paramètre n'est pas présent dans l'URL, une exception est soulevée
  • Si le paramètre est présent, l'application renvoie "Hello, World!" dans le corps de la réponse
  • Aucune modification de la requête HTTP n'est exécutée dans un intergiciel