aspnet/FileSystem

DefaultFilesMiddleware in conjunction with EmbeddedFileProvider and subpaths

muratg opened this issue · 5 comments

From @avanderhoorn on January 3, 2017 6:10

The behaviour of DefaultFilesMiddleware doesn't seem quite right when used in conjunction with EmbeddedFileProvider and subpaths. Specifically if my url was "localhost:3000/static/client/" and my EmbeddedFileProviders baseNamespace was setup to point to static, I would expect that translate through to and look for "localhost:3000/static/client/index.html"... this is not the case however.

Specifically, in scenarios where the EmbeddedFileProvider has been setup as described, the DefaultFilesMiddleware fails to find a match as the subpath.Value (in the first link below below) is equal to /client/ which causes the EmbeddedFileProvider to short circuit (in the second link below):

Based on the comment in GetDirectoryContents, I understand why this is the case - // Non-hierarchal. but in the context of how this is used within DefaultFilesMiddleware it seems like the wrong decision, or at the very least, very limiting - as the way the logic is setup, it can only ever support matching defaults at the root level.

I can think of a few different solutions to this problem, but before putting further energy into this, I wanted to see if there is any desire to support this use case?

Copied from original issue: aspnet/StaticFiles#164

From @Tratcher on January 3, 2017 6:53

Yes, this is a known limitation of EmbeddedFileProvider and that's where any enhancements would need to be made.

From @avanderhoorn on January 3, 2017 17:22

I'm happy to bring this up there, but before putting further energy into this, I wanted to see if there is any desire to support this use case?

From @Tratcher on January 3, 2017 17:52

It has come up before, though I can't find the thread at the moment. Yes, it would be nice to make it work eventually.

If I follow this correctly, I think users could overcome this limitation using my InMemoryFileProvider. ?

For example, this test shows taking resource embedded @ Dazinator.AspNet.Extensions.FileProviders.Tests.Resources.myresource.txt, and then serving it on a subpath /some/folder/myfile.txt - which is completely customised.


  [Fact]
        public void GetFileInfo_ReturnsFileInfo_ForEmbeddedFile()
        {
            using (var provider = new InMemoryFileProvider())
            {
                var embeddedFileInfo = new EmbeddedFileInfo(GetAssemblyFromType(this.GetType()),
                    $"Dazinator.AspNet.Extensions.FileProviders.Tests.Resources.myresource.txt",
                    "myfile.txt");

                provider.Directory.AddFile("/some/folder", embeddedFileInfo);

                var info = provider.GetFileInfo("/some/folder/myfile.txt");
                using (var stream = info.CreateReadStream())
                {
                    Assert.NotNull(stream);
                    Assert.True(stream.Length > 0);
                }

            }
        }

Obiously you would need to set up the InMemoryFileProvider on startup, and include it in the IHostingEnvironments WebRootFileProvider (or static files options fileproviders)

The main reason this functionality came about though was to overcome the issue that embedded file provider is non hierarchical. If you set up your resources as above, you can set them up into hierarchical folder structures - and GetDirectoryContents and everything else will work with them.

This issue was moved to aspnet/Home#2543