go 进阶 请求代理相关: 一. 基于原生HTTP实现请求代理

2023-11-09

一. 代理基础概念了解

什么是正向代理

  1. 是一种客户端的代理技术缩写为"forward_proxy",帮助客户端访问无法访问的服务资源,可以隐藏用户的真实ip,如浏览器web代理、vpn等
  2. 大概步骤:
  1. 监听中的代理服务器在接收到客户端的请求后,会创建一个上游的tcp连接,通过回调方法,复制原请求对象,并根据其中的数据配置新的请求中的各种参数
  2. 把新请求发送到真实的服务器,并接收到服务器端的返回
  3. 代理服务器对响应做一些处理后,返回给客户端

什么是反向代理

  1. 是一种服务端的代理技术,帮助服务器做负载均衡、缓存、提供安全校验等,可以隐藏服务器的真实ip。如LVS技术、Nginx Proxy_pass等
  2. 大概步骤:
  1. 代理接收客户端请求,更改请求结构体信息
  2. 通过一定的负载均衡算法获取下游服务器地址
  3. 把请求发送到下游服务器,并获取返回内容
  4. 对返回内容做一些处理,返回给客户端

二. 基于原生HTTP实现代理

简单正向代理示例

  1. 实现步骤
  1. 自定义结构体,实现ServeHTTP(),编写处理器
  2. ServeHTTP()中编写正向代理需要处理的业务逻辑
  3. 将自定义的处理器与对应的接口绑定,注册路由(此处示例中绑定的接口为"/")
  4. 编写main方法监听服务端口,启动服务
  1. 由于自定义处理器路由绑定的接口为"/",所以访问当前服务的所有接口都会被代理到
import (
	"fmt"
	"io"
	"net"
	"net/http"
	"strings"
)

//1.创建结构体
type Proxy struct{}

//2.结构体实现ServerHTTP()函数,将结构体变为Header
func (p *Proxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	fmt.Printf("接收请求 method: %s, host: %s, remoteAddr: %s", req.Method, req.Host, req.RemoteAddr)
	//1.获取一个默认的连接池
	transport := http.DefaultTransport
	//2.浅拷贝获取到请求数据
	outReq := new(http.Request)
	*outReq = *req

	//3.获取发送请求的ip地址,放到"X-Forwarded-For"请求头中
	if clientIp, _, err := net.SplitHostPort(req.RemoteAddr); nil == err {
		if prior, ok := outReq.Header["X-Forwarded-For"]; ok {
			//X-Forwarded-For多个时采用","拼接
			clientIp = strings.Join(prior, ",") + "," + clientIp
		}
		outReq.Header.Set("X-Forwarded-For", clientIp)
	}

	//4.请求下游服务,获取到下游服务响应
	resp, err := transport.RoundTrip(outReq)
	if nil != err {
		//如果异常响应异常
		rw.WriteHeader(http.StatusBadGateway)
		return
	}

	//5.封装响应头
	for key, val := range resp.Header {
		for _, v := range val {
			rw.Header().Add(key, v)

		}
	}

	//6.封装正常响应
	rw.WriteHeader(resp.StatusCode)
	//将resp中拿到的响应数据复制到rw中
	io.Copy(rw, resp.Body)

	//关闭响应资源
	resp.Body.Close()
}

func main() {
	//注册上面自定义的Proxy{}处理器,绑定"/"所有接口路径
	//意思是只要请求当前服务"http:127.0.0.1:8080/*"下的所有接口都会被
	//Proxy下实现的ServeHTTP()执行代理
	http.Handle("/", &Proxy{})
	http.ListenAndServe("0.0.0.0:8080", nil)
}

简单反向代理示例

  1. 实现步骤
  1. 明确需要调用的真实服务地址
  2. 实现ServeHTTP(),编写处理器,处理器中拿到真实服务地址,改写请求协议,主机地址等
  3. 监听指定端口,启动当前服务
import (
	"bufio"
	"log"
	"net/http"
	"net/url"
)

//1.代理后真实访问的服务地址
var (
	proxy_addr = "http://127.0.0.1:2003"
)

//2.实现ServeHTTP,编写处理器
func handler(w http.ResponseWriter, r *http.Request) {
	//1.通过url.Parse()解析代理地址,拿到真实服务地址
	proxy, err := url.Parse(proxy_addr)
	//2.更改请求体的协议和主机
	r.URL.Scheme = proxy.Scheme
	r.URL.Host = proxy.Host

	//3.获取一个默认的连接池
	transport := http.DefaultTransport
	//4.通过连接池的RoundTrip()请求下游服务,并拿到响应结果
	resp, err := transport.RoundTrip(r)
	//关闭资源
	defer resp.Body.Close()
	if err != nil {
		log.Print(err)
		return
	}

	//5.封装下游服务的响应头
	for k, vv := range resp.Header {
		for _, v := range vv {
			w.Header().Add(k, v)
		}
	}

	//6.下游服务的响应输出给当前服务的调用方
	bufio.NewReader(resp.Body).WriteTo(w)
}

func main() {
	//注册路由,处理器为上方自定义处理器
	http.HandleFunc("/", handler)
	//监听端口启动服务
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		log.Fatal(err)
	}
}

上方代理中可能存在的问题

  1. 上方才有原生HTTP实现正反向代理,可能存在一下问题
  1. 没有错误回调及错误日志等处理
  2. 无法更改代理后返回的内容
  3. 没有负载均衡
  4. 没有url重写
  5. 没有熔断限流,降级,数据统计等功能
  1. 解决以上问题,golang提供了ReverseProxy实现http代理
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

go 进阶 请求代理相关: 一. 基于原生HTTP实现请求代理 的相关文章

  • HTTP 查询字符串和 []

    PHP 使用 在查询参数名称中 以确保多次出现的参数都出现在 GET超全局变量 否则只出现最后一次出现的情况 还有其他软件可以做到这一点吗 但从RFC 3986 https www rfc editor org rfc rfc3986 以及
  • 如何让 NSURLRequest 获取 Twitter 请求令牌?

    我正在尝试使用以下代码从 Twitter 获取请求令牌 NSMutableURLRequest mURLRequest NSMutableURLRequest alloc initWithURL NSURL URLWithString ht
  • gRPC(HTTP/2) 比使用 HTTP/2 的 REST 更快吗?

    目标是引入一种性能更好的传输和应用层协议latency and 网络吞吐量 目前 该应用程序使用REST with HTTP 1 1并且我们遇到了很高的延迟 我需要解决这个延迟问题并且我愿意使用gRPC HTTP 2 or 休息 HTTP2
  • 反向代理受 NTLM 保护的网站

    如何将请求代理到受 NTLM 保护的网站 例如团队基金会 and 共享点 我不断得到401 身份验证错误 根据这篇 Microsoft TechNet 文章 https www microsoft com technet prodtechn
  • AWS ALB 截断 HTTP 响应

    我有一个带有目标组的 ALB 和运行 PHP API 的 ECS 集群 我正在尝试查询 API 以获得 CSV 响应 但如果请求通过 ALB 我会得到被截断的结果 当我通过 SSH 连接到运行集群的 EC2 实例并尝试手动运行curl 通过
  • 为什么使用 HTTP 动词?

    因为动词的目标是像 server domain getallrecords 或 server domain delete1record 或类似的 URL 而getallrecords delete1record都是专门为特定目的而设计的 为
  • 如何确定服务器是否支持 Range 标头?

    我一直在尝试使用 Range 标头值从特定点流式传输音频 但我总是从一开始就得到歌曲 我正在通过程序执行此操作 因此不确定问题是否出在我的代码中或服务器上 如何确定服务器是否支持 Range 标头参数 Thanks 方式HTTP规范 htt
  • 如何增加asp classic的请求接受限制

    我从java小程序向asp classic发送post请求 我在此请求中发送非常大的数据 即 csv 数据 当此请求中的字符数增加并超过 138000 时 asp 不接受该请求 java 小程序给出 500 错误 所以有人可以告诉我如何才能
  • ASP.NET 中 HTTP 缓存相关标头的有效含义

    我正在 ASP NET 2 0 中开发一个 Web 应用程序 其中涉及通过资源处理程序 ashx 提供图像 我刚刚实现了处理缓存标头和条件 GET 请求 这样我就不必为每个请求提供所有图像 但我不确定我是否完全理解浏览器缓存发生了什么 图像
  • AJAX 发送数据到 Node.js 服务器

    我尝试使用 AJAX 将数据发送到 Node js 服务器 但不断遇到同样的问题 即接收问题 这是客户端 JavaScript AJAX 代码 var objects function return new XMLHttpRequest f
  • 诸如用于测试 HTTP 请求的虚拟 REST 服务器之类的东西? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我一直在四处寻找 但找不到任何这样的网站 我想知道是否有一些虚拟服务器可以响应测试 GET 请求并返回
  • $http.get() 与 JSON 数据

    我正在编写一个服务器应用程序 并希望客户端使用正文中的数据来参数化我的 GET 方法 如下所示 http v GET http localhost 3000 url text 123 foo bar GET url HTTP 1 1 Acc
  • Node.js:server.setTimeout、server.timeout 和 server.keepAliveTimeout 之间有什么区别

    官方文档是here https nodejs org api http html http server settimeout msecs callback server setTimeout 中没有提及有关服务下一个请求的信息 所以我认为
  • UNIX/MacOS 上静态文件的“临时 Web 服务器”?

    是否有一个像小型网络服务器这样的东西 我可以从命令行调用它 只从本地文件系统获取文件并通过特定端口上的 HTTP 为它们提供服务 我希望能够做这样的事情 cd Sites mysite serve 10 0 1 1 8080 这应该会启动一
  • HTTP Header Key 可以重复吗?

    在 JAVA HttpUrlConnection 中 请求 Header 设置的主要逻辑代码如下 public synchronized void set String k String v for int i nkeys i gt 0 i
  • WCF WebHttp 混合身份验证(基本和匿名)

    所有这些都与 WebHttp 绑定有关 托管在自定义服务主机中 IIS 目前不是一个选项 我已经实现了自定义 UserNamePasswordValidator 和自定义 IAuthorizationPolicy 当我将端点的绑定配置为使用
  • 用 C++ 解析 HTTP 标头

    我正在使用curl 与服务器通信 当我发出数据请求时 我收到 HTTP 标头 后跟由边界分隔的 jpeg 数据 如下所示 我需要解析出 边界字符串 内容长度 我已将传入数据复制到 char 数组 如下所示 static size t OnR
  • 使用 Unity 在 C# 中发送 http 请求

    如何使用 Unity 在 C 中发送 HTTP GET 和 POST 请求 我想要的是 在post请求中发送json数据 我使用Unity序列化器 所以不需要 新的 我只想在发布数据中传递一个字符串并且能够 将 ContentType 设置
  • Flutter http请求上传mp3文件

    我使用这个 api 上传 mp3 文件 使用这种方法 Future
  • 注册期间现有电子邮件的 422 或 409 状态代码

    我正在构建 RESTful API 遇到了一种情况 在用户注册期间 如果电子邮件已存在 则在422 and 409哪个http响应代码有意义 我浏览过类似的one https stackoverflow com questions 9269

随机推荐

  • 恭喜广工荣获2023CUBAL冠军

    恭喜广工 作者 良知犹存 转载授权以及围观 欢迎添加微信公众号 羽林君 1 竞技比赛就有这样的刺激 也许到最后一刻才能决出胜负 一个赛季努力在最后几秒进行抉择 让人热血沸腾 尤其是人们也喜欢弱者的逆袭 再一次面对清华 一支来自由全国顶级篮球
  • Vue 对象数组修改数组中的对象的某个元素,元素更新了视图不更新的问题解决

    问题描述 当我修改数组对象中的某个元素的时候 元素更新了 但是视图没有更新 例如下数组对象 attendanceTime workDays 周一 shiftId 1 shiftTime workDays 周二 shiftId 2 shift
  • 使用uni-app开发叮咚买菜的一些笔记

    本项目纯开源免费 商品信息均来自网络 如有侵权 请联系作者 我会及时删除 前一段 看到一个大佬写的叮咚买菜 挺好 于是乎自己在家也琢磨了一下 自己搞了一版本 记录一些uni app的开发事项 纯属个人总结 不对之处 还请指教 功能不是很全面
  • 硬件工程师-MOS管

    目录 DS等效电阻 Rdson MOS管 GS电容 MOS管的损耗 MOS管体二极管 讨论MOSFET的GS电容问题 MOSFET的GS电容对管子开通特性的影响 MOS管GS下拉电阻 MOS管的等效模型 MOSFET是如何进行导通的 Rds
  • OpenCV-Python 图像平滑处理1:卷积函数filter2D详解及用于均值滤波的案例

    一 图像平滑处理简介 图像平滑处理属于图像空间滤波的一种 用于模糊处理和降低噪声 模糊处理经常用于图像预处理任务中 例如在 大 目标提取之前去除图像中的一些琐碎细节 以及桥接直线或曲线的缝隙 模糊处理后的图像 可以通过阈值处理 形态处理等方
  • 线性稳压芯片LR78L05U参数

    属性 参数值 商品目录 线性稳压芯片 输出电流 100mA 稳压器数 1 输出类型 Fixed 压降 最大值 1 7V 40mA 工作温度 55 125 工作电源电流 最大值 6 1mA 输入电压 最大值 30V 输出配置 Positive
  • Unity 在编辑模式下退出游戏

    实现在编辑器环境下退出编辑器 在非编译器环境下退出游戏 我们需要判断当前是否在编辑器环境中 在unity中是使用预处理的方式判断当前的环境 常用的预处理标识符如下 标识符 解释 UNITY EDITOR 只在编辑器中编译 UNITY AND
  • el-popover 通过js手动控制弹出框显示、隐藏

    el popover 通过js手动控制弹出框显示 隐藏 说明 element ui 2 x中 el popover的显示隐藏有4种触发方式 click focus hover manual 分别是点击 聚焦 悬浮 手动 正常情况这几个触发方
  • 总结/笔记-逻辑函数封装

    逻辑函数拆分业务 将同一组件中独立的业务代码通过函数做封装处理 提高代码的可维护性 步骤 1 命名函数 use业务名 js 2 用函数封装业务逻辑 3 函数内 return 数据 方法 4 组件中 调用函数使用 封装业务逻辑函数 compo
  • java文件名命名的规则,Java文件名及其他命名规则

    http bbs csdn net topics 70157841 关于JAVA源文件命名的问题 Java文件命名 java程序是由类组成的 java应用程序必须有一个包含main方法的public类 main方法是程序的入口 java源文
  • UncaughtExceptionHandler加Process 让应用程序不异常崩溃退出

    我们在开发应用程序时难免会遇到出现没有被try catch抓住的RunTimeException信息 从而导致程序异常崩溃退出 大大的影响了用户体验 那么有没有什么方法能避免这一现象呢 网上一查资料 果然有 UncaughtExceptio
  • 延迟渲染到最终结果---大象无形(11.3.1)--2,PrePass预处理阶段--<2>大致工作流程

    正如上文所言 对静态物体和动态物体分别处理 一 静态物体 1 设置渲染状态 只计算像素深度 不计算颜色 具体内容是 关闭颜色写入 打开深度测试与深度写入 2 渲染三个绘制列表 1 只绘制深度的列表PositionOnlyDepthDrawL
  • java 内存同步_Java同步的内存影响

    小编典典 简而言之 就是 JSR 133的解释太过分了 这不是一个严重的问题 因为JSR 133是非规范性文档 不属于语言或JVM标准 而是 只有文档解释了一种可能的策略 该策略 足以 实现内存模型 但通常不是 必需的 最重要的是 有关 缓
  • java:变量(二)变量的基本类型

    二 整型与浮点型细节 1 组成 整型变量是由符号位和数位两部分组成 浮点变量是由符号位 指数尾 尾数位组成 整型和浮点型变量的首位都是符号位 用来表示数据的正负 2 整型浮点型变量的长度和取值范围是固定的 事实上同一语言的基本数据类型的长度
  • 云优化:您需要知道的一切

    在不考虑云优化的情况下将开发工作迁移到云端有点类似于吃 PB J 花生酱 果酱 三明治 只不过没有果酱 虽然花生酱已经够美味了 但您错过了把这一切结合在一起的要素 如果您想确保最大限度地利用您的云支出并消除任何可能拖慢速度的低效率事项 那么
  • 在idea中集成redis

    https www cnblogs com yiMro p 13529150 html SpringBoot Redis 基本配置及使用 Test public void TestRedis Jedis jedis new Jedis 19
  • [docker学习笔记] 11.docker网络模式及容器间网络通信

    docker的容器之间需要进行业务通信 11 1 默认网络 初始安装docker 之后 有三种网络 可以通过 docker network ls 查看 root localhost docker network ls NETWORK ID
  • 常用校验码(奇偶校验码、海明校验码、CRC校验码)

    常用校验码 奇偶校验码 海明校验码 CRC校验码 一 奇偶校验码二 海明校验码三 CRC校验码 计算机系统运行时 各个部之间要进行数据交换 交换的过程中 会有发生误码的可能 即0变成1或1变成0 由于计算机的储存是通过二进制代码来实现的的
  • C#连接云服务器MySql数据库

    环境 vs2017 第一步 在主窗口代码区新建一个类 用于连接数据库 在开发过程中其他窗口 常常也需要 对数据库进行操作 如果在每一个窗口的代码区域都连接一次数据库的话 就会很麻烦 所以在主窗口先用一个公共类连接了数据库 其他窗口就可以直接
  • go 进阶 请求代理相关: 一. 基于原生HTTP实现请求代理

    目录 一 代理基础概念了解 什么是正向代理 什么是反向代理 二 基于原生HTTP实现代理 简单正向代理示例 简单反向代理示例 上方代理中可能存在的问题 一 代理基础概念了解 什么是正向代理 是一种客户端的代理技术缩写为 forward pr