How to configure an ASP.NET Core multi microservice application and Azure AKS ingress routes so that it doesn't break resources in the wwwroot folder

巧了我就是萌 提交于 2019-12-06 09:17:05

Problem

It seems that your proxy rewrites the path.

  • Before proxy: /blog/images/banner1.png
  • After proxy: /images/banner1.png

Asp generates absolute (host relative) links (path only, but starting with a slash "/"). That means, we have to tell the framework that it must prefix all URLs with "/blog".

Solution

Do this (for asp.net core 2.1) by inserting the following snipped in your Startup class:

app.Use((context, next) =>
{
    context.Request.PathBase = new PathString("/blog");
    return next();
});

Code sample from: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1

Insert this snipped before any other middleware in your Configure method.

You can test this on your local machine too. All generated links should be prefixed with "/blog" - so they will be broken on your dev machine.

Use Configuration

You will need to make it configurable e.g. like so:

        var basePath = Configuration.GetSection("BASE_PATH").Value;
        if (basePath != null)
        {
            Console.WriteLine($"Using base path '{basePath}'");
            // app.Use().. goes here
        }

(Assuming you read configuration from env vars in your startup.)

… and provide this env var in your kubernetes depoyment:

...
 containers:
  - name: myapp
    image: myappimage
    env:
      - name: BASE_PATH
        value: "/blog"

You want to annotate your Ingress with nginx.ingress.kubernetes.io/rewrite-target. For example:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: mydnsname.westeurope.cloudapp.azure.com
    http:
      paths:
      - backend:
          serviceName: headless-cms-svc
          servicePort: 80
        path: /
      - backend:
          serviceName: blog-svc
          servicePort: 80
        path: /blog

Hope it helps!

Follow these steps to run your code:

  1. deployment: pass environment variable with path base in k8s-yaml-file
apiVersion: apps/v1
kind: Deployment
# ..
spec:
  # ..
  template:
    # ..
    spec:
      # ..
      containers:
        - name: test01
          image: test.io/test:dev
          # ...
          env:
            # define custom Path Base (it should be the same as 'path' in Ingress-service)
            - name: API_PATH_BASE # <---
              value: "blog"
  1. program: enable loading environment params in Program.cs
var builder = new WebHostBuilder()
    .UseContentRoot(Directory.GetCurrentDirectory())
    // ..
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        // ..  
        config.AddEnvironmentVariables(); // <---
        // ..
    })
    // ..
  1. startup: apply UsePathBaseMiddleware in Startup.cs
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    private readonly IConfiguration _configuration;

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        var pathBase = _configuration["API_PATH_BASE"]; // <---

        if (!string.IsNullOrWhiteSpace(pathBase))
        {
            app.UsePathBase($"/{pathBase.TrimStart('/')}");
        }

        app.UseStaticFiles(); // <-- StaticFilesMiddleware must follow UsePathBaseMiddleware

        // ..

        app.UseMvc();
    }

    // ..
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!