github.com/metacubex/mihomo@v1.18.5/transport/vmess/http.go (about) 1 package vmess 2 3 import ( 4 "bufio" 5 "bytes" 6 "errors" 7 "fmt" 8 "net" 9 "net/http" 10 "net/textproto" 11 12 "github.com/metacubex/mihomo/common/utils" 13 14 "github.com/zhangyunhao116/fastrand" 15 ) 16 17 type httpConn struct { 18 net.Conn 19 cfg *HTTPConfig 20 reader *bufio.Reader 21 whandshake bool 22 } 23 24 type HTTPConfig struct { 25 Method string 26 Host string 27 Path []string 28 Headers map[string][]string 29 } 30 31 // Read implements net.Conn.Read() 32 func (hc *httpConn) Read(b []byte) (int, error) { 33 if hc.reader != nil { 34 n, err := hc.reader.Read(b) 35 return n, err 36 } 37 38 reader := textproto.NewConn(hc.Conn) 39 // First line: GET /index.html HTTP/1.0 40 if _, err := reader.ReadLine(); err != nil { 41 return 0, err 42 } 43 44 if _, err := reader.ReadMIMEHeader(); err != nil { 45 return 0, err 46 } 47 48 hc.reader = reader.R 49 return reader.R.Read(b) 50 } 51 52 // Write implements io.Writer. 53 func (hc *httpConn) Write(b []byte) (int, error) { 54 if hc.whandshake { 55 return hc.Conn.Write(b) 56 } 57 58 if len(hc.cfg.Path) == 0 { 59 return -1, errors.New("path is empty") 60 } 61 62 path := hc.cfg.Path[fastrand.Intn(len(hc.cfg.Path))] 63 host := hc.cfg.Host 64 if header := hc.cfg.Headers["Host"]; len(header) != 0 { 65 host = header[fastrand.Intn(len(header))] 66 } 67 68 u := fmt.Sprintf("http://%s%s", net.JoinHostPort(host, "80"), path) 69 req, err := http.NewRequest(utils.EmptyOr(hc.cfg.Method, http.MethodGet), u, bytes.NewBuffer(b)) 70 if err != nil { 71 return 0, err 72 } 73 for key, list := range hc.cfg.Headers { 74 req.Header.Set(key, list[fastrand.Intn(len(list))]) 75 } 76 req.ContentLength = int64(len(b)) 77 if err := req.Write(hc.Conn); err != nil { 78 return 0, err 79 } 80 hc.whandshake = true 81 return len(b), nil 82 } 83 84 func (hc *httpConn) Close() error { 85 return hc.Conn.Close() 86 } 87 88 func StreamHTTPConn(conn net.Conn, cfg *HTTPConfig) net.Conn { 89 return &httpConn{ 90 Conn: conn, 91 cfg: cfg, 92 } 93 }