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  }