62,263
社区成员
发帖
与我相关
我的任务
分享public class ProxyMiddleware
{
// private ProxyHttpClient _proxyHttpClient;
private const string CDN_HEADER_NAME = "Cache-Control";
private static readonly string[] NotForwardedHttpHeaders = new[] { "Connection", "Host" };////Http头文件的这两个属性在下面代码中用到,这两个状态属性是什么意思,如果头文件中没有这两个属性,代表什么意思呢?
private readonly RequestDelegate _next;
private readonly ILogger<ProxyMiddleware> _logger;
public ProxyMiddleware(
RequestDelegate next,
ILogger<ProxyMiddleware> logger
)
{
_next = next;
_logger = logger;
//_proxyHttpClient = proxyHttpClient;
}
/// <summary>
/// 通过中间件,拦截访问,检测前缀,并转发
/// </summary>
/// <param name="context"></param>
/// <param name="urlRewriter"></param>
/// <returns></returns>
public async Task Invoke(HttpContext context, IUrlRewriter urlRewriter, ProxyHttpClient proxyHttpClient)
{
var targetUri = await urlRewriter.RewriteUri(context);
if (targetUri != null)
{
var requestMessage = GenerateProxifiedRequest(context, targetUri);
await SendAsync(context, requestMessage, proxyHttpClient);
return;
}
await _next(context);
}
private async Task SendAsync(HttpContext context, HttpRequestMessage requestMessage, ProxyHttpClient proxyHttpClient)
{
using (var responseMessage = await proxyHttpClient.Client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted))
{
context.Response.StatusCode = (int)responseMessage.StatusCode;
foreach (var header in responseMessage.Headers)
{
context.Response.Headers[header.Key] = header.Value.ToArray();
}
foreach (var header in responseMessage.Content.Headers)
{
context.Response.Headers[header.Key] = header.Value.ToArray();
}
context.Response.Headers.Remove("transfer-encoding");
if (!context.Response.Headers.ContainsKey(CDN_HEADER_NAME))
{
context.Response.Headers.Add(CDN_HEADER_NAME, "no-cache, no-store");
}
await responseMessage.Content.CopyToAsync(context.Response.Body);
}
}
private static HttpRequestMessage GenerateProxifiedRequest(HttpContext context, Uri targetUri)
{
var requestMessage = new HttpRequestMessage();
CopyRequestContentAndHeaders(context, requestMessage);
requestMessage.RequestUri = targetUri;
requestMessage.Headers.Host = targetUri.Host;
requestMessage.Method = GetMethod(context.Request.Method);
return requestMessage;
}
private static void CopyRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage)
{
var requestMethod = context.Request.Method;
if (!HttpMethods.IsGet(requestMethod) &&
!HttpMethods.IsHead(requestMethod) &&
!HttpMethods.IsDelete(requestMethod) &&
!HttpMethods.IsTrace(requestMethod))
{
var streamContent = new StreamContent(context.Request.Body);
requestMessage.Content = streamContent;
}
foreach (var header in context.Request.Headers)
{
if (!NotForwardedHttpHeaders.Contains(header.Key))////Http头文件的这两个属性(connection,Host)这两个状态属性是什么意思,如果头文件中没有这两个属性,代表什么意思呢?
{
if (header.Key != "User-Agent")//////这句判断又什么意思呢?
{
if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null)
{
requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
}
}
else
{
string userAgent = header.Value.Count > 0 ? (header.Value[0] + " " + context.TraceIdentifier) : string.Empty;
if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, userAgent) && requestMessage.Content != null)
{
requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, userAgent);////主体文件属性里又都多了个头属性,这个头属性又啥意思,请结合代码帮解释下。
}
}
}
}
}
private static HttpMethod GetMethod(string method)
{
if (HttpMethods.IsDelete(method)) return HttpMethod.Delete;
if (HttpMethods.IsGet(method)) return HttpMethod.Get;
if (HttpMethods.IsHead(method)) return HttpMethod.Head;
if (HttpMethods.IsOptions(method)) return HttpMethod.Options;
if (HttpMethods.IsPost(method)) return HttpMethod.Post;
if (HttpMethods.IsPut(method)) return HttpMethod.Put;
if (HttpMethods.IsTrace(method)) return HttpMethod.Trace;
return new HttpMethod(method);
}
HttpHeaders抽象类恰恰没有定义属性。下面的派生类分别根据其职责定义其对应的属性。
HttpRequestHeaders类的属性,表示客户端请求的HEADER;
HttpResponseHeaders类的属性,表示服务器发送过来的HEADER;
HttpContentHeaders类的属性,表示作用于CONTENT的HEADER;
这里,到了HttpContentHeaders,就实现了内容类型,内容长度等字段,对应你了解的HTTP HEADER,就是Content-Length、Content-Length等HEADER
面向对象的设计中最重要的思想之一就是语义。

发现了,后者继承前者的。是在HttpRequestMessage.Content这个返回的是HttpContent,它有个Headers属性,返回HttpContentHeaders 类,这个类继承System.Net.Http.Headers.HttpHeaders。微软这样设计的目的是什么,这不是多此一举吗?前者没法添加,在后者里添加。
我们通用的Header头不都是直接获取HttpHeaders吗?什么时候要用到后者呢?