Golang正向代理
正向代理
一种客户端代理技术,用于帮助客户端访问无法直接访问的网络资源,并隐藏客户端IP,浏览器HTTP代理
实践
代理接收客户端发送的请求,复制该请求对象,根据实际需要修改请求参数。
构造新的请求,发送到服务器,并获取服务端响应
将接收到的内容返回给客户端
package main
import (
"fmt"
"io"
"log"
"net"
"net/http"
"strings"
)
type proxy struct{}
func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
//接收http请求
fmt.Printf("接收到请求:方法 %s 域名 %s 地址 %s 长度 %d", r.Method, r.Host, r.RemoteAddr, r.ContentLength)
//修改 构造新请求
transport := http.DefaultTransport
//copy源请求,避免影响源对象
req := new(http.Request)
//将源http请求给新new出的对象
*req = *r
//设置X-Forward-For请求头
/*
SplitHostPort 拆分“host:port”形式的网络地址,
"host%zone:port"、"[host]:port" 或 "[host%zone]:port" 进入主机或
主机%区域和端口。
*/
clientIP, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
log.Println("SplitHostPort error", err)
}
//req.header是一个map
if v, ok := req.Header["X-Forward-For"]; ok {
clientIP = strings.Join(v, ", ") + ", " + clientIP
fmt.Println("构造后的clientIP : ", clientIP)
}
req.Header.Set("X-Forward-For", clientIP)
//构造新request请求
response, err := transport.RoundTrip(req)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
//获取数据并返回
for k, v := range response.Header {
for _, v1 := range v {
w.Header().Add(k, v1)
}
w.WriteHeader(response.StatusCode)
io.Copy(w, response.Body)
response.Body.Close()
}
}
func main() {
server := &http.Server{
Addr: ":9090",
Handler: &proxy{},
}
if err := server.ListenAndServe(); err != nil {
log.Fatal("Http proxy server start failed.")
}
}
curl -x 127.0.0.1:9090 http://www.baidu.com
经测试 http正常 https无法正常使用