亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

帶有域阻止的 http 轉發

帶有域阻止的 http 轉發

Go
三國紛爭 2022-07-11 17:33:49
我正在嘗試實現一個支持域阻止的 http 轉發服務器。我試過了go io.Copy(dst, src)go io.Copy(src, dst)它就像 tcp 轉發的魅力一樣。然后我嘗試用類似的東西來做請求行解析go func(){    reader := io.TeeReader(src, dst)    textReader := textproto.NewReader(bufio.NewReader(reader))    requestLine, _ = textReader.ReadLine()    // ...    ioutil.ReadAll(reader)}它工作正常,但我開始擔心性能不佳(使用ioutil.ReadAll)。所以我寫了下面的代碼。func (f *Forwarder) handle(src, dst net.Conn) {    defer dst.Close()    defer src.Close()    done := make(chan struct{})    go func() {        textReader := bufio.NewReader(src)        requestLine, _ = textReader.ReadString('\n')        // parse request line and apply domain blocking        dst.Write([]byte(requestLine))        io.Copy(dst, src)        done <- struct{}{}    }()    go func() {        textReader := bufio.NewReader(dst)        s.statusLine, _ = textReader.ReadString('\n')        src.Write([]byte(s.statusLine))        io.Copy(src, dst)        done <- struct{}{}    }()    <-done    <-done}不幸的是,它根本不起作用。請求可以打印出來,但不能用于響應。我一直卡在這里,不知道出了什么問題。
查看完整描述

1 回答

?
慕碼人2483693

TA貢獻1860條經驗 獲得超9個贊

TCP轉發就是實現隧道代理不需要解析數據。反向代理可以使用標準庫。


實現隧道代理以分離 http 和 https 協議。客戶端一般使用隧道發送https,發送Connect方法。發送http是Get方法。對于https請求服務,只有dail創建連接tcp轉換,http請求使用反向代理實現。


func(w http.ResponseWriter, r *http.Request) {

    // check url host

    if r.URL.Host != "" {

        if r.Method == eudore.MethodConnect {

            // tunnel proxy

            conn, err := net.Dial("tcp", r.URL.Host)

            if err != nil {

                w.WriteHeader(502)

                return

            }


            client, _, err := w.Hijack()

            if err != nil {

                w.WriteHeader(502)

                conn.Close()

                return

            }

            client.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))

            go func() {

                io.Copy(client, conn)

                client.Close()

                conn.Close()

            }()

            go func() {

                io.Copy(conn, client)

                client.Close()

                conn.Close()

            }()

        } else {

            // reverse proxy

            httputil.NewSingleHostReverseProxy(r.URL).ServeHTTP(w, r)

        }

    }

}


實現反向代理會解析客戶端請求,代理會將請求發送到目標服務器。


反向代理轉換請求,未經測試:


func(w http.ResponseWriter, r *http.Request) {

    // set host

    r.URL.Scheme = "http"

    r.URL.Path = "example.com"

    // send

    resp,err := http.DefaultClient.Do(r)

    if err != nil {

        w.WriteHeader(502)

        return

    }


    // write respsonse

    defer resp.Body.Close()

    w.WriteHeader(resp.StatusCode)

    h := w.Header()

    for k,v := range resp.Header {

        h[k]=v

    }

    io.Copy(w, resp.Body)

}

但是,直接轉發請求不處理跳到跳標頭。跳到跳標頭在rfc中明確說明。hop-to-hop header是兩個連接之間的傳輸信息。例如,客戶端到代理和代理到服務器是兩個??蛻舳说椒掌魇嵌说蕉说摹?/p>


反向代理請直接使用標準庫,它已經為您處理了跳到跳標頭和升級。


帶有過濾器的示例 NewSingleHostReverseProxy:


package main


import (

    "net/http"

    "strings"

    "net/http/httputil"

    "net/url"

)


func main() {

    addr, _ := url.Parse("http://localhost:8088")

    proxy := httputil.NewSingleHostReverseProxy(addr)

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

        if strings.HasPrefix(r.URL.Path, "/api/") {

            proxy.ServeHTTP(w, r)

        } else {

            w.WriteHeader(404)

        }

    })

    // Listen Server

}


查看完整回答
反對 回復 2022-07-11
  • 1 回答
  • 0 關注
  • 121 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號