Go代理浏览器http请求
问题
因为网络问题,有些网页访问不了,于是想通过自己的云服务器,去代理浏览器的请求。在网上查阅如何用Go代理http请求,有些用Proxy转发,结果发现没用,返回的是一个文本,甚至无法请求。通过查阅浏览器网页请求原理后,自己写了段代码,简单实现了http请求代理,网页成功可以渲染出来。
原理
通过go自带的"net/http"包发送http请求
client := http.Client{}
//"http://www.XiuRen/12276.html"
resp, err := client.Get(r.URL.Scheme + ":" + r.URL.Host + "/" + r.URL.Path)
之后把结果返回到写回浏览器,在写回的时候要注意写好请求头的文件格式,不写文件格式都是文本格式
w.Header().Set("Content-Type", resp.Header.Get("Content-Type")) w.WriteHeader(resp.StatusCode)
全部代码
package main
import (
"fmt"
"io"
"os"
"os/signal"
"strings"
"syscall"
"log"
"net/http"
)
var logger log.Logger
type proxy struct {
}
func NewRoutes() http.Handler {
return &proxy{}
}
func (router *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Println("URL:", r.URL.Path)
var err error
//按照分隔符'/'对路径进行分解,获取服务名称serviceName
r.URL.Scheme = "http"
r.URL.Path = r.URL.Path
client := http.Client{}
if r.Referer() == "" {
pathArray := strings.Split(r.URL.Path, "/")
r.URL.Host = pathArray[0]
} else {
pathArray := strings.Split(r.Referer(), "/")
r.URL.Host = "/" + pathArray[len(pathArray)-1]
}
fmt.Println("compare:", "host:", r.URL.Host, "referer:", r.Referer())
fmt.Println("client:", r.URL.Scheme+":"+r.URL.Host+"/"+r.URL.Path)
resp, err := client.Get(r.URL.Scheme + ":/" + r.URL.Host + r.URL.Path)
if err != nil {
log.Println(err)
}
w.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
w.WriteHeader(resp.StatusCode)
defer resp.Body.Close()
io.Copy(w, resp.Body)
}
func main() {
var handle http.Handler
handle = NewRoutes()
errchan := make(chan error)
go func() {
errchan <- http.ListenAndServe(":9001", handle)
fmt.Println("http server at:", "127.0.0.1"+":"+"9001")
}()
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
errchan <- fmt.Errorf("%s", <-c)
}()
error := <-errchan
fmt.Println("err:", error)
}
例子
运行后修改浏览器的请求域名
http://127.0.0.1:9001/www.howzhi.com
由于只是简单实现,所以有些网站还不能很好代理,根据具体网站修改下便可以用。