Files
sing-box/option/http.go

124 lines
3.6 KiB
Go

package option
import (
"reflect"
"github.com/sagernet/sing/common/byteformats"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json"
"github.com/sagernet/sing/common/json/badjson"
"github.com/sagernet/sing/common/json/badoption"
)
type HTTP2Options struct {
IdleTimeout badoption.Duration `json:"idle_timeout,omitempty"`
KeepAlivePeriod badoption.Duration `json:"keep_alive_period,omitempty"`
StreamReceiveWindow byteformats.MemoryBytes `json:"stream_receive_window,omitempty"`
ConnectionReceiveWindow byteformats.MemoryBytes `json:"connection_receive_window,omitempty"`
MaxConcurrentStreams int `json:"max_concurrent_streams,omitempty"`
}
type QUICOptions struct {
HTTP2Options
InitialPacketSize int `json:"initial_packet_size,omitempty"`
DisablePathMTUDiscovery bool `json:"disable_path_mtu_discovery,omitempty"`
}
type _HTTPClientOptions struct {
Tag string `json:"tag,omitempty"`
Version int `json:"version,omitempty"`
DisableVersionFallback bool `json:"disable_version_fallback,omitempty"`
Headers badoption.HTTPHeader `json:"headers,omitempty"`
HTTP2Options HTTP2Options `json:"-"`
HTTP3Options QUICOptions `json:"-"`
DefaultOutbound bool `json:"-"`
ResolveOnDetour bool `json:"-"`
OutboundTLSOptionsContainer
DialerOptions
}
type (
HTTPClient _HTTPClientOptions
HTTPClientOptions _HTTPClientOptions
)
func (h HTTPClient) Options() HTTPClientOptions {
options := HTTPClientOptions(h)
options.Tag = ""
return options
}
func (o HTTPClientOptions) IsEmpty() bool {
if o.Tag != "" {
return false
}
o.DefaultOutbound = false
o.ResolveOnDetour = false
return reflect.ValueOf(_HTTPClientOptions(o)).IsZero()
}
func (o HTTPClientOptions) MarshalJSON() ([]byte, error) {
if o.Tag != "" {
return json.Marshal(o.Tag)
}
return badjson.MarshallObjects(_HTTPClientOptions(o), httpClientVariant(_HTTPClientOptions(o)))
}
func (o *HTTPClientOptions) UnmarshalJSON(content []byte) error {
if len(content) > 0 && content[0] == '"' {
*o = HTTPClientOptions{}
return json.Unmarshal(content, &o.Tag)
}
var options _HTTPClientOptions
err := json.Unmarshal(content, &options)
if err != nil {
return err
}
err = unmarshalHTTPClientVersionOptions(content, &options, &options)
if err != nil {
return err
}
options.Tag = ""
*o = HTTPClientOptions(options)
return nil
}
func (h HTTPClient) MarshalJSON() ([]byte, error) {
return badjson.MarshallObjects(_HTTPClientOptions(h), httpClientVariant(_HTTPClientOptions(h)))
}
func (h *HTTPClient) UnmarshalJSON(content []byte) error {
err := json.Unmarshal(content, (*_HTTPClientOptions)(h))
if err != nil {
return err
}
return unmarshalHTTPClientVersionOptions(content, (*_HTTPClientOptions)(h), (*_HTTPClientOptions)(h))
}
func unmarshalHTTPClientVersionOptions(content []byte, baseStruct any, options *_HTTPClientOptions) error {
switch options.Version {
case 1:
return json.UnmarshalDisallowUnknownFields(content, baseStruct)
case 0, 2:
options.Version = 2
return badjson.UnmarshallExcluded(content, baseStruct, &options.HTTP2Options)
case 3:
return badjson.UnmarshallExcluded(content, baseStruct, &options.HTTP3Options)
default:
return E.New("unknown HTTP version: ", options.Version)
}
}
func httpClientVariant(options _HTTPClientOptions) any {
switch options.Version {
case 1:
return nil
case 0, 2:
return options.HTTP2Options
case 3:
return options.HTTP3Options
default:
return nil
}
}