C# 使用 YARP 建立反向代理 示範

YARP 的意思是另一個反向代理(Yet Another Reverse Proxy),是微軟為了解決內部對反向代理(reverse proxy)的需求而建立的,以套件的方式發布到 NuGet ,目前來到 2.0.1 版

建立反向代理專案

YARP 2.0.0 以上要求使用 .NET 6 或以上的版本,使用指令建立 .NET 6 的 ASP.NET Core 專案
    
dotnet new web -n MyProxy -f net6.0
    

安裝套件

先使用 NuGet 安裝 Yarp.ReverseProxy 套件,或是使用 .NET CLI 執行以下指令安裝
	
dotnet add package Yarp.ReverseProxy
    

啟用反向代理

在 Program.cs 中加入以下程式碼:
    
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddReverseProxy() // 增加反向代理服務
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy")); // 讀取設定檔的 ReverseProxy 區塊

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.MapReverseProxy(); // 啟用反向代理路由

app.Run();
    

在設定檔中加入以下內容,即可將所有路徑反向代理到 http://localhost:3333/
    
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ReverseProxy": {
    "Routes": {
      "route1": {
        "ClusterId": "cluster1",
        "Match": {
          "Path": "{**catch-all}"
        }
      }
    },
    "Clusters": {
      "cluster1": {
        "Destinations": {
          "destination1": {
            "Address": "http://localhost:3333/"
          }
        }
      }
    }
  }
}
    

多組設定

上面示範的是只有一組設定,下面示範的是會將所有 /aaa 開頭的都指向到 http://localhost:8888/ ,並且會從路徑中移除 /aaa
    
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "Urls": "http://localhost:8010/;https://localhost:8011/",
  "AllowedHosts": "*",
  "ReverseProxy": {
    "Routes": {
      "route1": {
        "ClusterId": "cluster1",
        "Match": {
          "Path": "{**catch-all}"
        }
      },
      "route2": {
        "ClusterId": "cluster2",
        "Match": {
          "Path": "/aaa/{**catch-all}"
        },
        "Transforms": [
          {
            "PathRemovePrefix": "/aaa"
          }
        ]
      }
    },
    "Clusters": {
      "cluster1": {
        "Destinations": {
          "destination1": {
            "Address": "http://localhost:3333/"
          }
        }
      },
      "cluster2": {
        "Destinations": {
          "destination1": {
            "Address": "http://localhost:8888/"
          }
        }
      }
    }
  }
}

    


註: 至少要建立一個萬用的 route ,不然會拋出下列例外:
    
Unhandled exception. System.InvalidOperationException: Unable to load or apply the proxy configuration.
 ---> System.AggregateException: The proxy config is invalid. (Invalid path '/aaa{**catch-all}' for route 'route1'.)
 ---> System.ArgumentException: Invalid path '/aaa{**catch-all}' for route 'route1'.
 ---> Microsoft.AspNetCore.Routing.Patterns.RoutePatternException: A path segment that contains more than one section, such as a literal section or a parameter, cannot contain a catch-all parameter.

    

變更網址

預設會依照專案內的 Properties\launchSettings.json 設定檔中的 profiles > MyProxy(專案名稱) > applicationUrl 來指定網址
    
{
  "profiles": {
    "MyProxy": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7279;http://localhost:5052",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}
    

除了變更上面的設定值外,還可以直接在 appsettings.json 設定檔中加入下面這行指定:
(註: 記得 Json 的結尾逗號 ',')
    
{
  "Urls":"http://localhost:8010/;https://localhost:8011/"
}
    


延伸閱讀: ASP.NET Core 變更預設 port 的方式

隱藏 Log

如果是既有的專案加上這個反向代理套件,有時候會在 Log 中看到反向代理的 Log,可以在設定檔中加入這行來排除 Log
    
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Yarp": "Warning"
    }
  }
}
    



參考資料:
YARP
YARP - Configuration Files
GitHub - microsoft/reverse-proxy
GitHub - kkbruce/YARP-docs-zh-Hant

留言