一个利用go反向代理解决api转发的例子(go反向代理)
实现的效果:
如果访问的url路径是类似 /163/ 或 /163/debian 的形式,则转发到163开源镜像服务器
直接上代码:
package main import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
) var fwdHost = "mirrors.163.com" //http首部字段的HOST取值
var fwdTo = "http://" + fwdHost + "/"
var fwdPrefix = "/163/" type forward struct {
RProxy *httputil.ReverseProxy
} func (f *forward) ServeHTTP(wr http.ResponseWriter, req *http.Request) {
//fmt.Printf("http头部是:%+v\n", req.Header) //假设这是处理http头部的代码
fmt.Printf(" #### REQ:%+v\n", req) //处理完后转发到网易163镜像
req.URL.Path = req.URL.Path[len(fwdPrefix)-1:] //修改了这里,req.RequestURI会跟着变
req.Host = fwdHost
fmt.Printf(" *** REQ:%+v\n", req)
f.RProxy.ServeHTTP(wr, req)
} func main() {
var fwd forward
u, _ := url.Parse(fwdTo)
fwd.RProxy = httputil.NewSingleHostReverseProxy(u)
http.Handle(fwdPrefix, &fwd) //所有请求将转发到网易163的debian镜像
http.HandleFunc("/", notForward)
http.HandleFunc("/api/v1/", notForward)
log.Fatal(http.ListenAndServe(":3000", nil))
} func notForward(wr http.ResponseWriter, req *http.Request) {
wr.Write([]byte(fmt.Sprintf(`<html>
<body>
<em>Not forward!!</em>
<br />
<i>url = %s</i>
</body>
</html>
`,req.URL.String())))
}
类似的还有更简单的做法,关键在httputil.ReverseProxy的Director字段:
func APIReverseProxy(host string) http.HandlerFunc {
var rp = httputil.ReverseProxy{
Director:func(req *http.Request) {
req.URL.Scheme = "http"
req.URL.Host = host
req.Host = host //对于一个ip地址托管多个域名的情况下,必须要给req.Host赋值,如果一个ip地址只有一个域名,可以不写这一句
//req.URL.Path = //如果需要改path的话
},
}
return func(wr http.ResponsWriter, req *http.Request){
rp.ServeHTTP(wr,req)
} //这里是返回http.HandlerFunc的例子,其实也可以直接返回rp(因为*rp就是一个http.Handler, *rp实现了ServeHTTP(wr,req)方法)
}
关于req.URL.Host和req.Host:
go http包中对request中Host的注释:
// For server requests Host specifies the host on which the
// URL is sought. Per RFC 2616, this is either the value of
// the "Host" header or the host name given in the URL itself.
// It may be of the form "host:port". For international domain
// names, Host may be in Punycode or Unicode form. Use
// golang.org/x/net/idna to convert it to either format if
// needed.
//
// For client requests Host optionally overrides the Host
// header to send. If empty, the Request.Write method uses
// the value of URL.Host. Host may contain an international
// domain name.
Host string
另外:
req.URL.Host是从URL中解析出来的,
req.Host是http请求头部"Host" , 这个头部用于实现虚拟主机(一个ip托管多个域名),http1.1规范中,Host头是必须存在的
对于下面的请求:
GET /index.html HTTP/1.1
Host: www.example.org:8080
req.URL.Host是空的
对于通过代理的请求,req.URL.Host是目标主机,req.Host是代理服务器。
对于不是走代理的请求,req.URL.Host是空的,req.Host是目标主机
一个利用go反向代理解决api转发的例子(go反向代理)的更多相关文章
- windows环境下 nginx+iis 反向代理解决跨域问题
项目基本完成,是时候花点时间整理一下最近的姿势了 1 什么是跨域? 网上对于跨域的概念会有大篇幅的文章去解释,似乎有点玄乎,初学者很容易对这个概念产生恐惧,跨域其实很简单,其实只要知道一点,无法跨域访 ...
- 利用nginx做反向代理解决前端跨域问题
最近朋友再群里提了一个问题,他们公司给他提供了一个获取数据的接口,在浏览器访问这个接口能获取到json数据,但是放在项目里使用ajax就产生了跨域问题,一般这个需要提供接口的后台方面需要做跨域处理,但 ...
- 前端通过Nginx反向代理解决跨域问题
在前面写的一篇文章SpringMVC 跨域,我们探讨了什么是跨域问题以及SpringMVC怎么解决跨域问题,解决方式主要有如下三种方式: JSONP CORS WebSocket 可是这几种方式都是基 ...
- nginx反向代理-解决前端跨域问题
1.定义 跨域是指a页面想获取b页面资源,如果a.b页面的协议.域名.端口.子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源.注意:跨域限制访 ...
- nginx反向代理解决跨域问题
跨域:浏览器从一个域名的网页去请求另一个域名的资源时,域名.端口.协议任一不同,都是跨域 . 下表格为前后端分离的域名,技术信息: 域名 服务器 使用技术 前端 http://b.yynf.com ...
- Nginx入门及如何反向代理解决生产环境跨域问题
1.Nginx入门与基本操作篇 注:由于服务器是windows系统,所以本文主要讲解Nginx在windows下的操作. 首先下载Nginx 解压缩,我们所有的配置基本都在万能的 nginx/conf ...
- Nginx 反向代理解决跨域问题分析
当你遇到跨域问题,不要立刻就选择复制去尝试.请详细看完这篇文章再处理 .我相信它能帮到你. 分析前准备: 前端网站地址:http://localhost:8080 服务端网址:http://local ...
- [转]用apache反向代理解决单外网ip对应内网多个web主机的问题
用apache反向代理解决单外网ip对应内网多个web主机的问题 转载一个有独立外网IP,需内网服务器对外发布的例子,是应用apache虚拟主机的. 来源地址:http://www.itshantou ...
- 使用 ssh -R 建立反向/远程TCP端口转发代理
转自:https://yq.aliyun.com/articles/8469 ssh是一个非常棒的工具, 不但能建立动态转发, 例如chrome的Switchy插件用到的就是这个技术.http://b ...
- 使用nginx反向代理解决前端跨域问题
1. 首先去Nginx官网下载一个最新版本的Nginx,下载地址:http://nginx.org/en/download.html.我这里下载的版本是:nginx/Windows-1.12.0.下载 ...
随机推荐
- rabbitmq rpm包安装以及简单设置用户的方法
公司有一台性能比较好的power机器. 同事要求安装rabbitmq 今天尝试进行了一下处理 公司里面有网络有相应的源 性能还不错 第一步安装一下依赖的erlang yum install erlan ...
- sed 删除部分行以及删除包含某些行的命令
sed的简单学习 前言: 最近进行mysql数据库的备份恢复操作,发现source 命令执行时数据库表的速度非常缓慢, 本来想通过这种方式处理一下,能够减少数据备份的处理. 删除包含内容的信息 sed ...
- 隐私集合求交(PSI)协议研究综述
摘要 隐私集合求交(PSI)是安全多方计算(MPC)中的一种密码学技术,它允许参与计算的双方,在不获取对方额外信息(除交集外的其它信息)的基础上,计算出双方数据的交集.隐私集合求交在数据共享,广告转化 ...
- Flask的cookie、session
目录 七.设置cookies 7.1 设置cookie的参数 7.2 查询cookie 八.flask的session 实现session的两种思路 8.1 设置session(使用版) 8.2 设置 ...
- CLion搭建Qt开发环境,并解决目录重构问题(最新版)
序言 Qt版本不断更新,QtCreator也不断更新.在Qt4和Qt5时代,我一直认为开发Qt最好的IDE就是自带的QtCreator,可是时至今日,到了Qt6时代,QtCreator已经都12.0. ...
- apb vnext DynamicCient
1.在需要的服务客户端(xx.HttpApi.Client)Nuget 引用和模块依赖 引用:VOLO.APB.HTTP.CLENT [dependsOn(typeof(AbpHttpClientMo ...
- 从零开始配置vim(30)——DAP的其他配置
很抱歉这么久才来更新这一系列,主要是来新公司还在试用期,我希望在试用期干出点事来,所以摸鱼的时间就少了.加上前面自己阳了休息了一段时间.在想起来更新就过去一个多月了.废话不多说了,让我们开始进入正题. ...
- Nmap 扫描并生成HTML报告
Nmap扫描器,支持生成扫描报告,配合转换模板,可实现自定义转换报告,非常方便. 扫描报告,可以生成如下格式,这是Nmap中自带的格式. nmap -PR -oX lyshark.xml 192.16 ...
- C/C++ 使用CRC检测内存映像完整性
前面的那一篇文章中所使用的技术只能有效抵抗解密者直接修改硬盘文件,当我们使用动态补丁的时候,那么内存中同样不存在校验效果,也就无法抵御对方动态修改机器码了,为了防止解密者直接对内存打补丁,我们需要在硬 ...
- Hadoop超详细讲解之单节点搭建
1 Hadoop介绍 Hadoop是Apache旗下的一个用java语言实现开源软件框架,是一个开发和运行处理大规模数据的软件平台.允许使用简单的编程模型在大量计算机集群上对大型数据集进行分布式处理. ...