zoukankan      html  css  js  c++  java
  • Golang 简单 http 代理转发

    程序基本实现了对http的完整转发,目前暂不支持https

    windows需要在设置中的网络>代理设置为手动,并开启代理服务器,填写ip和端口

    // httpForward
    package main
    
    import (
        "fmt"
        "io"
        "io/ioutil"
        "net/http"
        "os"
        "strconv"
        "strings"
    )
    
    func HttpForward(pattern string, port int) {
        http.HandleFunc(pattern, doGo)
        strPort := strconv.Itoa(port)
        fmt.Print("listenning on :", " ", pattern, " ", strPort, "
    ")
        err := http.ListenAndServe(":"+strPort, nil)
        if err != nil {
            fmt.Println(err)
            os.Exit(1)
        }
    }
    
    func doGo(w http.ResponseWriter, r *http.Request) {
    
        //r.host不带http,r.url是完整的url
        //fmt.Println(r.Host, " ", r.URL, "
    ")
    
        fmt.Println("url: ", r.URL)
    
        //查看url各个信息
        // str := "hi ,it is working"
        // b := []byte(str)
        //w.Write(b)
        //fmt.Print(r.Host, " ", r.Method, " 
    r.URL.String ", r.URL.String(), " r.URL.Host ", r.URL.Host, " r.URL.Fragment ", r.URL.Fragment, " r.URL.Hostname ", r.URL.Hostname(), " r.URL.RequestURI ", r.URL.RequestURI(), " r.URL.Scheme ", r.URL.Scheme)
    
        cli := &http.Client{}
    
        //不建议用readfull,对于body大小难以判断,容易出错
        // body := make([]byte, 2048000)
        // n, err := io.ReadFull(r.Body, body)
    
        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            fmt.Print("io.ReadFull(r.Body, body) ", err.Error())
            //return,没有数据也是可以的,不需要直接结束
        }
        fmt.Print("req count :", len(body), "
    ")
    
        //fmt.Print(len(body))
        //reqUrl := r.Host + r.URL.String()
    
        reqUrl := r.URL.String()
    
        //url里带了协议类型,不需要用scheme
        // if r.URL.Scheme != "" {
        //     reqUrl = r.URL.Scheme + reqUrl
        // } else {
        //     reqUrl = "http://" + reqUrl
        // }
    
        req, err := http.NewRequest(r.Method, reqUrl, strings.NewReader(string(body)))
        if err != nil {
            fmt.Print("http.NewRequest ", err.Error())
            return
        }
    
        //用遍历header实现完整复制
        //contentType := r.Header.Get("Content-Type")
        //req.Header.Set("Content-Type", contentType)
    
        for k, v := range r.Header {
            req.Header.Set(k, v[0])
        }
        res, err := cli.Do(req)
        if err != nil {
            fmt.Print("cli.Do(req) ", err.Error())
            return
        }
        defer res.Body.Close()
    
        // n, err = io.ReadFull(res.Body, body)
        // if err != nil {
        //     fmt.Print("io.ReadFull(res.Body, body) ", err.Error())
        //     return
        // }
        //fmt.Print("count body bytes: ", n, "
    ")
    
        for k, v := range res.Header {
            w.Header().Set(k, v[0])
        }
        io.Copy(w, res.Body)
    
        //这样复制对大小控制较差,不建议。用copy即可
        // io.WriteString(w, string(body[:n]))
        // fmt.Print(string(body))
    }
    

    我发现使用https时,程序似乎接收不到请求,没有反应,不知道是不是证书的问题

  • 相关阅读:
    读书笔记
    STL 笔记
    Centos8如何配置网桥
    命令集合
    shared_ptr给管理的对象定制析沟函数
    share_ptr指向的对象的析构动作在创建的时候被捕获
    优秀博客
    字符串单词翻转
    带权图的最短路径算法(Dijkstra,Floyd,Bellman_ford)
    生产者与消费者 c++实现
  • 原文地址:https://www.cnblogs.com/boxker/p/11046342.html
Copyright © 2011-2022 走看看