http.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package option
  2. import (
  3. "reflect"
  4. "github.com/sagernet/sing/common/byteformats"
  5. E "github.com/sagernet/sing/common/exceptions"
  6. "github.com/sagernet/sing/common/json"
  7. "github.com/sagernet/sing/common/json/badjson"
  8. "github.com/sagernet/sing/common/json/badoption"
  9. )
  10. type HTTP2Options struct {
  11. IdleTimeout badoption.Duration `json:"idle_timeout,omitempty"`
  12. KeepAlivePeriod badoption.Duration `json:"keep_alive_period,omitempty"`
  13. StreamReceiveWindow byteformats.MemoryBytes `json:"stream_receive_window,omitempty"`
  14. ConnectionReceiveWindow byteformats.MemoryBytes `json:"connection_receive_window,omitempty"`
  15. MaxConcurrentStreams int `json:"max_concurrent_streams,omitempty"`
  16. }
  17. type QUICOptions struct {
  18. HTTP2Options
  19. InitialPacketSize int `json:"initial_packet_size,omitempty"`
  20. DisablePathMTUDiscovery bool `json:"disable_path_mtu_discovery,omitempty"`
  21. }
  22. type _HTTPClientOptions struct {
  23. Tag string `json:"tag,omitempty"`
  24. Engine string `json:"engine,omitempty"`
  25. Version int `json:"version,omitempty"`
  26. DisableVersionFallback bool `json:"disable_version_fallback,omitempty"`
  27. Headers badoption.HTTPHeader `json:"headers,omitempty"`
  28. HTTP2Options HTTP2Options `json:"-"`
  29. HTTP3Options QUICOptions `json:"-"`
  30. DefaultOutbound bool `json:"-"`
  31. ResolveOnDetour bool `json:"-"`
  32. DirectResolver bool `json:"-"`
  33. OutboundTLSOptionsContainer
  34. DialerOptions
  35. }
  36. type (
  37. HTTPClient _HTTPClientOptions
  38. HTTPClientOptions _HTTPClientOptions
  39. )
  40. func (h HTTPClient) Options() HTTPClientOptions {
  41. options := HTTPClientOptions(h)
  42. options.Tag = ""
  43. return options
  44. }
  45. func (o HTTPClientOptions) IsEmpty() bool {
  46. if o.Tag != "" {
  47. return false
  48. }
  49. o.DefaultOutbound = false
  50. o.ResolveOnDetour = false
  51. o.DirectResolver = false
  52. return reflect.ValueOf(_HTTPClientOptions(o)).IsZero()
  53. }
  54. func (o HTTPClientOptions) MarshalJSON() ([]byte, error) {
  55. if o.Tag != "" {
  56. return json.Marshal(o.Tag)
  57. }
  58. return badjson.MarshallObjects(_HTTPClientOptions(o), httpClientVariant(_HTTPClientOptions(o)))
  59. }
  60. func (o *HTTPClientOptions) UnmarshalJSON(content []byte) error {
  61. if len(content) > 0 && content[0] == '"' {
  62. *o = HTTPClientOptions{}
  63. return json.Unmarshal(content, &o.Tag)
  64. }
  65. var options _HTTPClientOptions
  66. err := json.Unmarshal(content, &options)
  67. if err != nil {
  68. return err
  69. }
  70. err = unmarshalHTTPClientVersionOptions(content, &options, &options)
  71. if err != nil {
  72. return err
  73. }
  74. options.Tag = ""
  75. *o = HTTPClientOptions(options)
  76. return nil
  77. }
  78. func (h HTTPClient) MarshalJSON() ([]byte, error) {
  79. return badjson.MarshallObjects(_HTTPClientOptions(h), httpClientVariant(_HTTPClientOptions(h)))
  80. }
  81. func (h *HTTPClient) UnmarshalJSON(content []byte) error {
  82. err := json.Unmarshal(content, (*_HTTPClientOptions)(h))
  83. if err != nil {
  84. return err
  85. }
  86. return unmarshalHTTPClientVersionOptions(content, (*_HTTPClientOptions)(h), (*_HTTPClientOptions)(h))
  87. }
  88. func unmarshalHTTPClientVersionOptions(content []byte, baseStruct any, options *_HTTPClientOptions) error {
  89. switch options.Version {
  90. case 1:
  91. return json.UnmarshalDisallowUnknownFields(content, baseStruct)
  92. case 0, 2:
  93. options.Version = 2
  94. return badjson.UnmarshallExcluded(content, baseStruct, &options.HTTP2Options)
  95. case 3:
  96. return badjson.UnmarshallExcluded(content, baseStruct, &options.HTTP3Options)
  97. default:
  98. return E.New("unknown HTTP version: ", options.Version)
  99. }
  100. }
  101. func httpClientVariant(options _HTTPClientOptions) any {
  102. switch options.Version {
  103. case 1:
  104. return nil
  105. case 0, 2:
  106. return options.HTTP2Options
  107. case 3:
  108. return options.HTTP3Options
  109. default:
  110. return nil
  111. }
  112. }