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{})
|
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{
|
sniffer := &sniffing.Sniffer{
|
||||||
Recorder: h.recorder.Recorder,
|
Recorder: h.recorder.Recorder,
|
||||||
RecorderOptions: h.recorder.Options,
|
RecorderOptions: h.recorder.Options,
|
||||||
RecorderObject: ro,
|
|
||||||
Certificate: h.md.certificate,
|
Certificate: h.md.certificate,
|
||||||
PrivateKey: h.md.privateKey,
|
PrivateKey: h.md.privateKey,
|
||||||
NegotiatedProtocol: h.md.alpn,
|
NegotiatedProtocol: h.md.alpn,
|
||||||
CertPool: h.certPool,
|
CertPool: h.certPool,
|
||||||
MitmBypass: h.md.mitmBypass,
|
MitmBypass: h.md.mitmBypass,
|
||||||
ReadTimeout: h.md.readTimeout,
|
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)
|
conn = xnet.NewReadWriteConn(br, rw, conn)
|
||||||
switch proto {
|
switch proto {
|
||||||
case sniffing.ProtoHTTP:
|
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:
|
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-Authorization")
|
||||||
req.Header.Del("Proxy-Connection")
|
req.Header.Del("Proxy-Connection")
|
||||||
req.Header.Del("Gost-Target")
|
req.Header.Del("Gost-Target")
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/go-gost/core/bypass"
|
"github.com/go-gost/core/bypass"
|
||||||
mdata "github.com/go-gost/core/metadata"
|
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"
|
"github.com/go-gost/x/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ const (
|
|||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
readTimeout time.Duration
|
readTimeout time.Duration
|
||||||
|
keepalive bool
|
||||||
probeResistance *probeResistance
|
probeResistance *probeResistance
|
||||||
enableUDP bool
|
enableUDP bool
|
||||||
header http.Header
|
header http.Header
|
||||||
@@ -52,6 +53,8 @@ func (h *httpHandler) parseMetadata(md mdata.Metadata) error {
|
|||||||
h.md.header = hd
|
h.md.header = hd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.md.keepalive = mdutil.GetBool(md, "http.keepalive", "keepalive")
|
||||||
|
|
||||||
if pr := mdutil.GetString(md, "probeResist", "probe_resist"); pr != "" {
|
if pr := mdutil.GetString(md, "probeResist", "probe_resist"); pr != "" {
|
||||||
if ss := strings.SplitN(pr, ":", 2); len(ss) == 2 {
|
if ss := strings.SplitN(pr, ":", 2); len(ss) == 2 {
|
||||||
h.md.probeResistance = &probeResistance{
|
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