web-dev-qa-db-fra.com

Modification de l'objet de réponse à partir du middleware OWIN

Mon middleware OWIN est comme ça. (Le framework est l'API Web ASP.NET).

public class MyMiddleware : OwinMiddleware
{
    public MyMiddleware(OwinMiddleware next) : base(next) { }

    public override async Task Invoke(OwinRequest request, OwinResponse response)
    {
        var header = request.GetHeader("X-Whatever-Header");

        await Next.Invoke(request, response);

        response.SetHeader("X-MyResponse-Header", "Some Value");
        response.StatusCode = 403;

    }
}

Des questions:

  1. Est-ce la pratique recommandée pour dériver de OwinMiddleware? Je vois que dans la source Katana, certaines classes de middleware dérivent de OwinMiddleware et d'autres non.

  2. Je vois bien les en-têtes de demande. Définition de l'en-tête de réponse ou du code d'état après Next.Invoke dans mon middleware n'a aucun effet sur la réponse retournée au client. Mais si je définis l'en-tête de réponse ou le statut avant le Next.Invoke appel, la réponse avec des en-têtes et le statut que j'ai défini est renvoyé au client. Quelle est la bonne façon de les régler?

28
Badri
  1. Oui, il est recommandé de dériver de OwinMiddleware. La raison pour laquelle certaines classes de middleware ne dérivent pas d'OwenMiddleware est qu'elles n'ont pas encore basculé car la classe a été introduite récemment. Ou pour éviter que l'assembly ne dépende de l'assembly Microsoft.Owin pour une raison quelconque.

  2. La raison probable pour laquelle la configuration de la réponse après avoir appelé Invoke on Next ne fonctionne pas est que l'en-tête HTTP de la réponse est envoyé dès que quelqu'un commence à écrire dans le flux du corps de la réponse. Ainsi, toute modification du code d'état ou des en-têtes HTTP après qu'un composant middleware commence à écrire dans le corps de la réponse n'aura aucun effet.

Ce que vous pouvez essayer de faire est d'utiliser le rappel OnSendingHeaders fourni par OWIN. Voici comment vous pouvez l'utiliser:

public override async Task Invoke(IOwinContext context)
{
   var response = context.Response;
   var request =  context.Request;

   response.OnSendingHeaders(state =>
   {
       var resp = (OwinResponse)state;
       resp.Headers.Add("X-MyResponse-Header", "Some Value");
       resp.StatusCode = 403;
       resp.ReasonPhrase = "Forbidden";
    }, response);

  var header = request.Headers["X-Whatever-Header"];

  await Next.Invoke(context);
}

Nous remercions biscuit314 pour avoir mis à jour ma réponse.

29
Youssef Moussaoui

J'ai essayé d'éditer l'excellente réponse de Youssef pour corriger un bogue mineur et mettre à jour l'exemple avec la façon dont OwinMiddleware fonctionne maintenant.

Le montage a été rejeté (enfin, approuvé par un, rejeté par un pour être trop mineur, et rejeté par deux pour être trop majeur).

Voici cette version du code de Youssef:

public override async Task Invoke(IOwinContext context)
{
  var response = context.Response;
  var request =  context.Request;

  response.OnSendingHeaders(state =>
    {
        var resp = (OwinResponse)state;
        resp.Headers.Add("X-MyResponse-Header", "Some Value");
        resp.StatusCode = 403;
        resp.ReasonPhrase = "Forbidden"; // if you're going to change the status code
                                         // you probably should also change the reason phrase
    }, response);

  var header = request.Headers["X-Whatever-Header"];

  await Next.Invoke(context);
}
9
biscuit314

J'ai utilisé ce code pour obtenir le temps pris par chaque demande.

appBuilder.Use(async (context, next) =>
        {
            var watch = new Stopwatch();
            watch.Start();
            await next();
            watch.Stop();
            context.Response.Headers.Set("ResponseTime", watch.Elapsed.Seconds.ToString());
        });
0
Deependra Kushwah