首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

ASP.NET Core 跨域請求中間件實現:反向代理轉發與 Session 共享

     編輯:PHP 相關知識

本文展示一個 ASP.NET Core (C#) 實現的 IHttpModule / 中間件,攔截特定路徑 (/Server/...) 請求,轉發至內部服務 (https://localhost:89),實現跨域/微服務網關功能,並透傳表單數據、Cookie、Header。

核心中間件代碼

using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

namespace Gateway {
    public class ReverseProxyMiddleware {
        private readonly RequestDelegate _next;
        private const string TargetBase = "https://localhost:89";
        private const string Prefix = "/Server";

        public ReverseProxyMiddleware(RequestDelegate next) {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context) {
            var path = context.Request.Path.Value;
            if (!path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase)) {
                await _next(context);
                return;
            }

            // 構建目標 URL
            var targetPath = path.Substring(Prefix.Length);
            var targetUrl = TargetBase + targetPath + context.Request.QueryString;

            // 建立上游請求
            var request = WebRequest.CreateHttp(targetUrl);
            request.Method = context.Request.Method;
            request.ContentType = context.Request.ContentType ?? "application/x-www-form-urlencoded";
            request.Timeout = 60000;

            // 複製 Header(排除 Host、Connection 等)
            foreach (var header in context.Request.Headers) {
                if (!WebHeaderCollection.IsRestricted(header.Key)) {
                    request.Headers[header.Key] = header.Value.ToString();
                }
            }

            // 轉發 Body (POST/PUT)
            if (context.Request.Method != "GET" && context.Request.Method != "HEAD") {
                using var reqStream = request.GetRequestStream();
                await context.Request.Body.CopyToAsync(reqStream);
            }

            try {
                using var response = (HttpWebResponse)await request.GetResponseAsync();
                // 複製響應
                context.Response.StatusCode = (int)response.StatusCode;
                foreach (string key in response.Headers) {
                    if (!WebHeaderCollection.IsRestricted(key)) {
                        context.Response.Headers[key] = response.Headers[key];
                    }
                }
                using var respStream = response.GetResponseStream();
                await respStream.CopyToAsync(context.Response.Body);
            } catch (WebException ex) {
                context.Response.StatusCode = 502;
                await context.Response.WriteAsync("Bad Gateway: " + ex.Message);
            }
        }
    }
}

// Startup.cs 註冊
app.UseMiddleware();

關鍵設計點

  1. 路徑攔截:/Server/ 前綴路由至內部微服務,其餘走正常管道。
  2. Header 透傳:過濾受限 Header (Host, Connection, Content-Length) 避免衝突。
  3. Body 流式轉發:CopyToAsync 避免大請求佔用內存。
  4. 錯誤處理:捕獲 WebException 返回 502,記錄日誌便於排查。
  5. Session/認證傳遞:若內部服務需用戶身份,可在中間件解析 JWT/Cookie,轉為內部 Header (X-User-Id) 傳遞。

現代替代:YARP (Yet Another Reverse Proxy)

微軟官方推出 YARP,提供聲明式配置、負載均衡、健康檢查、WebSocket 支援、速率限制等企業級功能,強烈建議新專案直接使用:

// appsettings.json
{
  "ReverseProxy": {
    "Routes": {
      "server-route": {
        "ClusterId": "internal",
        "Match": { "Path": "/Server/{**catch-all}" },
        "Transforms": [{ "PathPattern": "{**catch-all}" }]
      }
    },
    "Clusters": {
      "internal": {
        "Destinations": {
          "dest1": { "Address": "https://localhost:89/" }
        }
      }
    }
  }
}

// Program.cs
builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
app.MapReverseProxy();

手寫中間件適合學習原理、極簡場景;生產網關請用 YARP、Ocelot、Kong、APISIX 等成熟方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved