Spaces:
Building
Building
""" | |
Flare – API Executor | |
~~~~~~~~~~~~~~~~~~~~ | |
• Placeholder yerleştirme ({{variables.x}}, {{auth_tokens.api.token}}, {{config.xxx}}) | |
• Proxy string veya ProxyConfig objesi | |
• Auth: enabled==True → token alma & cache | |
""" | |
from __future__ import annotations | |
import json | |
import re | |
import time | |
from typing import Any, Dict | |
import requests | |
from utils import log | |
from config_provider import ConfigProvider, APIConfig, ProxyConfig | |
cfg = ConfigProvider.get() | |
_token_cache: Dict[str, Dict[str, Any]] = {} # api_name → {token, expiry} | |
# ----------- Placeholder helpers ---------- | |
_placeholder_re = re.compile(r"\{\{\s*([^\}]+?)\s*\}\}") | |
def _render(obj: Any, variables: Dict[str, Any], api_name: str) -> Any: | |
def repl(match): | |
key = match.group(1) | |
if key.startswith("variables."): | |
return str(variables.get(key.split(".", 1)[1], "")) | |
if key.startswith("auth_tokens."): | |
_, api, _ = key.split(".") | |
return _token_cache.get(api, {}).get("token", "") | |
if key.startswith("config."): | |
_, prop = key.split(".", 1) | |
return str(getattr(cfg.global_config, prop, "")) | |
return match.group(0) | |
if isinstance(obj, str): | |
return _placeholder_re.sub(repl, obj) | |
if isinstance(obj, dict): | |
return {k: _render(v, variables, api_name) for k, v in obj.items()} | |
if isinstance(obj, list): | |
return [_render(v, variables, api_name) for v in obj] | |
return obj | |
# ----------- Auth helpers ----------------- | |
def _ensure_token(api: APIConfig): | |
if not api.auth or not api.auth.enabled: | |
return | |
cached = _token_cache.get(api.name) | |
if cached and cached["expiry"] > time.time(): | |
return | |
body = api.auth.token_request_body | |
body = _render(body, {}, api.name) | |
log(f"🔒 Fetching token for {api.name} …") | |
r = requests.post(api.auth.token_endpoint, json=body, timeout=api.timeout_seconds) | |
r.raise_for_status() | |
js = r.json() | |
token = js | |
for part in api.auth.response_token_path.split("."): | |
token = token[part] | |
_token_cache[api.name] = {"token": token, "expiry": time.time() + 3500} | |
# ----------- Main call -------------------- | |
def call_api(api: APIConfig, variables: Dict[str, Any]): | |
_ensure_token(api) | |
headers = _render(api.headers, variables, api.name) | |
body = _render(api.body_template, variables, api.name) | |
url = api.url | |
method = api.method.upper() | |
proxy = None | |
if api.proxy: | |
proxy = api.proxy if isinstance(api.proxy, str) else (api.proxy.url if api.proxy.enabled else None) | |
log(f"🌐 {api.name} → {method} {url}") | |
r = requests.request( | |
method, | |
url, | |
json=body if method in ("POST", "PUT", "PATCH") else None, | |
params=body if method == "GET" else None, | |
headers=headers, | |
proxies={"http": proxy, "https": proxy} if proxy else None, | |
timeout=api.timeout_seconds, | |
) | |
r.raise_for_status() | |
return r | |