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  }