fengling-gateway/Middleware/TenantRoutingMiddleware.cs

64 lines
1.9 KiB
C#

using Microsoft.Extensions.Options;
using System.Text.RegularExpressions;
using YarpGateway.Services;
namespace YarpGateway.Middleware;
public class TenantRoutingMiddleware
{
private readonly RequestDelegate _next;
private readonly IRouteCache _routeCache;
private readonly ILogger<TenantRoutingMiddleware> _logger;
public TenantRoutingMiddleware(
RequestDelegate next,
IRouteCache routeCache,
ILogger<TenantRoutingMiddleware> logger)
{
_next = next;
_routeCache = routeCache;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var tenantId = context.Request.Headers["X-Tenant-Id"].FirstOrDefault();
if (string.IsNullOrEmpty(tenantId))
{
await _next(context);
return;
}
var path = context.Request.Path.Value ?? string.Empty;
var serviceName = ExtractServiceName(path);
if (string.IsNullOrEmpty(serviceName))
{
await _next(context);
return;
}
var route = _routeCache.GetRoute(tenantId, serviceName);
if (route == null)
{
_logger.LogWarning("Route not found - Tenant: {Tenant}, Service: {Service}", tenantId, serviceName);
await _next(context);
return;
}
context.Items["DynamicClusterId"] = route.ClusterId;
var routeType = route.IsGlobal ? "global" : "tenant-specific";
_logger.LogInformation("Tenant routing - Tenant: {Tenant}, Service: {Service}, Cluster: {Cluster}, Type: {Type}",
tenantId, serviceName, route.ClusterId, routeType);
await _next(context);
}
private string ExtractServiceName(string path)
{
var match = Regex.Match(path, @"/api/(\w+)/?");
return match.Success ? match.Groups[1].Value : string.Empty;
}
}