Skip to content

Commit 9179f52

Browse files
committed
fix(models): enforce string type for numeric range fields in xHTTP and xMux settings
1 parent 8508144 commit 9179f52

3 files changed

Lines changed: 43 additions & 13 deletions

File tree

app/models/host.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,19 @@ class NoiseSettings(BaseModel):
6363

6464

6565
class XMuxSettings(BaseModel):
66-
max_concurrency: str | int | None = Field(
66+
max_concurrency: str | None = Field(
6767
None, pattern=r"^\d{1,16}(-\d{1,16})?$", serialization_alias="maxConcurrency"
6868
)
69-
max_connections: str | int | None = Field(
69+
max_connections: str | None = Field(
7070
None, pattern=r"^\d{1,16}(-\d{1,16})?$", serialization_alias="maxConnections"
7171
)
72-
c_max_reuse_times: str | int | None = Field(
72+
c_max_reuse_times: str | None = Field(
7373
None, pattern=r"^\d{1,16}(-\d{1,16})?$", serialization_alias="cMaxReuseTimes"
7474
)
75-
h_max_reusable_secs: str | int | None = Field(
75+
h_max_reusable_secs: str | None = Field(
7676
None, pattern=r"^\d{1,16}(-\d{1,16})?$", serialization_alias="hMaxReusableSecs"
7777
)
78-
h_max_request_times: str | int | None = Field(
78+
h_max_request_times: str | None = Field(
7979
None, pattern=r"^\d{1,16}(-\d{1,16})?$", serialization_alias="hMaxRequestTimes"
8080
)
8181
h_keep_alive_period: int | None = Field(None, serialization_alias="hKeepAlivePeriod")
@@ -98,7 +98,7 @@ def normalize_numeric_or_range_fields(cls, value):
9898
class XHttpSettings(BaseModel):
9999
mode: XHttpModes | None = Field(default=None)
100100
no_grpc_header: bool | None = Field(default=None)
101-
x_padding_bytes: str | int | None = Field(default=None, pattern=r"^\d{1,16}(-\d{1,16})?$")
101+
x_padding_bytes: str | None = Field(default=None, pattern=r"^\d{1,16}(-\d{1,16})?$")
102102
x_padding_obfs_mode: bool | None = Field(default=None)
103103
x_padding_key: str | None = Field(default=None)
104104
x_padding_header: str | None = Field(default=None)
@@ -111,9 +111,9 @@ class XHttpSettings(BaseModel):
111111
seq_key: str | None = Field(default=None)
112112
uplink_data_placement: str | None = Field(default=None, pattern=r"^$|^(body|cookie|header)$")
113113
uplink_data_key: str | None = Field(default=None)
114-
uplink_chunk_size: str | int | None = Field(default=None, pattern=r"^\d{1,16}(-\d{1,16})?$")
115-
sc_max_each_post_bytes: str | int | None = Field(default=None, pattern=r"^\d{1,16}(-\d{1,16})?$")
116-
sc_min_posts_interval_ms: str | int | None = Field(default=None, pattern=r"^\d{1,16}(-\d{1,16})?$")
114+
uplink_chunk_size: str | None = Field(default=None, pattern=r"^\d{1,16}(-\d{1,16})?$")
115+
sc_max_each_post_bytes: str | None = Field(default=None, pattern=r"^\d{1,16}(-\d{1,16})?$")
116+
sc_min_posts_interval_ms: str | None = Field(default=None, pattern=r"^\d{1,16}(-\d{1,16})?$")
117117
xmux: XMuxSettings | None = Field(default=None)
118118
download_settings: int | None = Field(default=None)
119119

app/models/subscription.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,13 @@ class XHTTPTransportConfig(BaseTransportConfig):
9898

9999
mode: str = Field("auto")
100100
no_grpc_header: bool | None = Field(None)
101-
sc_max_each_post_bytes: str | int | None = Field(
101+
sc_max_each_post_bytes: str | None = Field(
102102
None, serialization_alias="scMaxEachPostBytes", pattern=r"^\d{1,16}(?:-\d{1,16})?$"
103103
)
104-
sc_min_posts_interval_ms: str | int | None = Field(
104+
sc_min_posts_interval_ms: str | None = Field(
105105
None, serialization_alias="scMinPostsIntervalMs", pattern=r"^\d{1,16}(?:-\d{1,16})?$"
106106
)
107-
x_padding_bytes: str | int | None = Field(
107+
x_padding_bytes: str | None = Field(
108108
None, serialization_alias="xPaddingBytes", pattern=r"^\d{1,16}(?:-\d{1,16})?$"
109109
)
110110
x_padding_obfs_mode: bool | None = Field(None, serialization_alias="xPaddingObfsMode")
@@ -119,7 +119,7 @@ class XHTTPTransportConfig(BaseTransportConfig):
119119
seq_key: str | None = Field(None, serialization_alias="seqKey")
120120
uplink_data_placement: str | None = Field(None, serialization_alias="uplinkDataPlacement")
121121
uplink_data_key: str | None = Field(None, serialization_alias="uplinkDataKey")
122-
uplink_chunk_size: str | int | None = Field(
122+
uplink_chunk_size: str | None = Field(
123123
None, serialization_alias="uplinkChunkSize", pattern=r"^\d{1,16}(?:-\d{1,16})?$"
124124
)
125125
xmux: dict[str, Any] | None = Field(None)

tests/test_subscription_clash_xhttp.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from app.core.xray import XRayConfig
2+
from app.models.host import XHttpSettings, XMuxSettings
23
from app.models.subscription import SubscriptionInboundData, TLSConfig, XHTTPTransportConfig
34
from app.subscription.clash import ClashConfiguration, ClashMetaConfiguration
45

@@ -250,6 +251,35 @@ def test_xray_parser_reads_xhttp_extra_advanced_fields():
250251
assert inbound["download_settings"] == {"address": "download.example.com"}
251252

252253

254+
def test_xhttp_models_accept_integer_numeric_range_fields_as_strings():
255+
transport = XHTTPTransportConfig(
256+
sc_max_each_post_bytes=4096,
257+
sc_min_posts_interval_ms=30,
258+
x_padding_bytes=128,
259+
uplink_chunk_size=2048,
260+
)
261+
262+
assert transport.sc_max_each_post_bytes == "4096"
263+
assert transport.sc_min_posts_interval_ms == "30"
264+
assert transport.x_padding_bytes == "128"
265+
assert transport.uplink_chunk_size == "2048"
266+
267+
host_settings = XHttpSettings(
268+
sc_max_each_post_bytes=4096,
269+
sc_min_posts_interval_ms=30,
270+
x_padding_bytes=128,
271+
uplink_chunk_size=2048,
272+
xmux=XMuxSettings(max_concurrency=4, max_connections=8),
273+
)
274+
275+
assert host_settings.sc_max_each_post_bytes == "4096"
276+
assert host_settings.sc_min_posts_interval_ms == "30"
277+
assert host_settings.x_padding_bytes == "128"
278+
assert host_settings.uplink_chunk_size == "2048"
279+
assert host_settings.xmux.max_concurrency == "4"
280+
assert host_settings.xmux.max_connections == "8"
281+
282+
253283
def test_xray_parser_does_not_mix_top_level_advanced_fields_when_extra_exists():
254284
parsed = XRayConfig(
255285
{

0 commit comments

Comments
 (0)