有这样的一个需求,我们要拦截某些特定的请求,并将它们重新定向到另一台服务器中,然而客户端并不知情。

在NetCore中我们可以用中间件来实现,

为什么要使用反向代理

  反向代理一般在下面的场景中进行使用:

  • 负载均衡:

    反向代理。它可以根据一些特定算法在一组相同的服务器之间分配请求负载,从而为系统的可伸缩性和可用性提供支持。

  • 网址重写:

    可以将无法更改的网络路径隐藏在反向代理后面。

  • 静态内容投放:

    反向代理服务器可以充当Web服务器。这使您可以将它们用于提供静态内容,例如HTML页面,JavaScript脚本,图像和其他文件,同时将对动态内容的请求转发到专用服务器。这是一种基于内容类型的负载平衡。

  • API网关:

    在具有微服务架构的系统中,您有多个服务器通过其API提供不同的服务。您可以使用反向代理来公开服务器API组合的单个入口点。

  • 多个网站合并:

    使多个网站使用共同的一个入口(网站),和微服务中的网关作用差不多。

首先创建项目:

  我这里只有2.1 Version 的

  

添加ProxyMiddleware

  

ProxyMiddleware内容如下:

  代码不多有兴趣的朋友可以调试一下。这里还可以有很多的方向扩展。

 public class ProxyMiddleware
{
private static readonly HttpClient _httpClient = new HttpClient();
private readonly RequestDelegate _nextRequestDelegate;
private static readonly Uri _targetUri = new Uri("https://www.cnblogs.com/");
public ProxyMiddleware(RequestDelegate nextMiddleware)
{
_nextRequestDelegate = nextMiddleware;
}
public async Task Invoke(HttpContext context)
{
bool validateUri = false;
if (context.Request.Path.StartsWithSegments("/api/values", out var Path))
{
validateUri = true;
}
if (validateUri == true)
{
var targetRequestMessage = CreateTargetMessage(context);
using (var responseMessage = await _httpClient.SendAsync(targetRequestMessage))
{
context.Response.StatusCode = (int)responseMessage.StatusCode;
CloneResponseHeadersIntoContext(context, responseMessage);
await responseMessage.Content.CopyToAsync(context.Response.Body);
}
return;
}
await _nextRequestDelegate(context);
}
private void CloneRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage)
{
foreach (var header in context.Request.Headers)
{
requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
}
}
private HttpRequestMessage CreateTargetMessage(HttpContext context)
{
var requestMessage = new HttpRequestMessage();
CloneRequestContentAndHeaders(context, requestMessage);
requestMessage.RequestUri = _targetUri;
requestMessage.Headers.Host = _targetUri.Host;
requestMessage.Method = new HttpMethod(context.Request.Method);
return requestMessage;
}
private void CloneResponseHeadersIntoContext(HttpContext context, HttpResponseMessage responseMessage)
{
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");
}
}

添加管道

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMiddleware<ProxyMiddleware>();
app.UseMvc();
}

运行结果:

  大家可以注意浏览器网址,以及显示的内容就可以了,(样式没了)

  

代码解释:

  所有的描述在代码中,这里我只是标出这点代码的重点

        创建静态HttpClient连接,减少连接池数量
     private static readonly HttpClient _httpClient = new HttpClient();
      
private readonly RequestDelegate _nextRequestDelegate;
     新的目标服务器
private static readonly Uri _targetUri = new Uri("https://www.cnblogs.com/");
public ProxyMiddleware(RequestDelegate nextMiddleware)
{
_nextRequestDelegate = nextMiddleware;
}
     所有的工作将由 Invoke执行 
     public async Task Invoke(HttpContext context)
{
bool validateUri = false;
if (context.Request.Path.StartsWithSegments("/api/values", out var Path))
{
validateUri = true;
}
if (validateUri == true)
{
var targetRequestMessage = CreateTargetMessage(context);
using (var responseMessage = await _httpClient.SendAsync(targetRequestMessage))
{
context.Response.StatusCode = (int)responseMessage.StatusCode;
CloneResponseHeadersIntoContext(context, responseMessage);
await responseMessage.Content.CopyToAsync(context.Response.Body);
}
return;
}
await _nextRequestDelegate(context);
}
        private void CloneResponseHeadersIntoContext(HttpContext context, HttpResponseMessage responseMessage)
{
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");
}

有不足之处 希望大家指出相互学习。

        

Net Core中 使用Middleware 实现反向代理的更多相关文章

  1. [C#]使用 C# 代码实现拓扑排序 dotNet Core WEB程序使用 Nginx反向代理 C#里面获得应用程序的当前路径 关于Nginx设置端口号,在Asp.net 获取不到的,解决办法 .Net程序员 初学Ubuntu ,配置Nignix 夜深了,写了个JQuery的省市区三级级联效果

    [C#]使用 C# 代码实现拓扑排序   目录 0.参考资料 1.介绍 2.原理 3.实现 4.深度优先搜索实现 回到顶部 0.参考资料 尊重他人的劳动成果,贴上参考的资料地址,本文仅作学习记录之用. ...

  2. dotNet Core WEB程序使用 Nginx反向代理

    之前记录过一篇 使用 jexus 作为dotNetCore的反向代理,发现jexus的内存占用较大,最终选择使用Nginx的原因就是占用内存较小,以及性能较优(https://www.cnblogs. ...

  3. IIS中利用ARR实现反向代理

    反向代理是什么,不了解的,请自行百度.本人也是最近才研究这个主题,简单的来说,利用这项技术可以实现负载均衡,安全控制等web应用中重要的功能,对于web应用来说这是个很基础,也很重要的技术,值得开发者 ...

  4. Linux系统中使用Nignx配置反向代理负载均衡

    目录 使用nginx实现动静分离的负载均衡集群 使用nginx实现负载均衡和动静分离 使用nginx实现动静分离的负载均衡集群 Nginx官网源码包下载链接:http://nginx.org/en/d ...

  5. Linux中配置端口转发(反向代理)

    在conf.d目录下建一个文件, 以conf为结尾(如果没有conf.d目录,就自己新建一个) server { listen 80; server_name 127.0.0.1; #这个IP是你服务 ...

  6. react项目中怎么使用http-proxy-middleware反向代理跨域

    第一步 安装 http-proxy-middleware npm install http-proxy-middleware 我们这里面请求用的axios,在将axios安装一下 npm instal ...

  7. .Net Core实践4 web 反向代理

    目标 将控制台程序改成web程序,通过IIS反向代理,处理请求 环境 win10 / .net core 2.1 / centos7 变成web程序 1.在新建的asp.net core控制台程序中添 ...

  8. Centos8 Docker+Nginx部署Asp.Net Core Nginx正向代理与反向代理 负载均衡实现无状态更新

    首先了解Nginx 相关介绍(正向代理和反向代理区别) 所谓代理就是一个代表.一个渠道: 此时就涉及到两个角色,一个是被代理角色,一个是目标角色,被代理角色通过这个代理访问目标角色完成一些任务的过程称 ...

  9. 如何设计出和 ASP.NET Core 中 Middleware 一样的 API 方法?

    由于笔者时间有限,无法写更多的说明文本,且主要是自己用来记录学习点滴,请谅解,下面直接贴代码了(代码中有一些说明): 01-不好的设计 代码: using System; namespace Desi ...

随机推荐

  1. laravel基础操作手册

    laravel基础操作手册 1.路由配置 测试配置路由: Route::get('/test', 'TestController@index'); 2.控制器书写 3.模型文件 4.增加扩展类文件 L ...

  2. VS Code配置Go语言开发环境(建议使用goland)

    VS Code是微软开源的一款编辑器,插件系统十分的丰富.本文就介绍了如何使用VS Code搭建Go语言开发环境. VS Code配置Go语言开发环境 说在前面的话,Go语言是采用UTF8编码的,理论 ...

  3. SDI接口基于FPGA GTP实现

    SDI采集和显示,基于xilinx 7系列器件进行实现,注意事项有如下几点: 1,如果多路SDI共用一个GTP Quad,或是SDI和PCIE在一个GTP Quad,时钟资源应该进行共享,既GTP c ...

  4. 【DP合集】背包 bound

    N 种物品,第 i 种物品有 s i 个,单个重量为 w i ,单个价值为 v i .现有一个限重为 W 的背包,求能容 纳的物品的最大总价值. Input 输入第一行二个整数 N , W ( N ≤ ...

  5. eventfd(2) 结合 select(2) 源码分析

    eventfd(2) 结合 select(2) 源码分析 本文代码选自内核 4.17 eventfd(2) - 创建一个文件描述符用于事件通知. 使用 源码分析 参考 #include <sys ...

  6. 项目开发---使用node.js中sass语法

    前言:本文中所有sass文件都指后缀名为scss的文件.在此也建议使用后缀名为scss的文件,以避免sass后缀名的严格格式要求报错. 一.sass插件的安装: gulp-sass-china //  ...

  7. lua行为树设计与实现

    项目需要,之前行为树用的是behaviorDesigner,要改成纯lua的 我先做了一版用递归实现,代码可读性高但是中断机制实现起来比较复杂,而且创建自定义action重写方法时需要调用父类的方法, ...

  8. PHP get_parent_class

    <?php class D { } class A extends D { } class B extends A { } function getAncestor($class){ $pare ...

  9. ‎Cocos2d-x 学习笔记(15.1) EventDispatcher

    EventDispatcher对监听器进行管理,围绕着监听器工作.可以添加.删除.暂停/恢复监听器.分发事件到监听器. 1. 一些成员 /** 把ListenerID和同ID监听器的容器对应 */ s ...

  10. Dubbo+Zookeeper(一)Zookeeper初识

    前面花了一段时间去学习SpringCloud的相关知识,主要是理解微服务的概念并使用SpringCloud的一系列组件实现微服务落地.学习这些组件本身是简单的,跟着操作一遍基本就会了,这也得益于Spr ...