mirror of
https://github.com/umbra2728/ctfd-mcp.git
synced 2026-02-07 22:08:12 +03:00
feat: allow configurable user agent
Support overriding the default UA via configuration for stricter gateways.
This commit is contained in:
@@ -7,6 +7,9 @@ from urllib.parse import urlparse
|
|||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_USER_AGENT = "ctfd-mcp/0.1 (+https://github.com/)"
|
||||||
|
|
||||||
|
|
||||||
class ConfigError(Exception):
|
class ConfigError(Exception):
|
||||||
"""Raised when configuration is missing or invalid."""
|
"""Raised when configuration is missing or invalid."""
|
||||||
|
|
||||||
@@ -22,6 +25,7 @@ class Config:
|
|||||||
read_timeout: float | None = None
|
read_timeout: float | None = None
|
||||||
username: str | None = None
|
username: str | None = None
|
||||||
password: str | None = None
|
password: str | None = None
|
||||||
|
user_agent: str | None = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def auth_header(self) -> dict[str, str]:
|
def auth_header(self) -> dict[str, str]:
|
||||||
@@ -51,6 +55,7 @@ def load_config() -> Config:
|
|||||||
total_timeout = _parse_timeout("CTFD_TIMEOUT")
|
total_timeout = _parse_timeout("CTFD_TIMEOUT")
|
||||||
connect_timeout = _parse_timeout("CTFD_CONNECT_TIMEOUT")
|
connect_timeout = _parse_timeout("CTFD_CONNECT_TIMEOUT")
|
||||||
read_timeout = _parse_timeout("CTFD_READ_TIMEOUT")
|
read_timeout = _parse_timeout("CTFD_READ_TIMEOUT")
|
||||||
|
user_agent = os.getenv("CTFD_USER_AGENT")
|
||||||
|
|
||||||
if not base_url:
|
if not base_url:
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
@@ -75,6 +80,10 @@ def load_config() -> Config:
|
|||||||
"Set CTFD_TOKEN, CTFD_SESSION or both CTFD_USERNAME/CTFD_PASSWORD."
|
"Set CTFD_TOKEN, CTFD_SESSION or both CTFD_USERNAME/CTFD_PASSWORD."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
user_agent = user_agent.strip() if user_agent else ""
|
||||||
|
if not user_agent:
|
||||||
|
user_agent = DEFAULT_USER_AGENT
|
||||||
|
|
||||||
return Config(
|
return Config(
|
||||||
base_url.rstrip("/"),
|
base_url.rstrip("/"),
|
||||||
token.strip() if token else None,
|
token.strip() if token else None,
|
||||||
@@ -85,4 +94,5 @@ def load_config() -> Config:
|
|||||||
read_timeout=read_timeout,
|
read_timeout=read_timeout,
|
||||||
username=username.strip() if username else None,
|
username=username.strip() if username else None,
|
||||||
password=password.strip() if password else None,
|
password=password.strip() if password else None,
|
||||||
|
user_agent=user_agent,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from typing import Any
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from .config import Config
|
from .config import DEFAULT_USER_AGENT, Config
|
||||||
|
|
||||||
|
|
||||||
class CTFdClientError(Exception):
|
class CTFdClientError(Exception):
|
||||||
@@ -45,9 +45,10 @@ class CTFdClient:
|
|||||||
read=config.read_timeout if config.read_timeout is not None else 15.0,
|
read=config.read_timeout if config.read_timeout is not None else 15.0,
|
||||||
)
|
)
|
||||||
# Force h1 and send explicit Accept/UA to reduce chances of HTML/redirect responses.
|
# Force h1 and send explicit Accept/UA to reduce chances of HTML/redirect responses.
|
||||||
|
user_agent = (config.user_agent or "").strip() or DEFAULT_USER_AGENT
|
||||||
headers = {
|
headers = {
|
||||||
"Accept": "application/json",
|
"Accept": "application/json",
|
||||||
"User-Agent": "ctfd-mcp/0.1 (+https://github.com/)",
|
"User-Agent": user_agent,
|
||||||
"X-Requested-With": "XMLHttpRequest",
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
**config.auth_header,
|
**config.auth_header,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user