- /swagger — Swagger UI (CDN, без pip-зависимостей) - /api/v1/svc/openapi.json — динамическая OpenAPI 3.1.0 спека - Nubes-брендированный topbar (лого + версия) - Bearer-токен предзаполняется автоматически - 17 эндпоинтов с полными схемами, примерами, описаниями - Ссылка «Swagger» на главной странице
143 lines
5.4 KiB
HTML
143 lines
5.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Polygon API — Swagger</title>
|
|
<link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='favicon.svg') }}">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css">
|
|
<style>
|
|
html { box-sizing: border-box; overflow-y: scroll; }
|
|
*, *:before, *:after { box-sizing: inherit; }
|
|
body {
|
|
margin: 0;
|
|
background: #fafafa;
|
|
}
|
|
/* Nubes-брендированный topbar */
|
|
.swagger-ui .topbar {
|
|
background: #fff;
|
|
border-bottom: 4px solid #2563eb;
|
|
padding: 10px 0;
|
|
}
|
|
.swagger-ui .topbar .wrapper {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
max-width: 1460px;
|
|
margin: 0 auto;
|
|
padding: 0 16px;
|
|
}
|
|
.swagger-ui .topbar a {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.swagger-ui .topbar img.logo {
|
|
height: 28px;
|
|
width: auto;
|
|
}
|
|
.swagger-ui .topbar .version-badge {
|
|
background: #2563eb;
|
|
color: #fff;
|
|
padding: 2px 10px;
|
|
border-radius: 100px;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
font-family: system-ui, sans-serif;
|
|
}
|
|
.swagger-ui .topbar .nav-link {
|
|
color: #6b7280;
|
|
font-size: 13px;
|
|
text-decoration: none;
|
|
font-family: system-ui, sans-serif;
|
|
margin-left: auto;
|
|
}
|
|
.swagger-ui .topbar .nav-link:hover {
|
|
color: #2563eb;
|
|
}
|
|
/* Скрываем лого Swagger по умолчанию (заменяем своим) */
|
|
.swagger-ui .topbar .link img[alt="Swagger UI"] {
|
|
display: none;
|
|
}
|
|
/* Инфо-блок в description */
|
|
.swagger-ui .markdown p {
|
|
font-size: 14px;
|
|
}
|
|
.swagger-ui .info .title {
|
|
font-family: system-ui, -apple-system, sans-serif;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="swagger-ui"></div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js" crossorigin></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-standalone-preset.js" crossorigin></script>
|
|
|
|
<script>
|
|
window.onload = function () {
|
|
const ui = SwaggerUIBundle({
|
|
url: "{{ openapi_url }}",
|
|
dom_id: "#swagger-ui",
|
|
deepLinking: true,
|
|
presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
|
|
plugins: [SwaggerUIBundle.plugins.DownloadUrl],
|
|
layout: "StandaloneLayout",
|
|
defaultModelsExpandDepth: 1,
|
|
defaultModelExpandDepth: 2,
|
|
docExpansion: "list",
|
|
filter: true,
|
|
showExtensions: true,
|
|
showCommonExtensions: true,
|
|
// Предзаполняем токен
|
|
onComplete: function () {
|
|
// Предзаполнить Bearer токен
|
|
const authToken = "{{ auth_token }}";
|
|
if (authToken) {
|
|
// Swagger UI хранит авторизацию в localStorage
|
|
try {
|
|
const key = "swagger_auth_bearerAuth_" + encodeURIComponent(window.location.origin);
|
|
const auth = JSON.parse(localStorage.getItem(key) || "{}");
|
|
auth.value = "Bearer " + authToken;
|
|
localStorage.setItem(key, JSON.stringify(auth));
|
|
ui.preauthorizeApiKey("bearerAuth", authToken);
|
|
} catch (e) { /* ignore */ }
|
|
}
|
|
},
|
|
requestInterceptor: function (req) {
|
|
// Добавляем заголовок Authorization если Swagger UI его не добавил
|
|
if (!req.headers.Authorization && "{{ auth_token }}") {
|
|
req.headers.Authorization = "Bearer {{ auth_token }}";
|
|
}
|
|
return req;
|
|
},
|
|
});
|
|
|
|
// Кастомный topbar с лого Nubes
|
|
const observer = new MutationObserver(function () {
|
|
const topbar = document.querySelector(".swagger-ui .topbar .wrapper");
|
|
if (topbar) {
|
|
observer.disconnect();
|
|
// Заменяем содержимое ссылки на свой логотип
|
|
const link = topbar.querySelector("a");
|
|
if (link) {
|
|
link.innerHTML = '<img class="logo" src="{{ url_for("static", filename="logo.svg") }}" alt="Nubes">' +
|
|
'<span class="version-badge">polygon v{{ version }}</span>';
|
|
link.href = "/";
|
|
}
|
|
// Добавляем ссылку «← На главную»
|
|
const navLink = document.createElement("a");
|
|
navLink.className = "nav-link";
|
|
navLink.href = "/";
|
|
navLink.textContent = "← На главную";
|
|
topbar.appendChild(navLink);
|
|
}
|
|
});
|
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
};
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|