ListenAndServe与浏览器之间建立的链接,为什么不能复用啊?

启动了一个ListenAndServe,浏览器访问,当似乎每一个文件都新建了一个connection,打开第二个网页,之前的connection没有使用,还是重新建立了新的conn。。。
这个问题可能是什么原因啊?

代码

package main

import (
    "bufio"
    "bytes"
    "flag"
    "fmt"
    "log"
    "net"
    "net/http"
    "net/url"
    "regexp"

    "github.com/elazarl/goproxy"
    "github.com/inconshreveable/go-vhost"
)

func orPanic(err error) {
    if err != nil {
        panic(err)
    }
}

func main() {
    verbose := flag.Bool("v", true, "should every proxy request be logged to stdout")
    http_addr := flag.String("httpaddr", ":3129", "proxy http listen address")
    https_addr := flag.String("httpsaddr", ":3128", "proxy https listen address")
    flag.Parse()

    proxy := goproxy.NewProxyHttpServer()
    proxy.Verbose = *verbose
    if proxy.Verbose {
        log.Printf("Server starting up! - configured to listen on http interface %s and https interface %s", *http_addr, *https_addr)
    }

    proxy.NonproxyHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
        if req.Host == "" {
            fmt.Fprintln(w, "Cannot handle requests without Host header, e.g., HTTP 1.0")
            return
        }
        req.URL.Scheme = "http"
        req.URL.Host = req.Host
        proxy.ServeHTTP(w, req)
    })
    proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*$"))).
        HandleConnect(goproxy.AlwaysMitm)
    proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*:80$"))).
        HijackConnect(func(req *http.Request, client net.Conn, ctx *goproxy.ProxyCtx) {
        defer func() {
            if e := recover(); e != nil {
                ctx.Logf("error connecting to remote: %v", e)
                client.Write([]byte("HTTP/1.1 500 Cannot reach destination\r\n\r\n"))
            }
            client.Close()
        }()
        clientBuf := bufio.NewReadWriter(bufio.NewReader(client), bufio.NewWriter(client))
        remote, err := connectDial(proxy, "tcp", req.URL.Host)
        orPanic(err)
        remoteBuf := bufio.NewReadWriter(bufio.NewReader(remote), bufio.NewWriter(remote))
        for {
            req, err := http.ReadRequest(clientBuf.Reader)
            orPanic(err)
            orPanic(req.Write(remoteBuf))
            orPanic(remoteBuf.Flush())
            resp, err := http.ReadResponse(remoteBuf.Reader, req)
            orPanic(err)
            orPanic(resp.Write(clientBuf.Writer))
            orPanic(clientBuf.Flush())
        }
    })

    go func() {
        log.Fatalln(http.ListenAndServe(*http_addr, proxy))
    }()

    // listen to the TLS ClientHello but make it a CONNECT request instead
    ln, err := net.Listen("tcp", *https_addr)
    if err != nil {
        log.Fatalf("Error listening for https connections - %v", err)
    }
    for {
        c, err := ln.Accept()
        if err != nil {
            log.Printf("Error accepting new connection - %v", err)
            continue
        }
        go func(c net.Conn) {
            tlsConn, err := vhost.TLS(c)
            if err != nil {
                log.Printf("Error accepting new connection - %v", err)
            }
            if tlsConn.Host() == "" {
                log.Printf("Cannot support non-SNI enabled clients")
                return
            }
            connectReq := &http.Request{
                Method: "CONNECT",
                URL: &url.URL{
                    Opaque: tlsConn.Host(),
                    Host:   net.JoinHostPort(tlsConn.Host(), "443"),
                },
                Host:   tlsConn.Host(),
                Header: make(http.Header),
            }
            resp := dumbResponseWriter{tlsConn}
            proxy.ServeHTTP(resp, connectReq)
        }(c)
    }
}

// copied/converted from https.go
func dial(proxy *goproxy.ProxyHttpServer, network, addr string) (c net.Conn, err error) {
    if proxy.Tr.Dial != nil {
        return proxy.Tr.Dial(network, addr)
    }
    return net.Dial(network, addr)
}

// copied/converted from https.go
func connectDial(proxy *goproxy.ProxyHttpServer, network, addr string) (c net.Conn, err error) {
    if proxy.ConnectDial == nil {
        return dial(proxy, network, addr)
    }
    return proxy.ConnectDial(network, addr)
}

type dumbResponseWriter struct {
    net.Conn
}

func (dumb dumbResponseWriter) Header() http.Header {
    panic("Header() should not be called on this ResponseWriter")
}

func (dumb dumbResponseWriter) Write(buf []byte) (int, error) {
    if bytes.Equal(buf, []byte("HTTP/1.0 200 OK\r\n\r\n")) {
        return len(buf), nil // throw away the HTTP OK response from the faux CONNECT request
    }
    return dumb.Conn.Write(buf)
}

func (dumb dumbResponseWriter) WriteHeader(code int) {
    panic("WriteHeader() should not be called on this ResponseWriter")
}

func (dumb dumbResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
    return dumb, bufio.NewReadWriter(bufio.NewReader(dumb), bufio.NewWriter(dumb)), nil
}
Contact GitHub API Training Shop Blog About

共 1 个回复