简体   繁体   中英

How can I server images on a subdomain with Asp.Net Core 2.2?

I have an app that is written using C# on the top of the Asp.Net Core 2.2 framework.

The app is designed to show lots of photos. I am trying to improve the app performance by utilizing a Cookie-Free subdomain to reduce the traffic when requesting images from the server.

Currently, I utilize the UseStaticFiles extension, to allow accessing my photos using the following URL https://example.com/photos/a/b/c/1.jpg . Instead, now I want to change the URL to serve these photos using https://photos.example.com/a/b/c/1.jpg . Here is how I use UseStaticFiles extension to provide images currently

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = blobFileProvider,
    RequestPath = "/photos",
    OnPrepareResponse = ctx =>
    {
        const int durationInSeconds = 3600 * 72;

        ctx.Context.Response.Headers[HeaderNames.CacheControl] = "public,max-age=" + durationInSeconds;
    }
});

I am sure I can create a second app for the images, but how can I use Asp.Net Core 2.2 framework to serve my images on photos.example.com subdomain without the need for a second running app?

I would branch the request pipeline using MapWhen method. Then apply the UseStaticFiles as you have done.

The end result will look like this

app.MapWhen(context => {
    return context.Request.Host.Value.StartsWith("photos.", StringComparison.OrdinalIgnoreCase)
} (appBuilder) =>
{
    appBuilder.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = blobFileProvider,
        OnPrepareResponse = ctx =>
        {
            const int durationInSeconds = 3600 * 72;
            ctx.Context.Response.Headers[HeaderNames.CacheControl] = "public,max-age=" + durationInSeconds;
        }   
    });
});

I put any performance critical stuff into my MiddleWare. Within the MiddleWare you can check the host and/or the path and write a file directly to the response stream and short-circuit the return.

You just have to add a MiddleWare class that looks something like this:

using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;

public class Middle
{
  private readonly RequestDelegate _next;

  public Middle(RequestDelegate next)
  {
    _next = next;
  }

  public async Task Invoke(HttpContext context)
  {
    string req_path = context.Request.Path.Value;
    string host = context.Request.Host.Value;

    if (host.StartsWith("photos.")) {
      context.Response.Clear();
      context.Response.StatusCode = 200;
      context.Response.ContentType = "<Image Type>";
      await context.Response.SendFileAsync(<file path>);
      return;
    }
    else {
      await _next.Invoke(context);
    }
  }
}

Then in your Configure method of Startup.cs you have to use the MiddleWare:

app.UseMiddleware<Middle>();

How you get your server to treat the subdomain and bare domain as the same app depends on what server you're using. In IIS you could just create 2 different sites that are pointed at the same app and use the same app pool (at least this worked in old .NET). You may also be able to just give the images site a unique port number, because I think cookies are specific to the host port combo.

You will want to make sure this middle ware runs first, so it can prevent anything after it from running. Unless of course you want some kind of auth to run for static content

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM