正向圈圈

go doc http.Transport
在這個接口下進行http協議的讀寫. 因此只要是實現了這個接口也就實現http協議.
代理的思路如下:
1. 本地開啓一個http服務接受請求.
2. 收到請求之後正確的向下一個節點(下一個代理或者真正的服務器)發送請求
3. 從下一個節點接收相應並正確的傳遞給用戶.
也就是充當一個中間人.

在處理請求和相應過程中的step 1/2/3分別是:
1.復制一個request. 並修改/插入header信息.
如果頭部有X-Forwarded-For字段, 則添加上一個節點的IP地址
2. 採用http.Transport實力的RoundTrip投遞請求, 拿到相應的http.Response.
需要做一些 error判定.
3. 把拿到的Reponse寫入http.ResponseWriter(在go裏的操作)

package main

import (
    "fmt"
    "io"
    "net"
    "net/http"
    "strconv"
    "strings"
    "time"
)

func main() {
    port := 8081
    fmt.Println("Proxy serve on :" + strconv.Itoa(port))

    svr := http.NewServeMux()
    svr.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
        fmt.Printf("Received request %s %s %s\n",
            req.Method,
            req.Host,
            req.RemoteAddr,
        )

        transport := http.DefaultTransport

        // step 1
        outReq := new(http.Request)
        *outReq = *req // this only does shallow copies of maps

        if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
            if prior, ok := outReq.Header["X-Forwarded-For"]; ok {
                clientIP = strings.Join(prior, ", ") + ", " + clientIP
            }
            outReq.Header.Set("X-Forwarded-For", clientIP)
        }

        // step 2
        res, err := transport.RoundTrip(outReq)
        if err != nil {
            rw.WriteHeader(http.StatusBadGateway)
            return
        }

        // step 3
        for key, value := range res.Header {
            for _, v := range value {
                rw.Header().Add(key, v)
            }
        }

        rw.WriteHeader(res.StatusCode)
        io.Copy(rw, res.Body)
        res.Body.Close()
    })

    serverInstance := http.Server{
        Addr:           fmt.Sprintf(":%d", port),
        ReadTimeout:    10 * time.Second,
        Handler:        svr,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    rv := serverInstance.ListenAndServe()
    fmt.Printf("\n%v", rv)
    // http.HandleFunc("/", SomeServeHTTP)
    // http.ListenAndServe(fmt.Sprintf(":%d", port), nil)

}

原文鏈接:
http://cizixs.com/2017/03/21/http-proxy-and-golang-implementation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值