다음을 통해 공유


YARP 구성 필터

소개

경로, 클러스터 및 대상에 대한 YARP 구성은 구성 파일 또는 구성 공급자에서 로드할 수 있습니다. 구성 필터를 사용하여 유효성을 검사하고 적용하기 전에 해당 원시 입력을 수정할 수 있습니다.

필터는 다음과 같은 다양한 용도로 사용할 수 있습니다.

  • 배포 환경과 같은 다른 원본의 데이터로 구성 필드 보완
  • 시스템 기본값 적용
  • 일반 설정 적용 및 정책 적용
  • 자리 표시자 값을 대체하기
  • 정규화 및 오류 수정

AddConfigFilter

구성 필터는 AddConfigFilter API를 사용하여 종속성 주입 시스템에 등록됩니다. 모든 수의 고유 필터를 추가할 수 있으며 추가된 순서대로 적용됩니다.

// Load the configuration and register a config filter
services.AddReverseProxy()
    .LoadFromConfig(_configuration.GetSection("ReverseProxy"))
    .AddConfigFilter<CustomConfigFilter>();

IProxyConfigFilter

구성 필터는 IProxyConfigFilter 인터페이스를 사용하여 작성됩니다. 필터는 DI에 등록되므로 종속성을 삽입하는 생성자를 정의할 수 있습니다.

구성이 로드되거나 다시 로드될 때마다 각 경로 및 클러스터에 대해 필터가 호출됩니다. 수정되지 않은 원래 입력 또는 수정된 복사본을 반환하도록 선택할 수 있습니다. C# 9 레코드 구문 수정된 복사본을 만드는 데 편리합니다.

다음은 환경 변수의 대상 주소를 채우고 경로의 순서 필드를 1로 설정하는 예제입니다.

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Yarp.ReverseProxy.Configuration;

namespace Yarp.Sample;

public class CustomConfigFilter : IProxyConfigFilter
{
    // Matches {{env_var_name}}
    private readonly Regex _exp = new("\\{\\{(\\w+)\\}\\}");

    // This sample looks at the destination addresses and any of the form {{key}} will be modified, looking up the key
    // as an environment variable. This is useful when hosted in Azure etc, as it enables a simple way to replace
    // destination addresses via the management console
    public ValueTask<ClusterConfig> ConfigureClusterAsync(ClusterConfig origCluster, CancellationToken cancel)
    {
        // Each cluster has a dictionary of destinations, which is read-only, so we'll create a new one with our updates 
        var newDests = new Dictionary<string, DestinationConfig>(StringComparer.OrdinalIgnoreCase);

        foreach (var d in origCluster.Destinations)
        {
            var origAddress = d.Value.Address;
            if (_exp.IsMatch(origAddress))
            {
                // Get the name of the env variable from the destination and lookup value
                var lookup = _exp.Matches(origAddress)[0].Groups[1].Value;
                var newAddress = Environment.GetEnvironmentVariable(lookup);

                if (string.IsNullOrWhiteSpace(newAddress))
                {
                    throw new ArgumentException($"Configuration Filter Error: Substitution for '{lookup}' in cluster '{d.Key}' not found as an environment variable.");
                }

                // using c# 9 "with" to clone and initialize a new record
                var modifiedDest = d.Value with { Address = newAddress };
                newDests.Add(d.Key, modifiedDest);
            }
            else
            {
                newDests.Add(d.Key, d.Value);
            }
        }

        return new ValueTask<ClusterConfig>(origCluster with { Destinations = newDests });
    }

    public ValueTask<RouteConfig> ConfigureRouteAsync(RouteConfig route, ClusterConfig cluster, CancellationToken cancel)
    {
        // Example: do not let config based routes take priority over code based routes.
        // Lower numbers are higher priority. Code routes default to 0.
        if (route.Order.HasValue && route.Order.Value < 1)
        {
            return new ValueTask<RouteConfig>(route with { Order = 1 });
        }

        return new ValueTask<RouteConfig>(route);
    }
}