github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/00_net/proxy/proxyhttp.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "log" 8 "net" 9 "net/http" 10 "net/url" 11 "strings" 12 ) 13 14 func main() { 15 log.SetFlags(log.LstdFlags | log.Lshortfile) 16 l, err := net.Listen("tcp", ":8081") 17 if err != nil { 18 log.Panic(err) 19 } 20 21 for { 22 client, err := l.Accept() 23 if err != nil { 24 log.Panic(err) 25 } 26 27 go handleClientRequest(client) 28 } 29 30 } 31 32 func handleClientRequest(client net.Conn) { 33 if client == nil { 34 return 35 } 36 defer client.Close() 37 38 var b [1024]byte 39 n, err := client.Read(b[:]) 40 if err != nil { 41 log.Println(err) 42 return 43 } 44 var method, host, address string 45 fmt.Sscanf(string(b[:bytes.IndexByte(b[:], '\n')]), "%s%s", &method, &host) 46 hostPortURL, err := url.Parse(host) 47 if err != nil { 48 log.Println(err) 49 return 50 } 51 52 if hostPortURL.Opaque == "443" { //https访问 53 address = hostPortURL.Scheme + ":443" 54 } else { //http访问 55 if strings.Index(hostPortURL.Host, ":") == -1 { //host不带端口, 默认80 56 address = hostPortURL.Host + ":80" 57 } else { 58 address = hostPortURL.Host 59 } 60 } 61 log.Println(client.RemoteAddr(), " -> ", address) 62 63 //获得了请求的host和port,就开始拨号吧 64 server, err := net.Dial("tcp", address) 65 if err != nil { 66 log.Println(err) 67 return 68 } 69 if method == http.MethodConnect { 70 fmt.Fprint(client, "HTTP/1.1 200 Connection established\r\n\r\n") 71 } else { 72 server.Write(b[:n]) 73 } 74 //进行转发 75 go io.Copy(server, client) 76 io.Copy(client, server) 77 }