6

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.

Ben Wilde
  • 5,552
  • 2
  • 39
  • 36

3 Answers3

10

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

Ben Wilde
  • 5,552
  • 2
  • 39
  • 36
2

Theoretically you can do this using UseStaticFiles with options instead of a separate UrlRewriter middleware:

string root = AppDomain.CurrentDomain.BaseDirectory;
var staticFilesOptions = new StaticFileOptions();
staticFilesOptions.RequestPath = new PathString("/foo");
staticFilesOptions.FileSystem = 
          new PhysicalFileSystem(Path.Combine(root, "web"));
app.UseStaticFiles(staticFilesOptions);

But see this question as it doesn't currently seem to work.

Community
  • 1
  • 1
Ian Mercer
  • 38,490
  • 8
  • 97
  • 133
  • Can you show how this could account for any version in the url, per the example in the question? – Ben Wilde Jul 08 '14 at 16:45
  • It can't handle "any" version, you'd need to repeat it for each version that you want, but the question only had one version in it. If you need all versions to be mapped to the same set of resources then yes, your Url rewriter may be more appropriate. – Ian Mercer Jul 08 '14 at 17:58
  • It does not work for me. I use Owin StaticFiles middleware version 4.0. How can i diagnose? – Vunb Feb 28 '18 at 00:58
2

There is now an Owin.UrlRewrite project in here : https://github.com/gertjvr/owin.urlrewrite

It is syntactically based on Apache mod_rewrite.

Jani Hyytiäinen
  • 5,293
  • 36
  • 45