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, "\n")
    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, "\n")

    fmt.Println("url: ", r.URL)

    //查看url各個信息
    // str := "hi ,it is working"
    // b := []byte(str)
    //w.Write(b)
    //fmt.Print(r.Host, " ", r.Method, " \nr.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), "\n")

    //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, "\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時,程序似乎接收不到請求,沒有反應,不知道是不是證書的問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM