add keepalive option for http handler
This commit is contained in:
+22
-10
@@ -338,31 +338,39 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
}
|
||||
|
||||
dial := func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return cc, nil
|
||||
}
|
||||
dialTLS := func(ctx context.Context, network, address string, cfg *tls.Config) (net.Conn, error) {
|
||||
return cc, nil
|
||||
}
|
||||
sniffer := &sniffing.Sniffer{
|
||||
Recorder: h.recorder.Recorder,
|
||||
RecorderOptions: h.recorder.Options,
|
||||
RecorderObject: ro,
|
||||
Certificate: h.md.certificate,
|
||||
PrivateKey: h.md.privateKey,
|
||||
NegotiatedProtocol: h.md.alpn,
|
||||
CertPool: h.certPool,
|
||||
MitmBypass: h.md.mitmBypass,
|
||||
ReadTimeout: h.md.readTimeout,
|
||||
Log: log,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return cc, nil
|
||||
},
|
||||
DialTLS: func(ctx context.Context, network, address string, cfg *tls.Config) (net.Conn, error) {
|
||||
return cc, nil
|
||||
},
|
||||
}
|
||||
|
||||
conn = xnet.NewReadWriteConn(br, rw, conn)
|
||||
switch proto {
|
||||
case sniffing.ProtoHTTP:
|
||||
return sniffer.HandleHTTP(ctx, conn)
|
||||
return sniffer.HandleHTTP(ctx, conn,
|
||||
sniffing.WithDial(dial),
|
||||
sniffing.WithDialTLS(dialTLS),
|
||||
sniffing.WithRecorderObject(ro),
|
||||
sniffing.WithLog(log),
|
||||
)
|
||||
case sniffing.ProtoTLS:
|
||||
return sniffer.HandleTLS(ctx, conn)
|
||||
return sniffer.HandleTLS(ctx, conn,
|
||||
sniffing.WithDial(dial),
|
||||
sniffing.WithDialTLS(dialTLS),
|
||||
sniffing.WithRecorderObject(ro),
|
||||
sniffing.WithLog(log),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,6 +458,10 @@ func (h *httpHandler) proxyRoundTrip(ctx context.Context, rw io.ReadWriter, cc n
|
||||
}
|
||||
}
|
||||
|
||||
if !h.md.keepalive {
|
||||
req.Header.Set("Connection", "close")
|
||||
}
|
||||
|
||||
req.Header.Del("Proxy-Authorization")
|
||||
req.Header.Del("Proxy-Connection")
|
||||
req.Header.Del("Gost-Target")
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/go-gost/core/bypass"
|
||||
mdata "github.com/go-gost/core/metadata"
|
||||
mdutil "github.com/go-gost/core/metadata/util"
|
||||
mdutil "github.com/go-gost/x/metadata/util"
|
||||
"github.com/go-gost/x/registry"
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ const (
|
||||
|
||||
type metadata struct {
|
||||
readTimeout time.Duration
|
||||
keepalive bool
|
||||
probeResistance *probeResistance
|
||||
enableUDP bool
|
||||
header http.Header
|
||||
@@ -52,6 +53,8 @@ func (h *httpHandler) parseMetadata(md mdata.Metadata) error {
|
||||
h.md.header = hd
|
||||
}
|
||||
|
||||
h.md.keepalive = mdutil.GetBool(md, "http.keepalive", "keepalive")
|
||||
|
||||
if pr := mdutil.GetString(md, "probeResist", "probe_resist"); pr != "" {
|
||||
if ss := strings.SplitN(pr, ":", 2); len(ss) == 2 {
|
||||
h.md.probeResistance = &probeResistance{
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/go-gost/core/metadata"
|
||||
)
|
||||
|
||||
func IsExists(md metadata.Metadata, keys ...string) bool {
|
||||
for _, key := range keys {
|
||||
if md.IsExists(key) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetBool(md metadata.Metadata, keys ...string) (v bool) {
|
||||
if md == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if !md.IsExists(key) {
|
||||
continue
|
||||
}
|
||||
switch vv := md.Get(key).(type) {
|
||||
case bool:
|
||||
v = vv
|
||||
case int:
|
||||
v = vv != 0
|
||||
case string:
|
||||
v, _ = strconv.ParseBool(vv)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetInt(md metadata.Metadata, keys ...string) (v int) {
|
||||
if md == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if !md.IsExists(key) {
|
||||
continue
|
||||
}
|
||||
switch vv := md.Get(key).(type) {
|
||||
case bool:
|
||||
if vv {
|
||||
v = 1
|
||||
}
|
||||
case int:
|
||||
v = vv
|
||||
case string:
|
||||
v, _ = strconv.Atoi(vv)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetFloat(md metadata.Metadata, keys ...string) (v float64) {
|
||||
if md == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if !md.IsExists(key) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch vv := md.Get(key).(type) {
|
||||
case float64:
|
||||
v = vv
|
||||
case int:
|
||||
v = float64(vv)
|
||||
case string:
|
||||
v, _ = strconv.ParseFloat(vv, 64)
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetDuration(md metadata.Metadata, keys ...string) (v time.Duration) {
|
||||
if md == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if !md.IsExists(key) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch vv := md.Get(key).(type) {
|
||||
case int:
|
||||
v = time.Duration(vv) * time.Second
|
||||
case string:
|
||||
v, _ = time.ParseDuration(vv)
|
||||
if v == 0 {
|
||||
n, _ := strconv.Atoi(vv)
|
||||
v = time.Duration(n) * time.Second
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetString(md metadata.Metadata, keys ...string) (v string) {
|
||||
if md == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if !md.IsExists(key) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch vv := md.Get(key).(type) {
|
||||
case string:
|
||||
v = vv
|
||||
case int:
|
||||
v = strconv.FormatInt(int64(vv), 10)
|
||||
case int64:
|
||||
v = strconv.FormatInt(vv, 10)
|
||||
case uint:
|
||||
v = strconv.FormatUint(uint64(vv), 10)
|
||||
case uint64:
|
||||
v = strconv.FormatUint(uint64(vv), 10)
|
||||
case bool:
|
||||
v = strconv.FormatBool(vv)
|
||||
case float32:
|
||||
v = strconv.FormatFloat(float64(vv), 'f', -1, 32)
|
||||
case float64:
|
||||
v = strconv.FormatFloat(float64(vv), 'f', -1, 64)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetStrings(md metadata.Metadata, keys ...string) (ss []string) {
|
||||
if md == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if !md.IsExists(key) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch v := md.Get(key).(type) {
|
||||
case []string:
|
||||
ss = v
|
||||
case []any:
|
||||
for _, vv := range v {
|
||||
if s, ok := vv.(string); ok {
|
||||
ss = append(ss, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetStringMap(md metadata.Metadata, keys ...string) (m map[string]any) {
|
||||
if md == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if !md.IsExists(key) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch vv := md.Get(key).(type) {
|
||||
case map[string]any:
|
||||
m = vv
|
||||
case map[any]any:
|
||||
m = make(map[string]any)
|
||||
for k, v := range vv {
|
||||
m[fmt.Sprintf("%v", k)] = v
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetStringMapString(md metadata.Metadata, keys ...string) (m map[string]string) {
|
||||
if md == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if !md.IsExists(key) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch vv := md.Get(key).(type) {
|
||||
case map[string]any:
|
||||
m = make(map[string]string)
|
||||
for k, v := range vv {
|
||||
m[k] = fmt.Sprintf("%v", v)
|
||||
}
|
||||
case map[any]any:
|
||||
m = make(map[string]string)
|
||||
for k, v := range vv {
|
||||
m[fmt.Sprintf("%v", k)] = fmt.Sprintf("%v", v)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user