当前位置: 首页 > news >正文

跨域案例go gf ,请求代理,前端请求后端A转发给多个后端B

跨域案例go gf ,请求代理,前端请求后端A转后端B

案例:从前端请求后端A(路径携带argusx),后端A转发请求到多个不同地区(可一个)后端B(切掉argusx,其他不变进行请求),由请求头x-proxy指定请求哪个服务端

方案一:handler形式处理:

func InitRouter() {s := g.Server()// 分组路由注册方式app.Api = s.Group("/argusx", func(group *ghttp.RouterGroup) {// 跨域中间件service.Middleware.InitGroup(group)ReverseProxy(group, "/xxx/")})
}// InitGroup 注册中间件
func (s *middlewareService) InitGroup(group *ghttp.RouterGroup) {group.Middleware(// 跨域处理s.CORS,//s.Auth,)
}
// 使用默认跨域处理
func (s *middlewareService) CORS(r *ghttp.Request) {//r.Response.CORSDefault() //若是请求头没有新的,则直接用default,否则用下面三行代码options := r.Response.DefaultCORSOptions()options.AllowHeaders = options.AllowHeaders + ",X-Proxy"r.Response.CORS(options)r.Middleware.Next()
}
func ReverseProxy(pg *ghttp.RouterGroup, path string) {op := func(r *ghttp.Request) {// 根据code拿到地址,可用自己的方式获取参数argusvoiceCode := r.GetHeader("x-proxy")g.Log().Infof("[argusvoice] argusvoiceCode=%s", argusvoiceCode)if argusvoiceCode != "" {argusvoiceApi := service.GetArgusVoiceUrlByCode(argusvoiceCode)g.Log().Infof("[argusvoice] argusvoiceApi=%s", argusvoiceApi)remote, err := url.Parse(argusvoiceApi)if err != nil {fmt.Println(err.Error())g.Log().Errorf("[argusvoice] url parse error, argusvoiceApi=%s, error=%v", argusvoiceApi, err)}reverseProxy := proxy.GoReverseProxy(&proxy.RProxy{Remote: remote,})if err != nil {fmt.Println(err.Error())r.ExitAll()return}reverseProxy.ServeHTTP(r.Response.Writer, r.Request)r.ExitAll()} else {r.Middleware.Next()}}pg.Bind([]ghttp.GroupItem{{"ALL", path + "*", op}})
}

方案二:中间件的形式代理:
对所有请求都拦截,包括options,这样需要自己处理options请求,options请求是为了协商请求头,所以需要返回成功以及必要信息方便后期请求携带。
请求允许的加上x-proxy,注意option请求是拿不到具体的值
坏处:无法使用框架自带的options处理

s.BindMiddlewareDefault(func(r *ghttp.Request) {// 根据code拿到地址accessControlHeaders := r.Header.Get("Access-Control-Request-Headers")isProxy := strings.Contains(accessControlHeaders, "x-proxy")argusvoiceCode := r.GetHeader("x-proxy")r.Header.Set("Access-Control-Allow-Origin", "*")g.Log().Infof("[argusvoice] argusvoiceCode=%s", argusvoiceCode)if isProxy || (argusvoiceCode != "") {argusvoiceApi := service.GetArgusVoiceUrlByCode(argusvoiceCode)if r.Request.Method == "OPTIONS" {r.Response.Status = 200// 以下头部请参照自己正常请求的头部r.Response.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) //此处不能写作*r.Response.Header().Set("Access-Control-Allow-Credentials", "true")r.Response.Header().Set("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token, x-token, x-requested-with,Accept,Origin,Referer,User-Agent,x-proxy")r.Response.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, PATCH, DELETE")r.Response.Header().Set("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")return}g.Log().Infof("[argusvoice] argusvoiceApi=%s", argusvoiceApi)remote, err := url.Parse(argusvoiceApi)if err != nil {fmt.Println(err.Error())g.Log().Errorf("[argusvoice] url parse error, argusvoiceApi=%s, error=%v", argusvoiceApi, err)}reverseProxy := proxy.GoReverseProxy(&proxy.RProxy{Remote: remote,})if err != nil {fmt.Println(err.Error())r.ExitAll()return}reverseProxy.ServeHTTP(r.Response.Writer, r.Request)r.ExitAll()} else {r.Middleware.Next()}
})

proxy文件:(此处代码大部分抄自https://github.com/hezhizheng/go-reverse-proxy/blob/master/handle.go)
该项目使用案例:https://hzz.cool/blog/implementation-of-simple-http-and-https-reverse-proxy-by-golang

package proxyimport ("github.com/gogf/gf/frame/g""net/http""net/http/httputil""net/url""strings"
)type RProxy struct {Remote *url.URL
}func GoReverseProxy(this *RProxy) *httputil.ReverseProxy {remote := this.Remoteproxy := httputil.NewSingleHostReverseProxy(remote)proxy.Director = func(request *http.Request) {Path := ""targetQuery := remote.RawQueryrequest.URL.Scheme = remote.Schemerequest.URL.Host = remote.Hostrequest.Host = remote.HostPath, request.URL.RawPath = joinURLPath(remote, request.URL)Paths := strings.Split(Path, "/argusx")request.URL.Path = Paths[1]g.Log().Infof("[argusvoice] request.Body=%v", request.Body)if targetQuery == "" || request.URL.RawQuery == "" {request.URL.RawQuery = targetQuery + request.URL.RawQuery} else {request.URL.RawQuery = targetQuery + "&" + request.URL.RawQuery}g.Log().Infof("[argusvoice] request.URL.Path=%s, request.URL.RawQuery=%s", request.URL.Path, request.URL.RawQuery)}proxy.ModifyResponse = func(response *http.Response) error {response.Header.Del("Access-Control-Allow-Origin")response.Header.Del("Access-Control-Allow-Credentials")response.Header.Del("Access-Control-Allow-Headers")response.Header.Del("Access-Control-Allow-Methods")return nil}return proxy
}// go sdk 源码
func joinURLPath(a, b *url.URL) (path, rawpath string) {if a.RawPath == "" && b.RawPath == "" {return singleJoiningSlash(a.Path, b.Path), ""}// Same as singleJoiningSlash, but uses EscapedPath to determine// whether a slash should be addedapath := a.EscapedPath()bpath := b.EscapedPath()aslash := strings.HasSuffix(apath, "/")bslash := strings.HasPrefix(bpath, "/")switch {case aslash && bslash:return a.Path + b.Path[1:], apath + bpath[1:]case !aslash && !bslash:return a.Path + "/" + b.Path, apath + "/" + bpath}return a.Path + b.Path, apath + bpath
}// go sdk 源码
func singleJoiningSlash(a, b string) string {aslash := strings.HasSuffix(a, "/")bslash := strings.HasPrefix(b, "/")switch {case aslash && bslash:return a + b[1:]case !aslash && !bslash:return a + "/" + b}return a + b
}

相关文章:

跨域案例go gf ,请求代理,前端请求后端A转发给多个后端B

跨域案例go gf ,请求代理,前端请求后端A转后端B 案例:从前端请求后端A(路径携带argusx),后端A转发请求到多个不同地区(可一个)后端B(切掉argusx,其他不变进行请求)&…...

9.4 集成功率放大电路

OTL、OCL 和 BTL 电路均有各种不同输出功率和不同电压增益的集成电路。应当注意,在使用 OTL 电路时,需外接输出电容。为了改善频率特性,减小非线性失真,很多电路内部还引入深度负反馈。这里以低频功放为例。 一、集成功率放大电路…...

Java“牵手“拼多多商品详情数据、拼多多优惠券信息、拼多多到手价信息获取方法,拼多多API实现批量商品数据抓取示例

拼多多商城是一个网上购物平台,售卖各类商品,包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取拼多多商品详情数据,您可以通过开放平台的接口或者直接访问拼多多商城的网页来获取商品详情信息。以下是两种常用方法的介绍:…...

亚马逊云科技 re:Inforce 大会云安全合规与技术实践及 Security Jam 大赛,快来报名吧!...

‍‍ 2023年8月31日在北京 亚马逊云科技 re:Inforce 大会 首次登陆中国! 我们期待您的莅临, 并与您一起迎接 AI 时代, 开启全面智能的安全旅程! 在13:00-17:00的 培训与动手实验环节中 云安全合规与技术实践 及 Security Jam 大赛…...

网络安全(黑客技术)学习手册

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高; 二、则是发展相对成熟…...

泡泡玛特回应头部IP营收增速放缓:IP上市时间不固定

8月23日,针对今年上半年头部IP营收增速放缓问题,泡泡玛特(09992.HK)管理层在业绩会上解释称,每个IP上市时间并不固定,单从上半年看同比增长会有偏差,而随着下半年两个新系列的推出,全…...

很干的 Nginx

🎨 前言 本篇文章有些概念性的东西,是结合自己的理解表达出来的,可能有些理解不到位的地方。希望多多指教,谢谢大家。 红包献上 🧧🧧🧧🧧🧧🧧🧧…...

【已解决】pycharm突然双击无法打开,重启电脑也不管用

1.问题: pycharm突然双击无法打开,重启电脑也不管用 2.解决 2.1 方法一(修改Roaming) 1.找到C盘对应路径下的pycharm版本 2. 用记事本打开文件类型为VMOPTIONS文件 3. 修改或删除最后一行的映射路径 4.保存退出 2.2 方法二…...

【HCIP】15.MPLS基础

多协议标签交换 MPLS位于TCP/IP协议栈中的数据链路层和网络层之间,可以向所有网络层提供服务。 通过在数据链路层和网络层之间增加额外的MPLS头部,基于MPLS头部实现数据快速转发。 术语 MPLS域(MPLS Domain):一系列…...

热烈祝贺重庆融能成功入选航天系统采购供应商库

经过航天系统采购平台的严审,重庆融能机电设备股份有限公司成功入选中国航天系统采购供应商库。航天系统采购平台是航天系统内企业采购专用平台,服务航天全球范围千亿采购需求,目前,已有华为、三一重工、格力电器、科大讯飞等企业…...

隧道vs免费爬虫ip:为何要选择隧道爬虫ip?

在网络爬虫的世界中,爬虫ip是一项关键技术,它可以帮助我们隐藏身份、突破限制、提高抓取效率。但是,在选择爬虫ip时,我们常常会面对隧道爬虫ip和免费爬虫ip之间的抉择。在本文中,我们将探讨隧道爬虫ip相对于免费爬虫ip…...

C++day6(多态实现动物园的讲解员和动物表演的相关介绍、用函数模板实现不同数据类型的交换功能)

1.比喻:动物园的讲解员和动物表演 想象一下你去了一家动物园,看到了许多不同种类的动物,如狮子、大象、猴子等。现在,动物园里有一位讲解员,他会为每种动物表演做简单的介绍。 在这个场景中,我们可以将动…...

多线程学习之生产者和消费者与阻塞队列的关系

生产者和消费者 概述: 生产者消费者问题,实际上主要是包含了两类线程: 生产者线程用于生产数据消费者线程用于消费数据 生产者和消费者之间通常会采用一个共享的数据区域,这样就可以将生产者和消费者进行解耦, 两…...

JAVA语言代入电商平台api接口拼多多根据关键词获取商品列表示例

拼多多根据关键词获取商品接口的意义; 实现商品搜索:通过关键词搜索商品API接口,电商平台可以为消费者提供一个简单、快捷的商品搜索功能。用户只需输入关键词,就可以得到与该关键词相关的商品列表。 提供便捷的商品搜索服务&…...

Centos7更新glibc2.18

Centos7更新glibc2.18 查看glibc版本下载解压glibc2.18编译安装结果验证 查看glibc版本 # 查看glibc版本 ldd --version下载解压glibc2.18 参考: https://blog.csdn.net/qq_39295044/article/details/86685789 https://blog.csdn.net/myhes/article/details/106923039 # 下载…...

QT初学者该安装qt creator哪个版本?

对于Qt初学者,建议安装最新版本的Qt Creator。Qt Creator是Qt官方提供的集成开发环境(IDE),用于开发Qt应用程序。每个Qt版本都会配套提供对应的Qt Creator版本,确保兼容性和稳定性。同时,选择合适的Qt版本也…...

VR智慧校园资中控管理平台综合提升了课堂教学质量

随着越来越多高校在课堂中引进VR虚拟仿真实训系统,为了方便老师对全班同学进行高效率地管理,VR中控平台应运而生。下面为您详细介绍VR中控平台在课堂教学中的应用优势。 VR中控系统安装在教师总控端,融合了课件、视频、3D动画等丰富的教学资源…...

【Go 基础篇】Go语言中的数组:初识与应用

Go语言以其简洁、高效和强大的特性在编程界广受欢迎。数组作为一种基本的数据结构,在各种应用场景中扮演着重要角色。本文将引入Go语言中的数组,介绍其特点、创建、初始化以及基本应用,为你打开数组的大门。 前言 数组是一种固定大小的数据…...

(vue)el-table 怎么把表格列中相同的数据 合并为一行

(vue)el-table 怎么把表格列中相同的数据 合并为一行 效果&#xff1a; 文档解释&#xff1a; 写法&#xff1a; <el-table:data"tableData"size"mini"class"table-class"borderstyle"width:100%"max-height"760":span-…...

精准高效农业作业,植保无人机显身手

中国作为农业大国&#xff0c;拥有约18亿亩的农田&#xff0c;每年都需要进行种子喷洒和农药施用等农业作业&#xff0c;对于普通农户来说&#xff0c;这是一项耗时耗力的工程&#xff0c;同时&#xff0c;人工喷洒农药极易造成农药慢性中毒&#xff0c;对农民的身体健康产生极…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型

在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重&#xff0c;适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解&#xff0c;并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...

Python异步编程:深入理解协程的原理与实践指南

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 持续学习&#xff0c;不断…...