当前位置: 首页 > 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;对农民的身体健康产生极…...

用Logisim搞定Educoder交通灯实训:从数码管驱动到状态机集成的保姆级避坑指南

用Logisim征服Educoder交通灯实训&#xff1a;从零搭建到联调的全链路实战手册 第一次打开Educoder平台的交通灯实训项目时&#xff0c;我盯着那些闪烁的数码管和错综复杂的线路图&#xff0c;感觉像在破解某种外星密码。三小时后&#xff0c;当我的第一个状态机模块终于通过测…...

TongWEB(东方通)实战:从零部署企业级WEB前后端项目

1. 环境准备&#xff1a;银河麒麟系统下的基础搭建 在银河麒麟桌面系统V10(SP1)兆芯版上部署企业级WEB项目&#xff0c;环境准备是第一步。我遇到过不少开发者直接跳过环境检查就急着部署&#xff0c;结果浪费大量时间排查兼容性问题。这里分享几个关键点&#xff1a; 首先是系…...

抖音批量下载神器:5分钟学会免费高效下载视频、音乐和直播

抖音批量下载神器&#xff1a;5分钟学会免费高效下载视频、音乐和直播 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback s…...

技术视角:Sketchfab数据提取工具深度解析3D模型下载机制

技术视角&#xff1a;Sketchfab数据提取工具深度解析3D模型下载机制 【免费下载链接】sketchfab sketchfab download userscipt for Tampermonkey by firefox only 项目地址: https://gitcode.com/gh_mirrors/sk/sketchfab 在WebGL技术日益成熟的今天&#xff0c;Sketch…...

5分钟掌握小红书无水印下载:让内容保存效率提升300%

5分钟掌握小红书无水印下载&#xff1a;让内容保存效率提升300% 【免费下载链接】XHS-Downloader 小红书&#xff08;XiaoHongShu、RedNote&#xff09;链接提取/作品采集工具&#xff1a;提取账号发布、收藏、点赞、专辑作品链接&#xff1b;提取搜索结果作品、用户链接&#…...

DLP/SLA光固化3D打印技术解析与Ember打印机实战指南

1. DLP/SLA 3D打印技术深度解析&#xff1a;从光与树脂的对话说起如果你是从FDM&#xff08;熔丝制造&#xff09;打印转向树脂打印的&#xff0c;那感觉就像从开手动挡卡车换到了开精密数控机床。DLP&#xff08;数字光处理&#xff09;和SLA&#xff08;立体光刻&#xff09;…...

番茄小说下载器终极指南:3分钟打造你的私人数字图书馆

番茄小说下载器终极指南&#xff1a;3分钟打造你的私人数字图书馆 【免费下载链接】fanqienovel-downloader 下载番茄小说 项目地址: https://gitcode.com/gh_mirrors/fa/fanqienovel-downloader 你是否曾在深夜追更小说时&#xff0c;突然发现网络连接中断&#xff1f;…...

SoC片上系统:从架构原理到选型实战的深度解析

1. 项目概述&#xff1a;从“黑盒子”到“智慧核心”的认知跃迁在电子产品的世界里&#xff0c;我们常常惊叹于一部智能手机的纤薄与强大&#xff0c;它既能流畅播放高清视频&#xff0c;又能处理复杂的游戏画面&#xff0c;还能实时连接网络、定位导航。这一切的背后&#xff…...

MCP-Commander:让AI助手操作本地文件与命令行的智能接口

1. 项目概述&#xff1a;一个连接思维与执行的智能接口最近在折腾AI工作流的时候&#xff0c;发现了一个挺有意思的项目&#xff0c;叫nmindz/mcp-commander。乍一看这个名字&#xff0c;可能有点摸不着头脑&#xff0c;但如果你正在尝试让大型语言模型&#xff08;LLM&#xf…...

MySQL-MVCC核心原理-版本链ReadView与可见性判断

MVCC 全称是 Multi-Version Concurrency Control&#xff0c;也就是多版本并发控制。它的核心思想是&#xff1a;为同一行数据维护多个版本&#xff0c;让读写在很多情况下不用互相阻塞。 没有 MVCC 时&#xff0c;读写冲突通常要大量依赖锁。MVCC 让普通 select 可以读一个可见…...