6

So I am playing around with Owin and Katana and I want to serve static files in my public folder.

I have a Content folder with stylesheets and a scripts folder.

My Startup:

    public void Configuration(IAppBuilder app)
    {
 #if DEBUG
        //when things go south
        app.UseErrorPage();
  #endif

        // Remap '/' to '.\public\'.
        // Turns on static files and public files.
        app.UseFileServer(new FileServerOptions()
        {
            RequestPath = PathString.Empty,
            FileSystem = new PhysicalFileSystem(@".\public"),
        });

    }

So if if I browse to localhost:8861/ I go the the index.html file in my public folder. That's ok. But I can also browse to my localhost:8861/Content/style.css which I want to block. Everything the user needs should be accessible in the public folder. All the rest should be blocked.

How can I achieve this?

user1613512
  • 3,590
  • 8
  • 28
  • 32

2 Answers2

3

If you need bare-bones file-handling, with absolute control over which files you do, or do not, want to serve you can take complete control with some middle-ware. I did this as I wanted uncached file-serving during development.

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Web;

namespace Owin
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public static class DynamicFileExtension
    {    
        /// <summary>
        /// ONLY use during development
        /// </summary>
        public static void UseDynamicFiles(this IAppBuilder app, string baseDirectory)
        {
            app.Use(new Func<AppFunc, AppFunc>(next => (async context =>
            {
                var method = (string) context["owin.RequestMethod"];
                var requestpath = (string) context["owin.RequestPath"];
                var scheme = (string) context["owin.RequestScheme"];
                var response = (Stream) context["owin.ResponseBody"];
                var responseHeader = (Dictionary<string, string[]>) context["owin.ResponseHeaders"];

                if (method == "GET" && scheme == "http")
                {
                    var fullpath = baseDirectory + requestpath;

                    // block logic...     

                    if (File.Exists(fullpath))
                    {

                        using (var file = File.OpenRead(fullpath))
                        {
                            await file.CopyToAsync(response);
                        }

                        var mime = MimeMapping.GetMimeMapping(fullpath);

                        responseHeader.Add("Content-Type", new[] {mime});

                        return;
                    }
                }

                await next.Invoke(context);
            })));
        }
    }
} 

I wouldn't use it in production, but it did the trick for me.

Meirion Hughes
  • 24,994
  • 12
  • 71
  • 122
1

The configuration of file server is correct and doesn't allow access to other folders. I've checked it within test OWIN self-host project and it works as expected, only public folder can be accessed. I assume that you use IIS to host your OWIN appllication (so your app is not self-hosted). If so, IIS Static File Handler allows aceess to static files and directories (and to your content folder as well). So you can search how to disable access to static files in IIS (can be done in web.config) or how to restrict access to some of them.

You can remove StaticFile Handler from website's configuration, but you should do it carefully because from this moment IIS won't serve static files at all.

<configuration>
    <system.webServer>
        <handlers>
           <remove name="StaticFile" />
        </handlers>
    </system.webServer>
</configuration>
ntl
  • 1,289
  • 1
  • 10
  • 16
  • Thanks this solves the problem indeed. However there seems to be an issue with serving the other files in my public folder. So public contains an index.html, style.css and script.js. Index is served but style.css and script.js give a 404.4. Any ideas? – user1613512 Aug 28 '14 at 21:14
  • Strange, everything works fine on my PC, but i test with self-hosted app. Are you sure that you access these files with next urls yoursite/style.css and not yoursite/public/style.css? These files exist in website's folder, right? – ntl Aug 28 '14 at 21:42
  • One more thing that you can try. Register next middleware as the last one in you configuration: app.Run(context => { return context.Response.WriteAsync(" Wildcard OWIN App"); }); place breakpoint inside the delegate and try to access style.css from the browser. This handler is wildcard middleware that handles all requests that were not handled by other middlewares. If your app will be stopped with the breakpoint, OWIN handles the request but configuration is not correct, otherwise something is wrong with IIS configuration. – ntl Aug 28 '14 at 21:48