This commit is contained in:
bxd
2023-08-02 10:09:16 +08:00
parent c46000b1d1
commit 5db82c9fed
9 changed files with 226 additions and 137 deletions

View File

@@ -4,11 +4,12 @@ import (
"context"
"crypto/tls"
"net"
"net/http"
"net/http/cookiejar"
"net/url"
"time"
"net/http"
"net/http/cookiejar"
"gitee.com/baixudong/http2"
"gitee.com/baixudong/ja3"
utls "github.com/refraction-networking/utls"
@@ -193,14 +194,11 @@ func NewClient(preCtx context.Context, options ...ClientOption) (*Client, error)
// }
// }
var http0Transport *RoundTripper
if option.Http0 {
http0Transport = NewRoundTripper(dialClient)
}
if option.H2Ja3 || option.H2Ja3Spec.IsSet() {
http2Upg = http2.NewUpg(transport, http2.UpgOption{
http2Upg = http2.NewUpg(http2.UpgOption{
H2Ja3Spec: option.H2Ja3Spec,
DialTLSContext: dialClient.requestHttp2DialTlsContext,
IdleConnTimeout: option.TLSHandshakeTimeout,
IdleConnTimeout: option.IdleConnTimeout,
TLSHandshakeTimeout: option.TLSHandshakeTimeout,
ResponseHeaderTimeout: option.ResponseHeaderTimeout,
TlsConfig: tlsConfig,
@@ -211,6 +209,9 @@ func NewClient(preCtx context.Context, options ...ClientOption) (*Client, error)
},
}
}
if option.Http0 {
http0Transport = NewRoundTripper(ctx, dialClient, http2Upg, option)
}
client := &http.Client{
Jar: jar,
CheckRedirect: func(req *http.Request, via []*http.Request) error {

View File

@@ -2,9 +2,10 @@ package requests
import (
"errors"
"net/http"
_ "unsafe"
"net/http"
"gitee.com/baixudong/tools"
"github.com/tidwall/gjson"
)

View File

@@ -7,12 +7,13 @@ import (
"errors"
"io"
"net"
"net/http"
"net/url"
"strings"
"sync"
"time"
"net/http"
"gitee.com/baixudong/ja3"
"gitee.com/baixudong/tools"
utls "github.com/refraction-networking/utls"

15
go.mod
View File

@@ -5,15 +5,17 @@ go 1.20
require (
gitee.com/baixudong/bar v0.0.0-20230726064206-c402a9061923
gitee.com/baixudong/bs4 v0.0.0-20230726070247-16e869055fa3
gitee.com/baixudong/http2 v0.0.0-20230726070349-0b364387f0f4
gitee.com/baixudong/ja3 v0.0.0-20230726070357-f35eae6532ad
gitee.com/baixudong/re v0.0.0-20230726070429-e1a623b3c133
gitee.com/baixudong/tools v0.0.0-20230726070525-d80da902e36d
gitee.com/baixudong/websocket v0.0.0-20230726070532-ab0f08baf667
github.com/refraction-networking/utls v1.3.2
github.com/tidwall/gjson v1.14.4
github.com/refraction-networking/utls v1.3.3
github.com/tidwall/gjson v1.15.0
golang.org/x/net v0.11.0
)
require gitee.com/baixudong/http2 v0.0.0-20230726070349-0b364387f0f4
require (
gitee.com/baixudong/blog v0.0.0-20230726070237-ee8a30e182ac // indirect
gitee.com/baixudong/kinds v0.0.0-20230726070402-0bc6b1ebb086 // indirect
@@ -25,7 +27,7 @@ require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/klauspost/compress v1.16.6 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/tidwall/match v1.1.1 // indirect
@@ -33,11 +35,10 @@ require (
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/image v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.11.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
nhooyr.io/websocket v1.8.7 // indirect

24
go.sum
View File

@@ -63,8 +63,8 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
@@ -77,14 +77,14 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/refraction-networking/utls v1.3.2 h1:o+AkWB57mkcoW36ET7uJ002CpBWHu0KPxi6vzxvPnv8=
github.com/refraction-networking/utls v1.3.2/go.mod h1:fmoaOww2bxzzEpIKOebIsnBvjQpqP7L2vcm/9KUfm/E=
github.com/refraction-networking/utls v1.3.3 h1:f/TBLX7KBciRyFH3bwupp+CE4fzoYKCirhdRcC490sw=
github.com/refraction-networking/utls v1.3.3/go.mod h1:DlecWW1LMlMJu+9qpzzQqdHDT/C2LAe03EdpLUz/RL8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.15.0 h1:5n/pM+v3r5ujuNl4YLZLsQ+UE5jlkLVm7jMzT5Mpolw=
github.com/tidwall/gjson v1.15.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
@@ -103,8 +103,8 @@ go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/image v0.9.0 h1:QrzfX26snvCM20hIhBwuHI/ThTg18b/+kcKdXHvnR+g=
@@ -117,8 +117,8 @@ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -130,8 +130,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=

View File

@@ -2,6 +2,7 @@ package requests
import (
"errors"
"net/http"
"gitee.com/baixudong/tools"

View File

@@ -7,12 +7,13 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"os"
"strings"
_ "unsafe"
"net/http"
"gitee.com/baixudong/re"
"gitee.com/baixudong/tools"
"gitee.com/baixudong/websocket"

View File

@@ -8,11 +8,12 @@ import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"net/http"
"gitee.com/baixudong/bar"
"gitee.com/baixudong/bs4"
"gitee.com/baixudong/tools"

View File

@@ -2,118 +2,121 @@ package requests
import (
"bufio"
"container/list"
"context"
"crypto/tls"
"fmt"
"log"
"net"
"net/http"
"net/url"
"sync"
"time"
"sync/atomic"
"net/http"
h2ja3 "gitee.com/baixudong/http2"
"golang.org/x/net/http2"
utls "github.com/refraction-networking/utls"
)
type Connector struct {
element *list.Element
h2 bool
r *bufio.Reader
conn net.Conn
type roundTripper interface {
RoundTrip(*http.Request) (*http.Response, error)
}
type connecotr struct {
conn net.Conn
cnl context.CancelFunc
ctx context.Context
h2 bool
r *bufio.Reader
t2 *http2.Transport
t22 *h2ja3.Upg
c2 roundTripper
}
func (obj *connecotr) run() {
defer obj.Close()
con := make([]byte, 0)
t := time.NewTimer(0)
defer t.Stop()
for {
_, err := obj.conn.Read(con)
if err != nil {
return
type reqTask struct {
ctx context.Context //控制请求的生命周期
cnl context.CancelFunc
req *http.Request //发送的请求
res *http.Response //接收的请求
err error
}
type connPool struct {
ctx context.Context
cnl context.CancelFunc
key string
total atomic.Int64
tasks chan *reqTask
rt *RoundTripper
}
func (obj *connPool) rwMain(conn *connecotr) {
defer func() {
if obj.total.Load() == 0 {
obj.rt.delConnPool(obj.key)
}
t.Reset(time.Second * 5)
}()
defer obj.total.Add(-1)
if conn.h2 {
obj.h2Main(conn)
} else {
obj.h1Main(conn)
}
}
func (obj *connPool) h1Main(conn *connecotr) {
for {
select {
case task := <-obj.tasks:
http1Req(conn, task)
case <-obj.ctx.Done():
return
}
}
}
func (obj *connPool) h2Main(conn *connecotr) {
for {
select {
case task := <-obj.tasks:
http2Req(conn, task)
case <-obj.ctx.Done():
return
case <-t.C:
}
}
}
func (obj *connecotr) Close() error {
obj.cnl()
return obj.conn.Close()
}
func (obj *connecotr) Read(b []byte) (n int, err error) {
obj.conn.SetDeadline(time.Now().Add(time.Second * 60 * 5))
return obj.conn.Read(b)
}
func (obj *connecotr) Write(b []byte) (n int, err error) {
obj.conn.SetDeadline(time.Now().Add(time.Second * 60 * 5))
return obj.conn.Write(b)
}
type conns struct {
conns *list.List
connsLock sync.Mutex
}
type RoundTripper struct {
conns map[string]*conns
ctx context.Context
cnl context.CancelFunc
connPools map[string]*connPool
connsLock sync.Mutex
dialer *DialClient
t2 *http2.Transport
t22 *h2ja3.Upg
}
func NewRoundTripper(dialClient *DialClient) *RoundTripper {
func NewRoundTripper(preCtx context.Context, dialClient *DialClient, t22 *h2ja3.Upg, option ClientOption) *RoundTripper {
if preCtx == nil {
preCtx = context.TODO()
}
ctx, cnl := context.WithCancel(preCtx)
t2 := http2.Transport{
DialTLSContext: dialClient.requestHttp2DialTlsContext,
TLSClientConfig: dialClient.TlsConfig(),
ReadIdleTimeout: option.ResponseHeaderTimeout,
PingTimeout: option.TLSHandshakeTimeout,
WriteByteTimeout: option.IdleConnTimeout,
}
return &RoundTripper{
conns: make(map[string]*conns),
dialer: dialClient,
t2: &t2,
t22: t22,
ctx: ctx,
cnl: cnl,
connPools: make(map[string]*connPool),
dialer: dialClient,
}
}
func (obj *Connector) RoundTrip(req *http.Request) (*http.Response, error) {
err := req.Write(obj.conn)
if err != nil {
return nil, err
}
n, err := obj.conn.Read(make([]byte, 0))
log.Print("read end")
log.Print(n, err)
resp, err := http.ReadResponse(bufio.NewReader(obj.conn), req)
return resp, err
}
func (obj *conns) getConn() *Connector {
obj.connsLock.Lock()
defer obj.connsLock.Unlock()
front := obj.conns.Front()
if front == nil {
return nil
}
conn := obj.conns.Remove(front).(*Connector)
conn.element = nil
return conn
}
func (obj *conns) putConn(conn *Connector) {
obj.connsLock.Lock()
defer obj.connsLock.Unlock()
element := obj.conns.PushBack(conn)
conn.element = element
}
func (obj *conns) newConn(req *http.Request) *Connector {
return nil
}
func (obj *RoundTripper) getAddr(uurl *url.URL) string {
func getAddr(uurl *url.URL) string {
if uurl == nil {
return ""
}
@@ -128,7 +131,7 @@ func (obj *RoundTripper) getAddr(uurl *url.URL) string {
}
return uurl.Host
}
func (obj *RoundTripper) getHost(req *http.Request) string {
func getHost(req *http.Request) string {
host := req.Host
if host == "" {
host = req.URL.Host
@@ -144,20 +147,42 @@ func (obj *RoundTripper) getHost(req *http.Request) string {
}
return host
}
func (obj *RoundTripper) getKey(req *http.Request) string {
func getKey(req *http.Request) string {
ctxData := req.Context().Value(keyPrincipalID).(*reqCtxData)
return fmt.Sprintf("%s@%s", obj.getAddr(ctxData.proxy), obj.getAddr(req.URL))
return fmt.Sprintf("%s@%s", getAddr(ctxData.proxy), getAddr(req.URL))
}
func (obj *RoundTripper) getConn(key string) *Connector {
func (obj *RoundTripper) newConnPool(key string, conn *connecotr) *connPool {
pool := new(connPool)
pool.ctx, pool.cnl = context.WithCancel(obj.ctx)
pool.total.Add(1)
pool.tasks = make(chan *reqTask)
pool.rt = obj
pool.key = key
go pool.rwMain(conn)
return pool
}
func (obj *RoundTripper) delConnPool(key string) {
obj.connsLock.Lock()
defer obj.connsLock.Unlock()
conns, ok := obj.conns[key]
if ok {
return conns.getConn()
}
return nil
delete(obj.connPools, key)
}
func (obj *RoundTripper) newConn(req *http.Request) (connector *Connector, err error) {
func (obj *RoundTripper) getConnPool(key string) *connPool {
obj.connsLock.Lock()
defer obj.connsLock.Unlock()
return obj.connPools[key]
}
func (obj *RoundTripper) putConnPool(key string, conn *connecotr) {
obj.connsLock.Lock()
defer obj.connsLock.Unlock()
pool, ok := obj.connPools[key]
if ok {
pool.rwMain(conn)
} else {
obj.connPools[key] = obj.newConnPool(key, conn)
}
}
func (obj *RoundTripper) dial(key string, req *http.Request) (conn *connecotr, err error) {
ctxData := req.Context().Value(keyPrincipalID).(*reqCtxData)
if !ctxData.disProxy && ctxData.proxy == nil { //确定代理
if ctxData.proxy, err = obj.dialer.GetProxy(req.Context(), req.URL); err != nil {
@@ -165,8 +190,8 @@ func (obj *RoundTripper) newConn(req *http.Request) (connector *Connector, err e
}
}
var netConn net.Conn
host := obj.getHost(req)
addr := obj.getAddr(req.URL)
host := getHost(req)
addr := getAddr(req.URL)
if ctxData.proxy == nil {
netConn, err = obj.dialer.DialContext(req.Context(), "tcp", addr)
} else {
@@ -175,7 +200,8 @@ func (obj *RoundTripper) newConn(req *http.Request) (connector *Connector, err e
if err != nil {
return nil, err
}
connector = new(Connector)
conne := new(connecotr)
var h2 bool
if req.URL.Scheme == "https" {
ctx, cnl := context.WithTimeout(req.Context(), obj.dialer.tlsHandshakeTimeout)
defer cnl()
@@ -186,28 +212,84 @@ func (obj *RoundTripper) newConn(req *http.Request) (connector *Connector, err e
if tlsConn, ok := netConn.(interface {
ConnectionState() utls.ConnectionState
}); ok {
connector.h2 = tlsConn.ConnectionState().NegotiatedProtocol == "h2"
h2 = tlsConn.ConnectionState().NegotiatedProtocol == "h2"
} else if tlsConn, ok := netConn.(interface {
ConnectionState() tls.ConnectionState
}); ok {
connector.h2 = tlsConn.ConnectionState().NegotiatedProtocol == "h2"
h2 = tlsConn.ConnectionState().NegotiatedProtocol == "h2"
}
}
connector.conn = netConn
return connector, nil
conne.conn = netConn
if h2 {
conne.h2 = h2
conne.t2 = obj.t2
conne.t22 = obj.t22
if conne.t22 != nil {
if conne.c2, err = conne.t22.ClientConn(netConn); err != nil {
return conne, err
}
} else {
if conne.c2, err = conne.t2.NewClientConn(netConn); err != nil {
return conne, err
}
}
} else {
conne.r = bufio.NewReader(netConn)
}
return conne, err
}
func (obj *RoundTripper) RoundTrip(req *http.Request) (resp *http.Response, err error) {
key := obj.getKey(req)
conn := obj.getConn(key)
if conn == nil {
if conn, err = obj.newConn(req); err != nil {
return nil, err
func http1Req(conn *connecotr, task *reqTask) {
log.Print("===============222")
log.Print(task, conn)
defer task.cnl()
err := task.req.Write(conn.conn)
log.Print("===============555", err)
if err != nil {
task.err = err
} else {
log.Print("===============666", conn.r)
task.res, task.err = http.ReadResponse(conn.r, task.req)
log.Print(task, err)
}
}
func http2Req(conn *connecotr, task *reqTask) {
log.Print("===============444")
log.Print(conn)
log.Print(task, conn)
log.Print("===============3")
defer task.cnl()
task.res, task.err = conn.c2.RoundTrip(task.req)
}
func (obj *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
key := getKey(req)
pool := obj.getConnPool(key)
ctx, cnl := context.WithCancel(req.Context())
defer cnl()
task := &reqTask{
ctx: ctx,
cnl: cnl,
req: req,
}
if pool != nil {
select {
case <-ctx.Done():
return nil, ctx.Err()
case pool.tasks <- task:
return task.res, task.err
default:
}
}
return conn.RoundTrip(req)
// // 2. 执行请求
// // 3. 返回连接
// obj.putConn(conn)
// return resp, err
conn, err := obj.dial(key, req)
if err != nil {
return nil, err
}
if !conn.h2 {
http1Req(conn, task)
} else {
http2Req(conn, task)
}
if task.err == nil && task.res != nil {
obj.putConnPool(key, conn)
}
return task.res, task.err
}