🚪 API Gateway

api-gateway-yarp-gateway-designer

Conception d'API Gateway avec YARP (Yet Another Reverse Proxy) en .NET — routing, load balancing, rate limiting, transformations et authentification.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- api-gateway-yarp-gateway-designer --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } api-gateway-yarp-gateway-designer -Launch"

🚀 Déjà installé ?

claude "/api-gateway-yarp-gateway-designer"

Ou tapez /api-gateway-yarp-gateway-designer dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

YARPreverse proxy .NETAPI gateway .NETYARP routingproxy .NETload balancer .NET

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/api-gateway-yarp-gateway-designer ~/.claude/skills/

Payload du plugin : skills/api-gateway-yarp-gateway-designer · source éditable : api-gateway-skills/yarp-gateway-designer

📖 Manuel

API Gateway avec YARP

Critères de décision

BesoinRecommandation
Reverse proxy léger, intégré .NETYARP
Developer portal, quotas avancés, monétisationAzure APIM ou Kong
Multi-tenant avec isolation stricteYARP + middleware tenant + JWT claims
mTLS entre gateway et backendsYARP + HttpClient custom avec cert

Workflow en 6 étapes

1. Installer le package

dotnet add package Yarp.ReverseProxy
# Dernière version stable : 2.2.0 (LTS .NET 8/9)

2. Enregistrer YARP dans Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));

// Optionnel : rate limiting (Microsoft.AspNetCore.RateLimiting)
builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("api-limit", opt =>
    {
        opt.PermitLimit = 100;
        opt.Window = TimeSpan.FromMinutes(1);
        opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        opt.QueueLimit = 10;
    });
    options.RejectionStatusCode = 429;
});

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();
app.MapReverseProxy();
app.Run();

3. Déclarer les routes et clusters (appsettings.json)

{
  "ReverseProxy": {
    "Routes": {
      "payments-route": {
        "ClusterId": "payments-cluster",
        "Match": { "Path": "/api/payments/{**catch-all}" },
        "Transforms": [
          { "PathRemovePrefix": "/api/payments" },
          { "RequestHeader": "X-Gateway-Source", "Set": "yarp-gw" }
        ],
        "RateLimiterPolicy": "api-limit",
        "AuthorizationPolicy": "anonymous"
      },
      "orders-route": {
        "ClusterId": "orders-cluster",
        "Match": {
          "Path": "/api/orders/{**catch-all}",
          "Headers": [{ "Name": "X-Api-Version", "Values": ["v2"], "Mode": "ExactHeader" }]
        },
        "Transforms": [
          { "PathRemovePrefix": "/api/orders" }
        ],
        "AuthorizationPolicy": "authenticated",
        "RateLimiterPolicy": "api-limit"
      }
    },
    "Clusters": {
      "payments-cluster": {
        "LoadBalancingPolicy": "RoundRobin",
        "HealthCheck": {
          "Active": {
            "Enabled": true,
            "Interval": "00:00:30",
            "Timeout": "00:00:10",
            "Path": "/health"
          },
          "Passive": { "Enabled": true }
        },
        "Destinations": {
          "primary":   { "Address": "https://payment-svc-1:8080" },
          "secondary": { "Address": "https://payment-svc-2:8080" }
        }
      },
      "orders-cluster": {
        "LoadBalancingPolicy": "LeastRequests",
        "Destinations": {
          "primary": { "Address": "https://order-svc:8080" }
        }
      }
    }
  }
}

4. Ajouter des transformations par code (claims, tenant, corrélation)

builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
    .AddTransforms(ctx =>
    {
        // Injecter le tenant depuis le JWT dans chaque requête proxiée
        ctx.AddRequestTransform(async reqCtx =>
        {
            var tenantId = reqCtx.HttpContext.User.FindFirst("tenant_id")?.Value;
            if (tenantId is not null)
                reqCtx.ProxyRequest.Headers.TryAddWithoutValidation("X-Tenant-Id", tenantId);

            // Corrélation
            var correlationId = reqCtx.HttpContext.TraceIdentifier;
            reqCtx.ProxyRequest.Headers.TryAddWithoutValidation("X-Correlation-Id", correlationId);
        });

        // Masquer les headers internes sur la réponse
        ctx.AddResponseTransform(async respCtx =>
        {
            respCtx.ProxyResponse?.Headers.Remove("X-Internal-Node");
            await Task.CompletedTask;
        });
    });

5. Health check passif + circuit breaker (Polly)

// Besoin : Microsoft.Extensions.Http.Resilience
builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
    .ConfigureHttpClient((ctx, handler) =>
    {
        // Timeout global par requête proxiée
        handler.ActivityHeadersPropagator = null;
    })
    .AddResilienceHandler("circuit-breaker", builder =>
    {
        builder.AddCircuitBreaker(new HttpCircuitBreakerStrategyOptions
        {
            SamplingDuration = TimeSpan.FromSeconds(30),
            FailureRatio = 0.5,
            MinimumThroughput = 10,
            BreakDuration = TimeSpan.FromSeconds(15)
        });
        builder.AddTimeout(TimeSpan.FromSeconds(5));
    });

6. Rechargement à chaud (hot reload) sans restart

// Recharger les routes/clusters depuis n'importe quelle source dynamique
var proxyConfig = app.Services.GetRequiredService<InMemoryConfigProvider>();
proxyConfig.Update(newRoutes, newClusters);
// Pas besoin de redémarrer le process — YARP recharge instantanément.

Pour un chargement depuis une base de données ou un API config, implémenter IProxyConfigProvider.

Patterns de routing courants

CasConfig YARP
Path prefix routingMatch.Path: "/api/svc/{**catch-all}" + PathRemovePrefix
Header-based routing (versioning)Match.Headers[].Values + Mode: ExactHeader
Query string routingMatch.QueryParameters[].Values
Host-based routing (multi-tenant)Match.Hosts: ["tenant1.api.com"]
Weighted routing (canary)Deux destinations, Weight dans les clusters
Rewrite complet de cheminPathPattern: "/v2/{**catch-all}"

Politiques de load balancing

PolitiqueUsage
RoundRobinDistribution uniforme, cas général
LeastRequestsBackends hétérogènes (latence variable)
RandomTests, benchmarks
PowerOfTwoChoicesHaute charge, meilleure distribution que RoundRobin
FirstAlphabeticalFailover ordonné, actif/passif

Garde-fous et anti-patterns

Ne pas faire :

Pièges courants :

Bonnes pratiques 2026