This commit is contained in:
riglen
2026-05-28 17:11:57 +08:00
parent 28c49ce299
commit 9bb7858d42
3 changed files with 33 additions and 2 deletions

View File

@@ -4,6 +4,10 @@ HOST=0.0.0.0
PORT=18080 PORT=18080
LOG_LEVEL=info LOG_LEVEL=info
# 上游订阅抓取时使用的 User-Agent。
# 如果机场对默认 UA 返回 406可改成你客户端实际使用的 UA例如 Clash Party 抓包得到的值。
UPSTREAM_USER_AGENT=sub-provider/0.2
# 对外访问前缀,尽量改成足够长的随机字符串 # 对外访问前缀,尽量改成足够长的随机字符串
PUBLIC_PATH=change-me-random-hash-path PUBLIC_PATH=change-me-random-hash-path

View File

@@ -74,6 +74,7 @@ cp .env.example .env
- `PUBLIC_PATH` 改成足够长的随机字符串 - `PUBLIC_PATH` 改成足够长的随机字符串
- `PUBLIC_BASE_URL` 建议填写你反代后的最终访问地址,例如 `https://sub.example.com` - `PUBLIC_BASE_URL` 建议填写你反代后的最终访问地址,例如 `https://sub.example.com`
- 如果上游订阅地址对默认 UA 返回 `406`,可在 `.env` 里设置 `UPSTREAM_USER_AGENT`,填成你客户端实际使用的 UA例如 Clash Party 抓包出来的值
- `AIRPORT_A_URL` / `AIRPORT_B_URL` / `AIRPORT_C_URL` 都可以直接填订阅地址,项目会自动判断是 YAML 还是 URI 订阅 - `AIRPORT_A_URL` / `AIRPORT_B_URL` / `AIRPORT_C_URL` 都可以直接填订阅地址,项目会自动判断是 YAML 还是 URI 订阅
- 也可以直接填本地文件路径,例如 `/app/data/sources/airport-b.txt``file:///app/data/sources/airport-b.txt` - 也可以直接填本地文件路径,例如 `/app/data/sources/airport-b.txt``file:///app/data/sources/airport-b.txt`
- 允许把其中一个留空;留空时这个机场会自动跳过 - 允许把其中一个留空;留空时这个机场会自动跳过
@@ -271,3 +272,15 @@ python scripts/compare_conf_outputs.py --sample-source C:\path\to\sample.yaml
- `sources` 填多个机场源:**只取第一个**机场源的 `Subscription-Userinfo` - `sources` 填多个机场源:**只取第一个**机场源的 `Subscription-Userinfo`
这样 Stash、Clash Party 这类客户端读取配置订阅头时,行为是稳定可预期的。 这样 Stash、Clash Party 这类客户端读取配置订阅头时,行为是稳定可预期的。
---
## 上游 `406` 处理
上游订阅抓取默认使用 `sub-provider/0.2` 作为 `User-Agent`。如果机场对这个 UA 返回 `406 Not Acceptable`,可以直接在 `.env` 里覆盖:
```env
UPSTREAM_USER_AGENT=Clash Party/<你的版本号或抓包值>
```
代码里也兼容旧变量名 `DEFAULT_USER_AGENT`,但建议后续统一用 `UPSTREAM_USER_AGENT`

View File

@@ -1,9 +1,10 @@
from __future__ import annotations from __future__ import annotations
import os
from functools import lru_cache from functools import lru_cache
from pathlib import Path from pathlib import Path
from pydantic import Field from pydantic import AliasChoices, Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict from pydantic_settings import BaseSettings, SettingsConfigDict
@@ -25,7 +26,10 @@ class Settings(BaseSettings):
cache_ttl_seconds: int = 900 cache_ttl_seconds: int = 900
bundle_cache_ttl_seconds: int = 600 bundle_cache_ttl_seconds: int = 600
max_proxy_name_length: int = 80 max_proxy_name_length: int = 80
default_user_agent: str = "sub-provider/0.2" default_user_agent: str = Field(
default="sub-provider/0.2",
validation_alias=AliasChoices("UPSTREAM_USER_AGENT", "DEFAULT_USER_AGENT"),
)
sources_file: Path = CONFIG_DIR / "sources.yaml" sources_file: Path = CONFIG_DIR / "sources.yaml"
conf_base_file: Path = CONFIG_DIR / "conf" / "base.conf" conf_base_file: Path = CONFIG_DIR / "conf" / "base.conf"
@@ -40,6 +44,16 @@ class Settings(BaseSettings):
extra="ignore", extra="ignore",
) )
@field_validator("default_user_agent", mode="before")
@classmethod
def _coalesce_default_user_agent(cls, value: str) -> str:
if isinstance(value, str) and value.strip():
return value
legacy = os.getenv("DEFAULT_USER_AGENT", "").strip()
if legacy:
return legacy
return "sub-provider/0.2"
@lru_cache(maxsize=1) @lru_cache(maxsize=1)
def get_settings() -> Settings: def get_settings() -> Settings: