refactor: move some webserver-exclusive functions behind webserver gate

This commit is contained in:
Matthias
2026-01-20 06:07:42 +01:00
parent c9fd8a619a
commit b5d467c943
3 changed files with 95 additions and 74 deletions

View File

@@ -8,7 +8,6 @@ from fastapi.exceptions import HTTPException
from freqtrade import __version__
from freqtrade.data.history import get_datahandler
from freqtrade.enums import CandleType, RunMode, State, TradingMode
from freqtrade.exceptions import OperationalException
from freqtrade.rpc import RPC
from freqtrade.rpc.api_server.api_pairlists import handleExchangePayload
from freqtrade.rpc.api_server.api_schemas import (
@@ -21,14 +20,12 @@ from freqtrade.rpc.api_server.api_schemas import (
DeleteLockRequest,
DeleteTrade,
Entry,
ExchangeListResponse,
Exit,
ForceEnterPayload,
ForceEnterResponse,
ForceExitPayload,
FreqAIModelListResponse,
Health,
HyperoptLossListResponse,
ListCustomData,
Locks,
LocksPayload,
@@ -48,8 +45,6 @@ from freqtrade.rpc.api_server.api_schemas import (
ShowConfig,
Stats,
StatusMsg,
StrategyListResponse,
StrategyResponse,
SysInfo,
Version,
WhitelistResponse,
@@ -434,75 +429,6 @@ def plot_config(
raise HTTPException(status_code=502, detail=str(e))
@router.get("/strategies", response_model=StrategyListResponse, tags=["strategy"])
def list_strategies(config=Depends(get_config)):
from freqtrade.resolvers.strategy_resolver import StrategyResolver
strategies = StrategyResolver.search_all_objects(
config, False, config.get("recursive_strategy_search", False)
)
strategies = sorted(strategies, key=lambda x: x["name"])
return {"strategies": [x["name"] for x in strategies]}
@router.get("/strategy/{strategy}", response_model=StrategyResponse, tags=["strategy"])
def get_strategy(strategy: str, config=Depends(get_config)):
if ":" in strategy:
raise HTTPException(status_code=500, detail="base64 encoded strategies are not allowed.")
config_ = deepcopy(config)
from freqtrade.resolvers.strategy_resolver import StrategyResolver
try:
strategy_obj = StrategyResolver._load_strategy(
strategy, config_, extra_dir=config_.get("strategy_path")
)
except OperationalException:
raise HTTPException(status_code=404, detail="Strategy not found")
except Exception as e:
raise HTTPException(status_code=502, detail=str(e))
return {
"strategy": strategy_obj.get_strategy_name(),
"code": strategy_obj.__source__,
"timeframe": getattr(strategy_obj, "timeframe", None),
}
@router.get("/exchanges", response_model=ExchangeListResponse, tags=[])
def list_exchanges(config=Depends(get_config)):
from freqtrade.exchange import list_available_exchanges
exchanges = list_available_exchanges(config)
return {
"exchanges": exchanges,
}
@router.get(
"/hyperoptloss", response_model=HyperoptLossListResponse, tags=["hyperopt", "webserver"]
)
def list_hyperoptloss(
config=Depends(get_config),
):
import textwrap
from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver
loss_functions = HyperOptLossResolver.search_all_objects(config, False)
loss_functions = sorted(loss_functions, key=lambda x: x["name"])
return {
"loss_functions": [
{
"name": x["name"],
"description": textwrap.dedent((x["class"].__doc__ or "").strip()),
}
for x in loss_functions
]
}
@router.get("/freqaimodels", response_model=FreqAIModelListResponse, tags=["freqai"])
def list_freqaimodels(config=Depends(get_config)):
from freqtrade.resolvers.freqaimodel_resolver import FreqaiModelResolver

View File

@@ -0,0 +1,89 @@
import logging
from copy import deepcopy
from fastapi import APIRouter, Depends
from fastapi.exceptions import HTTPException
from freqtrade.exceptions import OperationalException
from freqtrade.rpc.api_server.api_schemas import (
ExchangeListResponse,
HyperoptLossListResponse,
StrategyListResponse,
StrategyResponse,
)
from freqtrade.rpc.api_server.deps import get_config
logger = logging.getLogger(__name__)
# Private API, protected by authentication and webserver_mode dependency
router = APIRouter()
@router.get("/strategies", response_model=StrategyListResponse, tags=["strategy"])
def list_strategies(config=Depends(get_config)):
from freqtrade.resolvers.strategy_resolver import StrategyResolver
strategies = StrategyResolver.search_all_objects(
config, False, config.get("recursive_strategy_search", False)
)
strategies = sorted(strategies, key=lambda x: x["name"])
return {"strategies": [x["name"] for x in strategies]}
@router.get("/strategy/{strategy}", response_model=StrategyResponse, tags=["strategy"])
def get_strategy(strategy: str, config=Depends(get_config)):
if ":" in strategy:
raise HTTPException(status_code=500, detail="base64 encoded strategies are not allowed.")
config_ = deepcopy(config)
from freqtrade.resolvers.strategy_resolver import StrategyResolver
try:
strategy_obj = StrategyResolver._load_strategy(
strategy, config_, extra_dir=config_.get("strategy_path")
)
except OperationalException:
raise HTTPException(status_code=404, detail="Strategy not found")
except Exception as e:
raise HTTPException(status_code=502, detail=str(e))
return {
"strategy": strategy_obj.get_strategy_name(),
"code": strategy_obj.__source__,
"timeframe": getattr(strategy_obj, "timeframe", None),
}
@router.get("/exchanges", response_model=ExchangeListResponse, tags=[])
def list_exchanges(config=Depends(get_config)):
from freqtrade.exchange import list_available_exchanges
exchanges = list_available_exchanges(config)
return {
"exchanges": exchanges,
}
@router.get(
"/hyperoptloss", response_model=HyperoptLossListResponse, tags=["hyperopt", "webserver"]
)
def list_hyperoptloss(
config=Depends(get_config),
):
import textwrap
from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver
loss_functions = HyperOptLossResolver.search_all_objects(config, False)
loss_functions = sorted(loss_functions, key=lambda x: x["name"])
return {
"loss_functions": [
{
"name": x["name"],
"description": textwrap.dedent((x["class"].__doc__ or "").strip()),
}
for x in loss_functions
]
}

View File

@@ -124,6 +124,7 @@ class ApiServer(RPCHandler):
from freqtrade.rpc.api_server.api_pairlists import router as api_pairlists
from freqtrade.rpc.api_server.api_v1 import router as api_v1
from freqtrade.rpc.api_server.api_v1 import router_public as api_v1_public
from freqtrade.rpc.api_server.api_webserver import router as api_webserver
from freqtrade.rpc.api_server.api_ws import router as ws_router
from freqtrade.rpc.api_server.deps import is_webserver_mode
from freqtrade.rpc.api_server.web_ui import router_ui
@@ -136,6 +137,11 @@ class ApiServer(RPCHandler):
prefix="/api/v1",
dependencies=[Depends(http_basic_or_jwt_token)],
)
app.include_router(
api_webserver,
prefix="/api/v1",
dependencies=[Depends(http_basic_or_jwt_token), Depends(is_webserver_mode)],
)
app.include_router(
api_backtest,
prefix="/api/v1",