{ "openapi": "3.0.0", "info": { "title": "Proxy Service API", "version": "1.0.0", "description": "API для редиректа коротких ссылок на оригинальные URL", "contact": { "name": "API Support" }, "license": { "name": "MIT" } }, "servers": [ { "url": "http://localhost:3020", "description": "Development server" }, { "url": "https://api.example.com", "description": "Production server" } ], "tags": [ { "name": "Redirect", "description": "Операции для редиректа коротких ссылок" }, { "name": "Health", "description": "Health check endpoints" } ], "components": { "schemas": { "Error": { "type": "object", "properties": { "code": { "type": "string", "description": "Код ошибки", "example": "LINK_NOT_FOUND" }, "message": { "type": "string", "description": "Сообщение об ошибке", "example": "Link with hash 'abc123' not found" } }, "required": [ "code", "message" ] }, "ValidationError": { "type": "object", "properties": { "code": { "type": "string", "description": "Код ошибки валидации", "example": "VALIDATION_ERROR" }, "message": { "type": "string", "description": "Сообщение об ошибке валидации", "example": "Invalid hash format" }, "field": { "type": "string", "description": "Поле с ошибкой", "example": "hash" }, "details": { "type": "object", "description": "Дополнительные детали ошибки" } }, "required": [ "code", "message" ] } }, "responses": { "NotFound": { "description": "Ресурс не найден", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "BadRequest": { "description": "Невалидный запрос", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ValidationError" } } } }, "TooManyRequests": { "description": "Превышен лимит запросов (обрабатывается на уровне ingress/istio)", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "example": "Too many requests" } } } } } }, "InternalServerError": { "description": "Внутренняя ошибка сервера", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "paths": { "/s/{hash}": { "get": { "summary": "Редирект на оригинальный URL по короткой ссылке", "description": "Выполняет редирект (301) на оригинальный URL по хешу короткой ссылки.\nСтатистика редиректов собирается автоматически через eBPF.\n", "tags": [ "Redirect" ], "parameters": [ { "in": "path", "name": "hash", "required": true, "schema": { "type": "string", "pattern": "^[a-zA-Z0-9]+$", "minLength": 1, "maxLength": 100 }, "description": "Хеш короткой ссылки", "example": "abc123" } ], "responses": { "301": { "description": "Успешный редирект на оригинальный URL", "headers": { "Location": { "description": "URL для редиректа", "schema": { "type": "string", "example": "https://example.com" } } } }, "400": { "$ref": "#/components/responses/BadRequest", "description": "Невалидный формат хеша" }, "404": { "$ref": "#/components/responses/NotFound", "description": "Ссылка с указанным хешем не найдена" }, "429": { "$ref": "#/components/responses/TooManyRequests", "description": "Превышен лимит запросов (100 запросов за 15 минут)" }, "500": { "$ref": "#/components/responses/InternalServerError", "description": "Внутренняя ошибка сервера" } } } }, "/ready": { "get": { "summary": "Health check endpoint для Kubernetes", "description": "Проверка готовности сервиса для Kubernetes readiness/liveness probes.\nВозвращает 200 OK если сервис готов к обработке запросов.\n", "tags": [ "Health" ], "responses": { "200": { "description": "Сервис готов к работе", "content": { "text/plain": { "schema": { "type": "string", "example": "OK" } } } }, "503": { "description": "Сервис не готов (например, при graceful shutdown)", "content": { "text/plain": { "schema": { "type": "string", "example": "Service Unavailable" } } } } } } } } }