Search code examples
c#owinowin-middleware

How to use OWIN middleware to rewrite versioned url for request to static file?


e.g. I have a file located on the server at /Content/static/home.html. I want to be able to make a request to /Content/v/1.0.0.0/static/home.html (for versioning), and have it rewrite the url so it accesses the file at the correct url, using OWIN middleware.

I am currently using the URL rewrite module (an IIS extension), but I want to make this work in the OWIN pipeline instead.


Solution

  • I found a solution using the Microsoft.Owin.StaticFiles nuget package:

    First make sure this is in your web config so that static file requests are sent to OWIN:

    <system.webServer>
        ...
        <modules runAllManagedModulesForAllRequests="true"></modules>
        ...
    </system.webServer>
    

    Then in your Startup Configuration method, add this code:

    // app is your IAppBuilder
    app.Use(typeof(MiddlewareUrlRewriter));
    app.UseStaticFiles();
    app.UseStageMarker(PipelineStage.MapHandler);
    

    And here is the MiddlewareUrlRewriter:

    public class MiddlewareUrlRewriter : OwinMiddleware
    {
        private static readonly PathString ContentVersioningUrlSegments = PathString.FromUriComponent("/content/v");
    
        public MiddlewareUrlRewriter(OwinMiddleware next)
            : base(next)
        {
        }
    
        public override async Task Invoke(IOwinContext context)
        {
            PathString remainingPath;
            if (context.Request.Path.StartsWithSegments(ContentVersioningUrlSegments, out remainingPath) && remainingPath.HasValue && remainingPath.Value.Length > 1)
            {
                context.Request.Path = new PathString("/Content" + remainingPath.Value.Substring(remainingPath.Value.IndexOf('/', 1)));
            }
    
            await Next.Invoke(context);
        }
    }
    

    For an example, this will allow a GET request to /Content/v/1.0.0.0/static/home.html to retrieve the file at /Content/static/home.html.

    UPDATE: Added app.UseStageMarker(PipelineStage.MapHandler); after the other app.Use methods as it is required to make this work. http://katanaproject.codeplex.com/wikipage?title=Static%20Files%20on%20IIS