实现的效果:

如果访问的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反向代理)的更多相关文章

  1. windows环境下 nginx+iis 反向代理解决跨域问题

    项目基本完成,是时候花点时间整理一下最近的姿势了 1 什么是跨域? 网上对于跨域的概念会有大篇幅的文章去解释,似乎有点玄乎,初学者很容易对这个概念产生恐惧,跨域其实很简单,其实只要知道一点,无法跨域访 ...

  2. 利用nginx做反向代理解决前端跨域问题

    最近朋友再群里提了一个问题,他们公司给他提供了一个获取数据的接口,在浏览器访问这个接口能获取到json数据,但是放在项目里使用ajax就产生了跨域问题,一般这个需要提供接口的后台方面需要做跨域处理,但 ...

  3. 前端通过Nginx反向代理解决跨域问题

    在前面写的一篇文章SpringMVC 跨域,我们探讨了什么是跨域问题以及SpringMVC怎么解决跨域问题,解决方式主要有如下三种方式: JSONP CORS WebSocket 可是这几种方式都是基 ...

  4. nginx反向代理-解决前端跨域问题

    1.定义 跨域是指a页面想获取b页面资源,如果a.b页面的协议.域名.端口.子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源.注意:跨域限制访 ...

  5. nginx反向代理解决跨域问题

    跨域:浏览器从一个域名的网页去请求另一个域名的资源时,域名.端口.协议任一不同,都是跨域 . 下表格为前后端分离的域名,技术信息:   域名 服务器 使用技术 前端 http://b.yynf.com ...

  6. Nginx入门及如何反向代理解决生产环境跨域问题

    1.Nginx入门与基本操作篇 注:由于服务器是windows系统,所以本文主要讲解Nginx在windows下的操作. 首先下载Nginx 解压缩,我们所有的配置基本都在万能的 nginx/conf ...

  7. Nginx 反向代理解决跨域问题分析

    当你遇到跨域问题,不要立刻就选择复制去尝试.请详细看完这篇文章再处理 .我相信它能帮到你. 分析前准备: 前端网站地址:http://localhost:8080 服务端网址:http://local ...

  8. [转]用apache反向代理解决单外网ip对应内网多个web主机的问题

    用apache反向代理解决单外网ip对应内网多个web主机的问题 转载一个有独立外网IP,需内网服务器对外发布的例子,是应用apache虚拟主机的. 来源地址:http://www.itshantou ...

  9. 使用 ssh -R 建立反向/远程TCP端口转发代理

    转自:https://yq.aliyun.com/articles/8469 ssh是一个非常棒的工具, 不但能建立动态转发, 例如chrome的Switchy插件用到的就是这个技术.http://b ...

  10. 使用nginx反向代理解决前端跨域问题

    1. 首先去Nginx官网下载一个最新版本的Nginx,下载地址:http://nginx.org/en/download.html.我这里下载的版本是:nginx/Windows-1.12.0.下载 ...

随机推荐

  1. 如何区分Unity国内版和国际版

    从这三个地方都可以判断使用的Unity是国内版本还是国际版,国内版的版本号后面会多出c1,而国际版则不会有c1结尾. 安装目录名 unity hub - 安装 - 查看当前安装的Unity各版本 un ...

  2. border多层渐变

    .content { margin-top: 19px; border-top: 1px dashed rgba(113, 183, 248, 0.6) !important; border-left ...

  3. 【3】jupyter notebook【修改主题、字体、字号、代码自动补全、变更工作目录、添加目录插件、解决工具栏隐藏问题、修改默认浏览器、默认打开位置】

    相关文章: [1]Anaconda安装超简洁教程,瞬间学会! [2]Anaconda下:ipython文件的打开方式,Jupyter Notebook中运行.py文件,快速打开ipython文件的方法 ...

  4. CentOS7设置防火墙

    ①查看防火状态 systemctl status firewalld service iptables status ②暂时关闭防火墙 systemctl stop firewalld service ...

  5. Hadoop3 No FileSystem for scheme "hdfs"

    Hadoop3 No FileSystem for scheme "hdfs" 异常信息: org.apache.hadoop.fs.UnsupportedFileSystemEx ...

  6. 使用Nuget快速集成.Net三维控件

    据老一辈的程序员说开发三维程序门槛很高,需要学若干年才能入门,自从遇上AnyCAD三维控件后,开发三维应用变的简单了.当结合nuget后,一切更简单了. 1 准备工作 安装VS201x以后,就可以开始 ...

  7. 使用Docker部署Tomcat

    目录 使用Docker部署Tomcat 1. 获取镜像 2. 第一次启动tomcat 3.带参数启动 4.查看tomcat日志 5.时区问题 使用Docker部署Tomcat 1. 获取镜像 dock ...

  8. Windows开机自动同步时间

    前言   有些Windows客户端因主板电池没电或其他原因,每次启动系统后,读取到BIOS的时间是初始时间(1970年)或错误的时间,这时需要系统启动后立即向时间服务器同步一次时间.   该方法是添加 ...

  9. XPath从入门到精通:基础和高级用法完整指南,附美团APP匹配示例

    XPath 通常用来进行网站.XML (APP )和数据挖掘,通过元素和属性的方式来获取指定的节点,然后抓取需要的信息. 学习 XPath 语法之前,首先了解一下一些概念. 概念介绍 节点之间的关系 ...

  10. Linux(CentOS)设置密码永不过期

    Linux服务器有默认的密码修改时间,默认是90天.这种情况下,即使设置过免密登录(互信),当密码到期后,依然需要输入服务器密码. 那么如何设置用户的密码永不过期呢? 一.查看密码过期时间 在root ...