You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用ASP.NET Core Minimal API实现简易请求代理

Blazor WASM开发环境CORS代理最简实现方案

你不需要手写复杂的流读写、头处理逻辑,ASP.NET Core原生能力就能实现零额外依赖、极少代码的开发测试用代理,完全满足需求。


现有代码的问题根源

  • 每次请求新建HttpClient会导致套接字耗尽,长期运行会出现端口占用问题
  • 写死只支持GET请求,无法适配POST/PUT/DELETE等其他接口方法
  • 调用res.EnsureSuccessStatusCode()会在下游返回4xx/5xx状态码时直接抛出异常,框架捕获后统一返回500,丢失原始状态码
  • 手动读取响应为字符串再返回,会丢失所有响应头,同时大响应会占用额外内存
  • 手动处理Authorization头容易因为格式问题报错,也无法透传其他业务需要的请求头
  • 直接返回HttpResponseMessage时,Minimal API默认不会透传所有自定义响应头,也不会保留原始错误状态码,才会出现内容传递异常的问题

最少代码实现(无第三方依赖)

整个代理逻辑只需要20行左右代码,解决所有提到的缺陷:

  1. 注册复用的HttpClient实例,替换每次new的写法
  2. 匹配所有HTTP方法的代理路由,不要只映射GET
  3. 全量透传请求头、请求体、下游状态码、下游响应头
  4. 直接用流复制传递响应内容,不做内存缓冲

完整代码如下:

var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("appsettings.json").AddEnvironmentVariables();
// 原有CORS配置保持不变
builder.Services.AddCors(options =>
{
    options.AddPolicy("cors", policy =>
    {
        policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin();
    });
});
// 注册复用的代理HttpClient
builder.Services.AddHttpClient("DiscosProxy", client =>
{
    client.BaseAddress = new Uri(builder.Configuration["DiscosOptions:DiscosApiUrl"]!);
});

var app = builder.Build();
app.UseCors("cors");

// 匹配所有HTTP方法的代理路由
app.Map("/discos-proxy/{**discosRoute}", async (
    string discosRoute,
    HttpContext context,
    IHttpClientFactory httpClientFactory) =>
{
    var proxyClient = httpClientFactory.CreateClient("DiscosProxy");
    // 构造透传请求
    var requestMsg = new HttpRequestMessage
    {
        Method = new HttpMethod(context.Request.Method),
        RequestUri = new Uri(discosRoute + context.Request.QueryString, UriKind.Relative),
        Content = new StreamContent(context.Request.Body)
    };
    // 透传所有非宿主请求头
    foreach (var header in context.Request.Headers)
    {
        if (!header.Key.StartsWith(":") && header.Key != "Host")
        {
            requestMsg.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
        }
    }
    // 发送请求,仅等待响应头返回就开始处理,不缓冲全量响应
    var downstreamResp = await proxyClient.SendAsync(requestMsg, 
        HttpCompletionOption.ResponseHeadersRead, 
        context.RequestAborted);
    // 透传原始状态码
    context.Response.StatusCode = (int)downstreamResp.StatusCode;
    // 透传所有响应头(包括速率限制头、Content-Type等)
    foreach (var header in downstreamResp.Headers.Concat(downstreamResp.Content.Headers))
    {
        context.Response.Headers[header.Key] = header.Value.ToArray();
    }
    // 直接复制响应流,不需要手动读成字符串
    await downstreamResp.Content.CopyToAsync(context.Response.Body, context.RequestAborted);
});

app.Run();

该实现覆盖的能力

  • 支持所有HTTP方法,自动透传请求体,适配RESTful全类型接口
  • 下游返回的任意状态码(包括4xx、5xx错误码)都会原样返回,不会被转成500
  • 所有响应头(包括速率限制相关头、鉴权头、缓存头、Content-Type)全量透传
  • 流转发不缓冲全量响应,大文件、大列表接口也不会额外占用内存
  • 自动透传所有请求头,不需要单独处理Authorization头,不会出现token格式解析错误
  • 复用HttpClient实例,不会出现端口耗尽问题

注:该实现仅适用于开发测试环境,生产环境使用需要补充头过滤、异常处理、限流、鉴权等逻辑,不满足生产级安全要求。


内容的提问来源于stack exchange,提问作者ScottishTapWater

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 22:30:55