Exercice – Créer un intergiciel personnalisé

Effectué

Les développeurs peuvent créer des composants intergiciels personnalisés pour ajouter des fonctionnalités à une application ASP.NET Core. Les intergiciels personnalisés peuvent être insérés n’importe où dans le pipeline d’intergiciels. Ils peuvent également être utilisés à l’aide de composants d’intergiciels intégrés, comme le montre l’exemple ci-dessous :

Diagramme illustrant le flux d’une requête via le pipeline.

L’équipe des opérations réseau de votre entreprise est en train de résoudre des problèmes de performance dans l’environnement de production. Votre chef d’équipe vous a chargé d’implémenter certaines fonctionnalités pour mieux prendre en charge la surveillance en temps réel de l’application. L’application doit consigner les détails de la demande dans la console. Pour chaque requête, elle doit consigner la méthode de demande, le chemin d’accès et le code d’état de la réponse.

Dans cet exercice, vous créerez un composant intergiciel personnalisé qui journalise les détails de la requête dans la console.

Ajouter un intergiciel personnalisé

Nous allons modifier l’application ASP.NET Core existante pour inclure des intergiciels personnalisés qui journalise les détails de la requête dans la console.

  1. Ouvrez le fichier Program.cs s’il n’est pas déjà ouvert.

  2. Juste avant app.Run(), insérez le code suivant :

    app.Use(async (context, next) =>
    {
        Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
        await next(); 
    });
    

    Dans le code précédent :

    • app.Use() ajoute un composant middleware personnalisé au pipeline. Le composant prend un objet HttpContext et un objet RequestDelegate en tant que paramètres.
    • Le délégué écrit la méthode de demande, le chemin d’accès et le code d’état de la réponse dans la console.
    • await next() appelle le composant intergiciel suivant dans le pipeline.

Tester les modifications

  1. Appuyez sur Ctrl+Maj + F5 pour reconstruire et redémarrer l’application.

  2. Lorsque la fenêtre du navigateur s’ouvre, notez que l’URL racine affiche « Bienvenue dans Contoso ! »

  3. Ajoutez /history à l’URL et appuyez sur Entrer. Le navigateur sera redirigé vers la page /about.

  4. Dans Visual Studio Code, appuyez sur Ctrl+Maj+P pour ouvrir la palette de commandes. Recherchez et sélectionnez Console de débogage : Concentrez-vous sur la vue de la Console de débogage pour basculer vers l’onglet Console de débogage dans le panneau inférieur. Notez les lignes suivantes :

    GET / 200
    GET /about 200
    

    la sortie de la console affiche la méthode de demande, le chemin d’accès et le code d’état de la réponse pour chaque requête. La première ligne affiche la requête de l’URL racine, et la deuxième, celle de la page /about.

    Remarque

    Votre navigateur peut également requérir /favicon.ico. Il s’agit d’une requête standard pour le favicon d’un site Web. Elle peut par conséquent être ignorée.

  5. Laissez l'application ouverte pour le prochain exercice.

Modifier l’ordre de l’intergiciel

L’application semble fonctionner, mais il y a un problème. Vous avez demandé la page /history, mais la sortie de la console ne l’affiche pas. Ce comportement est dû au fait que le composant intergiciel personnalisé qui journalise les détails de la requête a été ajouté après l’intergiciel de réécriture d’URL. L’intergiciel de réécriture d’URL redirige les requêtes de /history vers /about et envoie la réponse. Le composant intergiciel personnalisé quant à lui ne voit pas la requête. Nous allons résoudre ce problème.

  1. Déplacez la ligne app.Use() que vous avez ajoutée immédiatement avant la ligne app.UseRewriter().

    Le fichier Program.cs complet doit ressembler à ce qui suit :

    using Microsoft.AspNetCore.Rewrite;
    
    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    
    app.Use(async (context, next) =>
    {
        Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
        await next(); 
    });
    
    app.UseRewriter(new RewriteOptions().AddRedirect("history", "about"));
    
    app.MapGet("/", () => "Hello World!");
    app.MapGet("/about", () => "Contoso was founded in 2000.");
    
    app.Run();
    

    Le composant intergiciel personnalisé est désormais ajouté avant l’intergiciel de réécriture d’URL. Le composant intergiciel personnalisé journalise les détails de la requête avant que l’intergiciel de réécriture d’URL traite la requête et la redirige.

  2. Redémarrez l’application et testez-la comme avant. Cette fois, la sortie de la Console de débogage doit inclure la requête de la page /history.

    GET / 200
    GET /history 200
    GET /about 200
    

    La sortie de la console affiche désormais la requête de la page /history juste avant de la rediriger vers la page /about.

Corriger le code d’état

L’application est presque prête, mais il y a un autre problème. Le code d’état dans la sortie de la console est toujours 200, même lorsque l’application redirige la requête. Le code d’état de la requête /history doit être une redirection 302. La raison de ce comportement est un autre problème lié à l'ordre dans lequel les composants middleware sont traités.

Le composant intergiciel personnalisé journalise les détails sur la console, puis appelle await next() pour passer au composant intergiciel suivant. Le problème est que la propriété StatusCode de l’objet Response est définie après que le composant intergiciel de terminal lance la réponse. Nous allons modifier le code pour résoudre ce problème.

  1. Dans le délégué que vous avez ajouté, déplacez la ligne Console.WriteLine() après la ligne await next().

    Le code mis à jour doit ressembler à ce qui suit :

    app.Use(async (context, next) =>
    {
        await next(); 
        Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
    });
    

    À présent, le composant intergiciel personnalisé journalisera les détails de la requête après que le composant intergiciel terminal ait défini le code d’état de la réponse.

  2. Redémarrez et testez à nouveau la requête /history. La sortie de la Console de débogage doit désormais afficher le bon code d'état.

    GET / 200
    GET /history 302
    GET /about 200