URL Rewrite Module (IIS) not working with OWIN Middleware hosted on IIS

1.6k views Asked by At

How can i use the URL Rewrite module together with OWIN middleware?

Having read http://www.asp.net/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline it says I should be able to use OWIN Middleware in the IIS pipeline using the NuGet package:

Microsoft.Owin.Host.SystemWeb

Here is the code I am trying to use:

Web.config:

<system.webServer> <rewrite> <rules> <rule name="pandainserter" patternSyntax="ECMAScript" stopProcessing="true"> <match url=".*test.*" /> <conditions trackAllCaptures="true"> <add input="{REQUEST_URI}" pattern="/(.*?)/(.*)" /> </conditions> <action type="Rewrite" url="http://{HTTP_HOST}:20000/v1/{C:2}" appendQueryString="false" /> </rule> </rules> </rewrite> </system.webServer>

Startup.cs (OWIN):

[assembly: OwinStartup(typeof(ApiUrlRewriter.Startup))]
namespace ApiUrlRewriter
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Run(context =>
            {
                string t = DateTime.Now.Millisecond.ToString();
                return context.Response.WriteAsync(t + " Production OWIN   App");
            });
        }
    }
}

What i want to do, is use the OWIN middleware, to allow CORS and fix the OPTIONS preflight http call (described here: How to make CORS Authentication in WebAPI 2?) while still having the abbility to use the IIS Rewrite module, to rewrite my calls to other sites on the same server.

I am getting this error, for all calls. when using OWIN with the IIS Rewrite module:

HTTP Error 404.4 - Not Found The resource you are looking for does not have a handler associated with it.

Detailed Error Information:

Module IIS Web Core

Notification MapRequestHandler

Handler ExtensionlessUrl-Integrated-4.0

Error Code 0x8007007b

It seems that the Rewrite module is not registered, and i am not sure what i am doing wrong, or if i am even using the right approach to this?

1

There are 1 answers

0
Thomas T On BEST ANSWER

First off, it seems that the IIS URL Rewrite module is not working on IIS Express per default (i have not tried installing it on a local dev machine).

So when running this on a Windows Server 2012, with IIS and the IIS URL Rewrite module installed i could see that my HTTP(s) requests starting getting rewritten.

For further reference I am posting the code I used to fix the CORS Preflight issues, while also having the possiblity to rewrite the HTTP(s) requests to other servers. Please note that this will allow CORS requests from any origin.

Startup.cs class:

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(Startup))]

namespace ApiUrlRewriter
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Use<CorsPreflightMiddlerware>();
            app.Use<CorsAuthorizationMiddleware>();
        }
    }
}

CorsPreflightMiddlerware.cs class:

public class CorsPreflightMiddlerware : OwinMiddleware
{
    private const string HTTP_METHOD_OPTIONS = "OPTIONS";

    public CorsPreflightMiddlerware(OwinMiddleware next)
        : base(next)
    {
    }

    public async override Task Invoke(IOwinContext context)
    {
        IOwinRequest req = context.Request;
        IOwinResponse res = context.Response;

        if (req.Method == HTTP_METHOD_OPTIONS)
        {
            res.StatusCode = (int)HttpStatusCode.OK;
            res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, OPTIONS");
            res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Headers", "Content-Type, Authorization");
        }
        else
        {
            await Next.Invoke(context);
        }
    }
}

CorsAuthorizationMiddleware.cs class:

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

    public async override Task Invoke(IOwinContext context)
    {
        IOwinRequest req = context.Request;
        IOwinResponse res = context.Response;

        var origin = req.Headers.Get("Origin");
        if (!string.IsNullOrEmpty(origin))
        {
            res.Headers.Set("Access-Control-Allow-Origin", origin);
        }
        if (string.IsNullOrEmpty(res.Headers.Get("Access-Control-Allow-Credentials")))
        {
            res.Headers.Set("Access-Control-Allow-Credentials", "true");
        }

        res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, OPTIONS");
        res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Headers", "Content-Type, Authorization");

        await Next.Invoke(context);
    }
}

Web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="test" patternSyntax="ECMAScript" stopProcessing="true">
          <match url=".*test.*" />
          <conditions trackAllCaptures="true">
            <add input="{REQUEST_URI}" pattern="/(.*?)/(.*)" />
          </conditions>
          <action type="Rewrite" url="http://{HTTP_HOST}:20000/v1/{C:2}" appendQueryString="false" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>