Добавлен Swagger #20

This commit is contained in:
2026-05-09 18:15:45 +03:00
parent a34e36b966
commit a35d6f7acc
9 changed files with 419 additions and 51 deletions

View File

@@ -0,0 +1,96 @@
-module(swagger_docs_handler).
-behaviour(cowboy_handler).
-export([init/2]).
init(Req, _Opts) ->
Path = cowboy_req:path(Req),
handle(Path, Req).
handle(<<"/">>, Req) ->
serve_index(Req);
handle(<<"/admin">>, Req) ->
redirect_to_slash(<<"/admin/">>, Req);
handle(<<"/admin/">>, Req) ->
serve_ui(admin, Req);
handle(<<"/admin/swagger.json">>, Req) ->
serve_json(admin, Req);
handle(<<"/client">>, Req) ->
redirect_to_slash(<<"/client/">>, Req);
handle(<<"/client/">>, Req) ->
serve_ui(client, Req);
handle(<<"/client/swagger.json">>, Req) ->
serve_json(client, Req);
handle(_, Req) ->
cowboy_req:reply(404, #{}, <<"Not Found">>, Req),
{ok, [], []}.
%% Главная страница с выбором API
serve_index(Req) ->
Html = <<"<!DOCTYPE html>
<html>
<head><title>EventHub API Docs</title></head>
<body>
<h1>EventHub API Documentation</h1>
<ul>
<li><a href=\"/admin/\">Admin API</a></li>
<li><a href=\"/client/\">Client API</a></li>
</ul>
</body>
</html>">>,
cowboy_req:reply(200, #{<<"content-type">> => <<"text/html">>}, Html, Req),
{ok, Html, []}.
%% Swagger UI для конкретного API
serve_ui(Api, Req) ->
{Title, SpecUrl} = case Api of
admin -> {<<"EventHub Admin API">>, <<"/admin/swagger.json">>};
client -> {<<"EventHub Client API">>, <<"/client/swagger.json">>}
end,
Html = iolist_to_binary([
"<!DOCTYPE html><html><head><title>", Title,
"</title><link rel=\"stylesheet\" href=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui.css\">",
"</head><body><div id=\"swagger-ui\"></div>",
"<script src=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js\"></script>",
"<script>window.onload=function(){SwaggerUIBundle({url:'", SpecUrl,
"',dom_id:'#swagger-ui',presets:[SwaggerUIBundle.presets.apis,SwaggerUIBundle.SwaggerUIStandalonePreset],layout:'BaseLayout'});}</script>",
"</body></html>"
]),
cowboy_req:reply(200, #{<<"content-type">> => <<"text/html">>}, Html, Req),
{ok, Html, []}.
%% Генерация OpenAPI JSON
serve_json(Api, Req) ->
Trails = case Api of
admin -> trails:admin();
client -> trails:client()
end,
OpenApi = #{
openapi => <<"3.0.3">>,
info => #{
title => case Api of
admin -> <<"EventHub Admin API">>;
client -> <<"EventHub Client API">>
end,
version => <<"1.0.0">>
},
servers => [#{url => <<"http://localhost:8445">>, description => <<"API server">>}],
paths => build_paths(Trails)
},
Json = jsx:encode(OpenApi),
cowboy_req:reply(200, #{<<"content-type">> => <<"application/json">>}, Json, Req),
{ok, Json, []}.
build_paths(Trails) ->
lists:foldl(fun(Trail, Acc) ->
Path = maps:get(path, Trail, <<"/">>),
Method0 = maps:get(method, Trail, <<"get">>),
Method = string:lowercase(Method0),
TrailData = maps:without([path, method], Trail),
PathItem = #{Method => TrailData},
maps:merge_with(fun(_, V1, V2) -> maps:merge(V1, V2) end, Acc, #{Path => PathItem})
end, #{}, Trails).
redirect_to_slash(Location, Req) ->
cowboy_req:reply(301, #{<<"location">> => Location}, <<>>, Req),
{ok, [], []}.