github.com/igoogolx/clash@v1.19.8/listener/http/upgrade.go (about) 1 package http 2 3 import ( 4 "net" 5 "net/http" 6 "strings" 7 8 "github.com/igoogolx/clash/adapter/inbound" 9 N "github.com/igoogolx/clash/common/net" 10 C "github.com/igoogolx/clash/constant" 11 "github.com/igoogolx/clash/transport/socks5" 12 ) 13 14 func isUpgradeRequest(req *http.Request) bool { 15 for _, header := range req.Header["Connection"] { 16 for _, elm := range strings.Split(header, ",") { 17 if strings.EqualFold(strings.TrimSpace(elm), "Upgrade") { 18 return true 19 } 20 } 21 } 22 23 return false 24 } 25 26 func handleUpgrade(conn net.Conn, request *http.Request, in chan<- C.ConnContext) { 27 defer conn.Close() 28 29 removeProxyHeaders(request.Header) 30 removeExtraHTTPHostPort(request) 31 32 address := request.Host 33 if _, _, err := net.SplitHostPort(address); err != nil { 34 address = net.JoinHostPort(address, "80") 35 } 36 37 dstAddr := socks5.ParseAddr(address) 38 if dstAddr == nil { 39 return 40 } 41 42 left, right := net.Pipe() 43 44 in <- inbound.NewHTTP(dstAddr, conn.RemoteAddr(), conn.LocalAddr(), right) 45 46 bufferedLeft := N.NewBufferedConn(left) 47 defer bufferedLeft.Close() 48 49 err := request.Write(bufferedLeft) 50 if err != nil { 51 return 52 } 53 54 resp, err := http.ReadResponse(bufferedLeft.Reader(), request) 55 if err != nil { 56 return 57 } 58 59 removeProxyHeaders(resp.Header) 60 61 err = resp.Write(conn) 62 if err != nil { 63 return 64 } 65 66 if resp.StatusCode == http.StatusSwitchingProtocols { 67 N.Relay(bufferedLeft, conn) 68 } 69 }