Asons
Asons

Reputation: 87191

UseStaticFiles, set folder dynamically based on host

I need to allow for individual hosts to have their own folder serving static files.

Started out doing like this:

var hosts = cfg.GetSection("AppSettings:AvailableHosts").Get<string[]>();

foreach (var host in hosts)
{
    app.UseWhen(ctx => ctx.Request.Host.Host == host, appBuilder =>
    {
        appBuilder.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(builder.Environment.ContentRootPath, host, "res")),
            RequestPath = "/res"
        });
    });
}

The downside with this is, I need to keep updating the "appsettings.json" all the time.

I'd like to find a solution where this could work dynamically/at runtime, so wonder if there is a way doing that?

Upvotes: 0

Views: 68

Answers (1)

Asons
Asons

Reputation: 87191

As suggested by @DavidG, here's one option using a custom file provider.

(and if there's a better, or more correct, way writing this, please edit mine or post a new)

In program.cs

app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments("/res", StringComparison.OrdinalIgnoreCase), appBuilder =>
{    
    appBuilder.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new HostResFileProvider(appBuilder.ApplicationServices.GetRequiredService<IHttpContextAccessor>(), builder.Environment),
        RequestPath = "/res"
    });
});

And the IFileProvider class

public class HostResFileProvider : IFileProvider
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly IWebHostEnvironment _env;

    public HostResFileProvider(IHttpContextAccessor httpContextAccessor, IWebHostEnvironment env)
    {
        _httpContextAccessor = httpContextAccessor;
        _env = env;
    }

    public IDirectoryContents GetDirectoryContents(string subpath)
    {
        return _env.WebRootFileProvider.GetDirectoryContents(subpath);
    }


    public IFileInfo GetFileInfo(string subpath)
    {
        string host = _httpContextAccessor.HttpContext.Request.Host.Host;

        if (!string.IsNullOrWhiteSpace(host))
        {    
            return _env.ContentRootFileProvider.GetFileInfo(Path.Combine(host, subpath));;
        }

        return _env.WebRootFileProvider.GetFileInfo(subpath);
    }


    public IChangeToken Watch(string filter)
    {
        return _env.WebRootFileProvider.Watch(filter);
    }
}

Upvotes: 0

Related Questions