.net api代理

背景

存在数量较多需要中转调用的接口,不可能每个接口都定义实体然后转发,可以直接编写通用的代理服务。

特殊逻辑

如果存在需要移除的url参数可以使用RemoveParamFromQueryString移除,本文需要移除参数中的__EnvID,根据实际情况调整。

调用方法

继承AgentBaseController 后创建接口

     /// <summary>
     /// 无代码系统列表(系统下拉)
     /// </summary>
     [HttpGet]
     [ApiIgnore]
     public IActionResult GetSystemList([FromQuery] EnvAgentDto dto)
     {
         var envBaseUrl="http://127.0.0.1:7000";

         var result = GetProxy("/api/NC/System/GetList", envBaseUrl);
         return result;
     }

     /// <summary>
     /// 
     /// </summary>
     [HttpPost]
     [ApiIgnore]
     public IActionResult GetTranslateValueInfo([FromQuery] EnvAgentDto dto)
     {
         var envBaseUrl="http://127.0.0.1:7000";

         var result = PostProxy("/api/common/TranslateValue/GetTranslateValueInfo", envBaseUrl);
         return result;
     }

     /// <summary>
     /// 
     /// </summary>
     [HttpPost]
     [ApiIgnore]
     public IActionResult GetPageList([FromQuery] EnvAgentDto dto)
     {
         var env = sysEnvService.GetByID(dto.__EnvID);
         ExceptionHelper.CheckNull(env, "EnvNull");
         callerAgent.IsAlive(env.EnvCode);

         var result = PostProxy("/api/NC/Page/GetList", env.EnvCfgAddress);
         return result;
     }

代理逻辑

 public class AgentBaseController : ServerBaseController
{
    private readonly string ContentType = "application/json; charset=utf-8";
    //private readonly string ContextType ="application/json";

    private readonly IHttpClientFactory _httpClientFactory;

    public AgentBaseController(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    protected IActionResult GetProxy(string path, string baseUrl)
    {
        if (string.IsNullOrWhiteSpace(baseUrl))
            return BadRequest(new { error = "Missing 'baseUrl' query parameter." });

        var filteredQuery = RemoveParamFromQueryString(Request.QueryString, "__EnvID");
        var targetUrl = $"{baseUrl.TrimEnd('/')}{path}{filteredQuery}";

        var client = _httpClientFactory.CreateClient();
        var requestMessage = new HttpRequestMessage(HttpMethod.Get, targetUrl);
        CopyHeaders(requestMessage);

        var response = client.SendAsync(requestMessage).Result;
        var content = response.Content.ReadAsStringAsync().Result;

        // 返回 JSON 格式,透传下游状态码
        return new ContentResult
        {
            Content = content,
            ContentType = ContentType,
            StatusCode = (int)response.StatusCode
        };
    }

    protected IActionResult PostProxy(string path, string baseUrl)
    {
        if (string.IsNullOrWhiteSpace(baseUrl))
            return BadRequest(new { error = "Missing 'baseUrl' query parameter." });

        Request.EnableBuffering();
        string bodyContent;
        using (var reader = new StreamReader(Request.Body, Encoding.UTF8, leaveOpen: true))
        {
            bodyContent = reader.ReadToEndAsync().Result;
            Request.Body.Position = 0;
        }

        var filteredQuery = RemoveParamFromQueryString(Request.QueryString, "__EnvID");
        var targetUrl = $"{baseUrl.TrimEnd('/')}{path}{filteredQuery}";

        var client = _httpClientFactory.CreateClient();
        var requestMessage = new HttpRequestMessage(HttpMethod.Post, targetUrl);
        CopyHeaders(requestMessage);
        requestMessage.Content = new StringContent(bodyContent, Encoding.UTF8, Request.ContentType ?? ContentType);

        var response = client.SendAsync(requestMessage).Result;
        var content = response.Content.ReadAsStringAsync().Result;

        return new ContentResult
        {
            Content = content,
            ContentType = ContentType,
            StatusCode = (int)response.StatusCode
        };
    }

    private static string RemoveParamFromQueryString(QueryString queryString, string paramName)
    {
        if (!queryString.HasValue)
            return string.Empty;

        var query = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(queryString.Value);
        query.Remove(paramName);

        var pairs = query.SelectMany(kv => kv.Value, (kv, v) => $"{kv.Key}={Uri.EscapeDataString(v)}");
        return pairs.Any() ? "?" + string.Join("&", pairs) : string.Empty;
    }

    private void CopyHeaders(HttpRequestMessage requestMessage)
    {
        var excludedHeaders = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
        {
            "Host", "Content-Length", "Transfer-Encoding", "Connection",
            "Keep-Alive", "Upgrade", "Proxy-Authorization", "Proxy-Connection",
            "TE", "Trailer"
        };

        foreach (var header in Request.Headers)
        {
            var key = header.Key;
            if (excludedHeaders.Contains(key))
                continue;
            if (key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase))
                continue;

            if (!requestMessage.Headers.TryAddWithoutValidation(key, header.Value.ToArray()))
            {
                // 忽略无法添加的头部
            }
        }
    }
}
posted @ 2026-08-17 11:40  Hey,Coder!  阅读(2)  评论(0)    收藏  举报