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

在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. 博客的第一天:回顾半年前的基础:SQL--基础查询+年月日格式+拼接

    ----------------------2019/6月份 <<必知必会>>书本练习-实践练习--------------------------- ---order by没 ...

  2. ThinkPHP框架快速开发网站

    使用ThinkPHP框架快速搭建网站 这一周一直忙于做实验室的网站,基本功能算是完成了.比较有收获的是大概了解了ThinkPHP框架.写一些东西留作纪念吧.如果对于同样是Web方面新手的你有一丝丝帮助 ...

  3. 前端get和post那些事

    首先,简单介绍下,get和post请求方法,综合以往笔记,现整理如下: 一.HTTP请求比较: 两种在客户端和服务器端进行请求-响应的方法是:GET和POST. GET - 从指定的资源请求数据 PO ...

  4. 利用 SASS 简化 `nth-child` 样式的生成

    考察如下的 HTML 片段,通过 CSS 的 nth-child() 伪选择器实现列表的颜色循环,比如每三个一次循环. <ul> <li>1</li> <li ...

  5. Python开发专属壁纸下载与轮换程序

    本人对于壁纸一直偏佛系,不爱特意去找一堆壁纸.因此用Python简单地搞了一个自动下载壁纸,定时随机轮换的功能来自娱自乐,顺便分享给大家. 原文链接:https://www.codernice.top ...

  6. 二次函数,为什么a>0就可以知道开口向上.

    最近自考. 学习高等数学. 学习高等数学过程中发现高中数学不会,,于是乎开始补高中数学. 学习高中数学过程中又发现初中数学有的不会,,于是乎开始补初中数学.. 可怕(→_→). 今天遇到一个二次函数, ...

  7. IMongoQuery的使用-C#

    一.Mongodb的IMongoQuery的使用 引用命名空间:MongoDB.Driver;MongoDB.Driver.Builders; Query.All("name",  ...

  8. Python从入门到精通视频(全60集) ☝☝☝

    Python从入门到精通视频(全60集) Python入门到精通 学习 教程 首先,课程的顺序需要调整:一和三主要是介绍学习和布置开发环境的,一介绍的是非VS开发,三介绍的是VS开发.VS2017现在 ...

  9. 学以致用,通过字节码理解:Java的内部类与外部类之私有域访问

    目录: 内部类的定义及用处 打开字节码理解内部类 一.内部类的定义及用处 内部类(inner class)是定义在另一个类中的类.使用内部类,我们可以: 访问该类定义所在的作用域中的数据,包括私有的数 ...

  10. Vue中的循环以及修改差值表达式

    0828自我总结 一.Vue中的循环 v-for 常见的4总情况 #第一种 <div v-for="item in items"></div> #第二种 & ...