Allow http1 in v2ray HTTP transport

This commit is contained in:
世界
2022-08-22 22:51:08 +08:00
parent 4005452772
commit a24a2b475a
4 changed files with 130 additions and 27 deletions

View File

@@ -1,6 +1,7 @@
package v2rayhttp
import (
"bufio"
"context"
"crypto/tls"
"io"
@@ -20,20 +21,25 @@ import (
var _ adapter.V2RayClientTransport = (*Client)(nil)
type Client struct {
ctx context.Context
client *http.Client
url *url.URL
host []string
method string
headers http.Header
ctx context.Context
dialer N.Dialer
serverAddr M.Socksaddr
client *http.Client
http2 bool
url *url.URL
host []string
method string
headers http.Header
}
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayHTTPOptions, tlsConfig *tls.Config) adapter.V2RayClientTransport {
client := &Client{
ctx: ctx,
host: options.Host,
method: options.Method,
headers: make(http.Header),
ctx: ctx,
dialer: dialer,
serverAddr: serverAddr,
host: options.Host,
method: options.Method,
headers: make(http.Header),
client: &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
@@ -43,6 +49,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
TLSClientConfig: tlsConfig,
},
},
http2: tlsConfig != nil,
}
if client.method == "" {
client.method = "PUT"
@@ -66,13 +73,54 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
}
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
if !c.http2 {
return c.dialHTTP()
} else {
return c.dialHTTP2()
}
}
func (c *Client) dialHTTP() (net.Conn, error) {
conn, err := c.dialer.DialContext(c.ctx, N.NetworkTCP, c.serverAddr)
if err != nil {
return nil, err
}
request := &http.Request{
Method: c.method,
URL: c.url,
ProtoMajor: 1,
Proto: "HTTP/1.1",
Header: c.headers.Clone(),
}
switch hostLen := len(c.host); hostLen {
case 0:
case 1:
request.Host = c.host[0]
default:
request.Host = c.host[rand.Intn(hostLen)]
}
err = request.Write(conn)
if err != nil {
return nil, err
}
reader := bufio.NewReader(conn)
response, err := http.ReadResponse(reader, request)
if err != nil {
return nil, err
}
if response.StatusCode != 200 {
return nil, E.New("unexpected status: ", response.Status)
}
return conn, nil
}
func (c *Client) dialHTTP2() (net.Conn, error) {
pipeInReader, pipeInWriter := io.Pipe()
request := &http.Request{
Method: c.method,
Body: pipeInReader,
URL: c.url,
ProtoMajor: 2,
ProtoMinor: 0,
Proto: "HTTP/2",
Header: c.headers.Clone(),
}