http.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. DisableEmptyDirectCheck bool `json:"-"`
  32. ResolveOnDetour bool `json:"-"`
  33. DirectResolver bool `json:"-"`
  34. OutboundTLSOptionsContainer
  35. DialerOptions
  36. }
  37. type (
  38. HTTPClient _HTTPClientOptions
  39. HTTPClientOptions _HTTPClientOptions
  40. )
  41. func (h HTTPClient) Options() HTTPClientOptions {
  42. options := HTTPClientOptions(h)
  43. options.Tag = ""
  44. return options
  45. }
  46. func (o HTTPClientOptions) IsEmpty() bool {
  47. if o.Tag != "" {
  48. return false
  49. }
  50. o.DefaultOutbound = false
  51. o.ResolveOnDetour = false
  52. o.DirectResolver = false
  53. return reflect.ValueOf(_HTTPClientOptions(o)).IsZero()
  54. }
  55. func (o HTTPClientOptions) MarshalJSON() ([]byte, error) {
  56. if o.Tag != "" {
  57. return json.Marshal(o.Tag)
  58. }
  59. return badjson.MarshallObjects(_HTTPClientOptions(o), httpClientVariant(_HTTPClientOptions(o)))
  60. }
  61. func (o *HTTPClientOptions) UnmarshalJSON(content []byte) error {
  62. if len(content) > 0 && content[0] == '"' {
  63. *o = HTTPClientOptions{}
  64. return json.Unmarshal(content, &o.Tag)
  65. }
  66. var options _HTTPClientOptions
  67. err := json.Unmarshal(content, &options)
  68. if err != nil {
  69. return err
  70. }
  71. err = unmarshalHTTPClientVersionOptions(content, &options, &options)
  72. if err != nil {
  73. return err
  74. }
  75. options.Tag = ""
  76. *o = HTTPClientOptions(options)
  77. return nil
  78. }
  79. func (h HTTPClient) MarshalJSON() ([]byte, error) {
  80. return badjson.MarshallObjects(_HTTPClientOptions(h), httpClientVariant(_HTTPClientOptions(h)))
  81. }
  82. func (h *HTTPClient) UnmarshalJSON(content []byte) error {
  83. err := json.Unmarshal(content, (*_HTTPClientOptions)(h))
  84. if err != nil {
  85. return err
  86. }
  87. return unmarshalHTTPClientVersionOptions(content, (*_HTTPClientOptions)(h), (*_HTTPClientOptions)(h))
  88. }
  89. func unmarshalHTTPClientVersionOptions(content []byte, baseStruct any, options *_HTTPClientOptions) error {
  90. switch options.Version {
  91. case 1:
  92. return json.UnmarshalDisallowUnknownFields(content, baseStruct)
  93. case 0, 2:
  94. options.Version = 2
  95. return badjson.UnmarshallExcluded(content, baseStruct, &options.HTTP2Options)
  96. case 3:
  97. return badjson.UnmarshallExcluded(content, baseStruct, &options.HTTP3Options)
  98. default:
  99. return E.New("unknown HTTP version: ", options.Version)
  100. }
  101. }
  102. func httpClientVariant(options _HTTPClientOptions) any {
  103. switch options.Version {
  104. case 1:
  105. return nil
  106. case 0, 2:
  107. return options.HTTP2Options
  108. case 3:
  109. return options.HTTP3Options
  110. default:
  111. return nil
  112. }
  113. }