diff --git a/option/simple.go b/option/simple.go index dec1e0e0..55bfe930 100644 --- a/option/simple.go +++ b/option/simple.go @@ -27,9 +27,9 @@ type SocksOutboundOptions struct { type HTTPOutboundOptions struct { DialerOptions ServerOptions - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - TLS *OutboundTLSOptions `json:"tls,omitempty"` - Path string `json:"path,omitempty"` - Headers map[string]Listable[string] `json:"headers,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + TLS *OutboundTLSOptions `json:"tls,omitempty"` + Path string `json:"path,omitempty"` + Headers HTTPHeader `json:"headers,omitempty"` } diff --git a/option/types.go b/option/types.go index 8a5e6cfc..a357387f 100644 --- a/option/types.go +++ b/option/types.go @@ -1,6 +1,7 @@ package option import ( + "net/http" "net/netip" "strings" "time" @@ -235,3 +236,15 @@ func DNSQueryTypeToString(queryType uint16) string { } return F.ToString(queryType) } + +type HTTPHeader map[string]Listable[string] + +func (h HTTPHeader) Build() http.Header { + header := make(http.Header) + for name, values := range h { + for _, value := range values { + header.Add(name, value) + } + } + return header +} diff --git a/option/v2ray_transport.go b/option/v2ray_transport.go index b01cafa7..54b0de79 100644 --- a/option/v2ray_transport.go +++ b/option/v2ray_transport.go @@ -61,19 +61,19 @@ func (o *V2RayTransportOptions) UnmarshalJSON(bytes []byte) error { } type V2RayHTTPOptions struct { - Host Listable[string] `json:"host,omitempty"` - Path string `json:"path,omitempty"` - Method string `json:"method,omitempty"` - Headers map[string]Listable[string] `json:"headers,omitempty"` - IdleTimeout Duration `json:"idle_timeout,omitempty"` - PingTimeout Duration `json:"ping_timeout,omitempty"` + Host Listable[string] `json:"host,omitempty"` + Path string `json:"path,omitempty"` + Method string `json:"method,omitempty"` + Headers HTTPHeader `json:"headers,omitempty"` + IdleTimeout Duration `json:"idle_timeout,omitempty"` + PingTimeout Duration `json:"ping_timeout,omitempty"` } type V2RayWebsocketOptions struct { - Path string `json:"path,omitempty"` - Headers map[string]Listable[string] `json:"headers,omitempty"` - MaxEarlyData uint32 `json:"max_early_data,omitempty"` - EarlyDataHeaderName string `json:"early_data_header_name,omitempty"` + Path string `json:"path,omitempty"` + Headers HTTPHeader `json:"headers,omitempty"` + MaxEarlyData uint32 `json:"max_early_data,omitempty"` + EarlyDataHeaderName string `json:"early_data_header_name,omitempty"` } type V2RayQUICOptions struct{} diff --git a/outbound/http.go b/outbound/http.go index cd9dc959..cfc03216 100644 --- a/outbound/http.go +++ b/outbound/http.go @@ -3,7 +3,6 @@ package outbound import ( "context" "net" - "net/http" "os" "github.com/sagernet/sing-box/adapter" @@ -34,13 +33,6 @@ func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogge if err != nil { return nil, err } - var headers http.Header - if options.Headers != nil { - headers = make(http.Header) - for key, values := range options.Headers { - headers[key] = values - } - } return &HTTP{ myOutboundAdapter{ protocol: C.TypeHTTP, @@ -56,7 +48,7 @@ func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogge Username: options.Username, Password: options.Password, Path: options.Path, - Headers: headers, + Headers: options.Headers.Build(), }), }, nil } diff --git a/transport/v2rayhttp/client.go b/transport/v2rayhttp/client.go index 4d660fef..d5e8a1f6 100644 --- a/transport/v2rayhttp/client.go +++ b/transport/v2rayhttp/client.go @@ -64,7 +64,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt serverAddr: serverAddr, host: options.Host, method: options.Method, - headers: make(http.Header), + headers: options.Headers.Build(), transport: transport, http2: tlsConfig != nil, } @@ -83,9 +83,6 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt if err != nil { return nil, E.New("failed to set path: " + err.Error()) } - for key, valueList := range options.Headers { - client.headers[key] = valueList - } client.url = &uri return client, nil } diff --git a/transport/v2rayhttp/server.go b/transport/v2rayhttp/server.go index a635e8f3..dcfb07a6 100644 --- a/transport/v2rayhttp/server.go +++ b/transport/v2rayhttp/server.go @@ -55,7 +55,7 @@ func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig t host: options.Host, path: options.Path, method: options.Method, - headers: make(http.Header), + headers: options.Headers.Build(), } if server.method == "" { server.method = "PUT" @@ -63,9 +63,6 @@ func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig t if !strings.HasPrefix(server.path, "/") { server.path = "/" + server.path } - for key, value := range options.Headers { - server.headers[key] = value - } server.httpServer = &http.Server{ Handler: server, ReadHeaderTimeout: C.TCPTimeout,