Repository navigation
Expand file tree
/
Copy pathapp.py
More file actions
201 lines (176 loc) · 8.36 KB
/
Copy pathapp.py
File metadata and controls
201 lines (176 loc) · 8.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import logging
import os
from typing import Optional
from flask import Flask
from flask_wtf.csrf import CSRFProtect
from werkzeug.middleware.proxy_fix import ProxyFix
from config import Config, DevelopmentConfig, ProductionConfig
from env_loader import load_runtime_env
from error_handlers import init_error_handlers
from middleware.external_origin import TrustedExternalOriginMiddleware
from middleware.lean_path import LeanPathMiddleware
from route_helpers import (
api_auth_required,
apply_cors_headers,
build_cors_preflight_response,
check_provider,
is_api_request_path,
login_required,
)
from routes.config_snapshots import register_config_snapshot_routes
from routes.enterprise_preview import register_enterprise_preview_routes
from routes.tenants import register_tenant_routes
from routes.core import register_core_routes
from routes.dashboard_security import register_dashboard_security_routes
from routes.intelligence_media import register_intelligence_media_routes
from routes.knowledge import register_knowledge_routes
from routes.documentation import register_documentation_routes
from routes.free_routes import register_free_routes
from routes.gateway_mcp import register_gateway_mcp_routes
from routes.gateway_batches import register_gateway_batch_routes
from routes.context_pages import register_context_page_routes
from routes.lean import register_lean_routes
from routes.optimized import register_optimized_routes
from routes.proxy import register_proxy_routes
from routes.status_page import register_status_routes
from routes.unified import register_unified_routes
from routes.media import register_media_routes
from routes.moderations import register_moderation_routes
from routes.safety import register_safety_routes
from routes.usage import register_usage_routes
from routes.usage_receipts import register_usage_receipt_routes
from routes.workbench import register_workbench_routes
from security_config import load_max_content_length, validate_runtime_secrets
from services.auth_service import AuthService
from services.cache_service import CacheService
from services.image_relay_catalog import ImageRelayCatalogRefresh
from services.provider_catalog_refresh import ProviderCatalogAutoRefresh
from services.gateway_extensions import gateway_callbacks, register_gateway_extensions, register_enterprise_features
from services.metrics_service import MetricsService
from services.proxy_service import ProxyService
from services import usage_ledger
from services.secret_firewall import init_secret_firewall
from services.shadow_eval_sampling import init_shadow_sampling
from routes.shadow_eval import register_shadow_eval_routes
_LOG_FORMAT = "%(asctime)s - %(levelname)s - [%(name)s] %(message)s"
_LOG_LEVELS = {
"DEBUG": logging.DEBUG,
"INFO": logging.INFO,
"WARNING": logging.WARNING,
"ERROR": logging.ERROR,
"CRITICAL": logging.CRITICAL,
}
def _env_flag(name: str) -> bool:
return os.environ.get(name, "").strip().lower() in {"1", "true", "yes", "on"}
def _configure_logging(level_name: Optional[str] = None) -> int:
"""Configure application logging without replacing server-owned handlers."""
normalized_level = (level_name or "").strip().upper()
level = _LOG_LEVELS.get(normalized_level, logging.INFO)
root_logger = logging.getLogger()
if not root_logger.handlers:
logging.basicConfig(level=level, format=_LOG_FORMAT)
root_logger.setLevel(level)
# urllib3 DEBUG logs can contain complete upstream request targets.
logging.getLogger("urllib3").setLevel(max(level, logging.WARNING))
return level
_configure_logging()
logger = logging.getLogger(__name__)
def create_app() -> Flask:
"""
Create and configure the Flask application.
"""
load_runtime_env()
_configure_logging(os.environ.get("LOG_LEVEL"))
runtime_secrets = validate_runtime_secrets()
app = Flask(
__name__,
static_url_path="/static",
template_folder="templates",
)
if _env_flag("MULTILLM_TRUST_PROXY_HEADERS"):
# The Worker overwrites both standard forwarding headers and its
# private origin header. The latter survives Container runtime header
# normalization and wins when Flask constructs public URLs.
app.wsgi_app = TrustedExternalOriginMiddleware(app.wsgi_app)
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
if os.environ.get("LEAN_ENDPOINT_ENABLED", "").strip().lower() not in {"0", "false", "no", "off"}:
app.wsgi_app = LeanPathMiddleware(app.wsgi_app)
app.secret_key = runtime_secrets["FLASK_SECRET_KEY"]
app.config["JWT_SECRET"] = runtime_secrets["JWT_SECRET"]
csrf = CSRFProtect()
csrf.init_app(app)
for directory in ["static", "templates"]:
dir_path = os.path.join(os.path.dirname(__file__), directory)
if not os.path.exists(dir_path):
os.makedirs(dir_path)
flask_env = os.environ.get("FLASK_ENV", "production")
app.config.from_object(Config)
if flask_env == "development":
app.config.from_object(DevelopmentConfig)
else:
app.config.from_object(ProductionConfig)
app.config["MAX_CONTENT_LENGTH"] = load_max_content_length()
app.config["SESSION_COOKIE_HTTPONLY"] = True
app.config["SESSION_COOKIE_SAMESITE"] = "Lax"
app.config["SESSION_COOKIE_SECURE"] = flask_env != "development"
init_error_handlers(app)
init_secret_firewall(app)
init_shadow_sampling(app)
AuthService.initialize()
app.extensions["image_relay_catalog_refresh"] = ImageRelayCatalogRefresh()
app.extensions["provider_catalog_refresh"] = ProviderCatalogAutoRefresh(
ttl_seconds=app.config["PROVIDER_CATALOG_REFRESH_SECONDS"],
cold_wait_seconds=app.config["PROVIDER_CATALOG_COLD_WAIT_SECONDS"],
)
register_proxy_routes(app, csrf, AuthService, MetricsService, ProxyService)
register_unified_routes(app, csrf, AuthService, MetricsService, ProxyService)
register_media_routes(app, csrf, AuthService, MetricsService, ProxyService)
register_moderation_routes(app, csrf, AuthService, MetricsService, ProxyService)
register_safety_routes(app, AuthService, MetricsService, ProxyService)
register_intelligence_media_routes(app, csrf, AuthService, ProxyService)
register_free_routes(app, csrf, AuthService, MetricsService, ProxyService)
register_optimized_routes(app, csrf, AuthService, MetricsService, ProxyService)
register_lean_routes(app)
register_status_routes(app, csrf, AuthService, ProxyService)
register_core_routes(app)
register_dashboard_security_routes(app)
register_workbench_routes(app)
register_config_snapshot_routes(app)
register_enterprise_preview_routes(app)
register_tenant_routes(app, csrf=csrf)
register_enterprise_features(app, csrf)
register_shadow_eval_routes(app, csrf, AuthService, MetricsService, ProxyService)
register_knowledge_routes(app, csrf)
register_gateway_mcp_routes(app, csrf)
register_documentation_routes(app, AuthService, ProxyService)
register_usage_routes(app, csrf)
register_usage_receipt_routes(app, csrf)
register_gateway_extensions(app, callbacks=gateway_callbacks(csrf=csrf))
register_gateway_batch_routes(app)
from functools import partial
from route_helpers import api_authenticate_only
from services.context_pages import ContextPageService, PrivatePageStore, managed_authority
from services.intelligence_d1_store import request_private_intelligence
app.extensions["context_page_service"] = ContextPageService(PrivatePageStore(
partial(request_private_intelligence, endpoint="context-pages")))
register_context_page_routes(app, service=app.extensions["context_page_service"],
authorize=managed_authority, authenticate=api_authenticate_only)
# Restore the dashboard's recent requests from the durable ledger in the background.
usage_ledger.start(MetricsService.get_instance())
return app
app = create_app()
if __name__ == "__main__":
try:
port = int(os.environ.get("SERVER_PORT", Config.DEFAULT_PORT))
host = os.environ.get("SERVER_HOST", "0.0.0.0")
logger.info("Starting server on %s:%s", host, port)
app.run(
host=host,
port=port,
threaded=True,
use_reloader=False,
debug=False,
)
except Exception as error:
logger.error("Server failed to start type=%s", type(error).__name__)
raise