You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Kestrel在不同相对路径下托管两个Web应用?

更优解决方案推荐

方案1:直接为每个子应用配置路径基址(无需反向代理)

这是最贴近你原来IIS Express使用习惯的方案,无需额外引入YARP,直接让每个子应用运行在带前缀的路径下,静态文件和路由会自动适配。

配置步骤:

  1. 修改子应用的launchSettings.json:
    给每个应用指定包含子路径的applicationUrl,比如:

    // Foo应用的launchSettings.json
    "profiles": {
      "FooApp": {
        "commandName": "Project",
        "applicationUrl": "https://localhost:1000/foo",
        "environmentVariables": {
          "ASPNETCORE_ENVIRONMENT": "Development"
        }
      }
    }
    
    // Bar应用的launchSettings.json
    "profiles": {
      "BarApp": {
        "commandName": "Project",
        "applicationUrl": "https://localhost:1000/bar",
        "environmentVariables": {
          "ASPNETCORE_ENVIRONMENT": "Development"
        }
      }
    }
    
  2. 在子应用的Program.cs中添加PathBase配置:

    var builder = WebApplication.CreateBuilder(args);
    // 读取启动时的路径基址,或者直接指定"/foo"
    app.UsePathBase(builder.Configuration["ASPNETCORE_APPL_PATH"] ?? "/foo");
    
    // 其他中间件配置(静态文件、路由等)保持不变
    app.UseStaticFiles();
    app.MapControllers();
    

这样配置后,~/foo.js会自动解析为/foo/foo.js,和你原来在IIS Express中的行为完全一致,无需修改任何静态资源引用或API路由代码。

方案2:优化YARP配置解决路由问题(适合必须用反向代理的场景)

如果因为生产部署等原因必须使用YARP,可通过完善路径转换和响应重写配置解决静态文件问题:

核心配置要点:

  1. 正确配置路径转换规则:
    在反向代理的appsettings.json中,确保路由转换时移除前缀并正确传递路径:

    "ReverseProxy": {
      "Routes": {
        "foo_route": {
          "ClusterId": "foo_cluster",
          "Match": {
            "Path": "/foo/{**catch-all}"
          },
          "Transforms": [
            { "PathRemovePrefix": "/foo" },
            { "RequestHeader": "X-Forwarded-PathBase", "Set": "/foo" }
          ]
        },
        "bar_route": {
          "ClusterId": "bar_cluster",
          "Match": {
            "Path": "/bar/{**catch-all}"
          },
          "Transforms": [
            { "PathRemovePrefix": "/bar" },
            { "RequestHeader": "X-Forwarded-PathBase", "Set": "/bar" }
          ]
        }
      },
      "Clusters": {
        "foo_cluster": {
          "Destinations": {
            "foo_app": { "Address": "https://localhost:1001/" }
          }
        },
        "bar_cluster": {
          "Destinations": {
            "bar_app": { "Address": "https://localhost:1002/" }
          }
        }
      }
    }
    
  2. 子应用启用转发头支持:
    在每个子应用的Program.cs中添加转发头配置,让应用识别代理传递的PathBase:

    app.UseForwardedHeaders(new ForwardedHeadersOptions {
      ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost
    });
    
  3. 响应重写修正静态资源路径:
    若子应用返回的响应中包含绝对路径(如API返回的链接),可添加YARP的响应转换规则,将后端地址替换为代理地址:

    "Transforms": [
      { "ResponseHeader": "Location", "Replace": "https://localhost:1001/", "With": "https://localhost:1000/foo/" }
    ]
    

方案3:用宿主应用挂载多个子应用(适合统一部署场景)

创建一个空的.NET 8 Web应用作为宿主,将Foo和Bar应用作为中间件挂载到对应子路径下,实现单入口访问:

宿主应用Program.cs示例:

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

// 挂载Foo应用到/foo路径
app.Map("/foo", fooApp => {
    var fooBuilder = WebApplication.CreateBuilder(new WebApplicationOptions {
        ContentRootPath = Path.GetDirectoryName(typeof(Foo.Program).Assembly.Location),
        WebRootPath = Path.Combine(Path.GetDirectoryName(typeof(Foo.Program).Assembly.Location), "wwwroot")
    });
    // 调用Foo应用的服务配置
    Foo.Program.ConfigureServices(fooBuilder.Services);
    var fooWebApp = fooBuilder.Build();
    // 调用Foo应用的中间件配置
    Foo.Program.Configure(fooWebApp, fooWebApp.Environment);
    fooApp.Use(fooWebApp);
});

// 挂载Bar应用到/bar路径
app.Map("/bar", barApp => {
    var barBuilder = WebApplication.CreateBuilder(new WebApplicationOptions {
        ContentRootPath = Path.GetDirectoryName(typeof(Bar.Program).Assembly.Location),
        WebRootPath = Path.Combine(Path.GetDirectoryName(typeof(Bar.Program).Assembly.Location), "wwwroot")
    });
    Bar.Program.ConfigureServices(barBuilder.Services);
    var barWebApp = barBuilder.Build();
    Bar.Program.Configure(barWebApp, barWebApp.Environment);
    barApp.Use(barWebApp);
});

app.Run("https://localhost:1000");

注意事项:

  • 需将子应用的ConfigureServices和Configure方法改为public,方便宿主调用。
  • 子应用无需单独启动,宿主启动时会自动加载两个子应用。

内容的提问来源于stack exchange,提问作者Vivian River

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 15:20:00