Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing the response object from OWIN Middleware

My OWIN middleware is like this. (Framework is ASP.NET Web API).

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;      } } 

Questions:

  1. Is it the recommended practice to derive from OwinMiddleware? I see that in Katana source, some of the middleware classes derive from OwinMiddleware and some do not.

  2. I can see the request headers okay. Setting response header or status code after Next.Invoke in my middleware has no effect on the response returned to the client. But if I set the response header or status before the Next.Invoke call, the response with headers and the status that I set is returned to the client. What is the right way of setting these?

like image 705
Badri Avatar asked Jul 07 '13 06:07

Badri


People also ask

What is OWIN middleware?

OWIN allows web apps to be decoupled from web servers. It defines a standard way for middleware to be used in a pipeline to handle requests and associated responses. ASP.NET Core applications and middleware can interoperate with OWIN-based applications, servers, and middleware.

Which are parts of OWIN application?

OWIN application has different working parts like (Host, Server, Middleware Pipeline, Application).

What is OWIN context?

Owin is a new standardised interface between web servers and web applications. It is meant as a away to break up the tight coupling between ASP.NET and IIS. With IIS supporting Owin it is possible to run other Owin-enabled frameworks such as Nancy on IIS.


2 Answers

  1. Yes, deriving from OwinMiddleware is recommended. The reason some middleware classes don't derive from OwinMiddleware is that either they haven't switched over yet because the class was introduced recently. Or to avoid having the assembly take a dependency on the Microsoft.Owin assembly for some reason.

  2. The probable reason setting stuff on the response after calling Invoke on Next doesn't work is that the response HTTP header gets sent as soon as anyone starts writing to the response body stream. So any changes to status code or HTTP headers after a middleware component starts writing to the response body won't have any effect.

What you can try doing is to use the OnSendingHeaders callback that OWIN provides. Here's how you can use it:

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); } 

Credit to biscuit314 for updating my answer.

like image 187
Youssef Moussaoui Avatar answered Sep 24 '22 05:09

Youssef Moussaoui


I tried to edit Youssef's excellent answer to correct a minor bug and update the example with how the OwinMiddleware now works.

The edit was rejected (well, approved by one, rejected by one for being too minor, and rejected by two for being too major).

Here is that version of Youssef's code:

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); } 
like image 38
biscuit314 Avatar answered Sep 23 '22 05:09

biscuit314