Docs
This commit is contained in:
@@ -54,6 +54,8 @@ std::string GuessContentType(const std::filesystem::path& assetPath)
|
||||
return "text/css";
|
||||
if (extension == ".json")
|
||||
return "application/json";
|
||||
if (extension == ".yaml" || extension == ".yml")
|
||||
return "application/yaml";
|
||||
if (extension == ".svg")
|
||||
return "image/svg+xml";
|
||||
if (extension == ".png")
|
||||
@@ -78,9 +80,10 @@ ControlServer::~ControlServer()
|
||||
Stop();
|
||||
}
|
||||
|
||||
bool ControlServer::Start(const std::filesystem::path& uiRoot, unsigned short preferredPort, const Callbacks& callbacks, std::string& error)
|
||||
bool ControlServer::Start(const std::filesystem::path& uiRoot, const std::filesystem::path& docsRoot, unsigned short preferredPort, const Callbacks& callbacks, std::string& error)
|
||||
{
|
||||
mUiRoot = uiRoot;
|
||||
mDocsRoot = docsRoot;
|
||||
mCallbacks = callbacks;
|
||||
|
||||
if (!InitializeWinsock(error))
|
||||
@@ -246,6 +249,12 @@ ControlServer::HttpResponse ControlServer::ServeGetRequest(const HttpRequest& re
|
||||
if (request.path == "/api/state")
|
||||
return { "200 OK", "application/json", mCallbacks.getStateJson ? mCallbacks.getStateJson() : "{}" };
|
||||
|
||||
if (request.path == "/openapi.yaml" || request.path == "/docs/openapi.yaml")
|
||||
return ServeOpenApiSpec();
|
||||
|
||||
if (request.path == "/docs" || request.path == "/docs/")
|
||||
return ServeSwaggerDocs();
|
||||
|
||||
if (request.path.size() > 1)
|
||||
{
|
||||
const HttpResponse assetResponse = ServeUiAsset(request.path.substr(1));
|
||||
@@ -265,6 +274,35 @@ ControlServer::HttpResponse ControlServer::ServeUiAsset(const std::string& relat
|
||||
: HttpResponse{ "200 OK", contentType, body };
|
||||
}
|
||||
|
||||
ControlServer::HttpResponse ControlServer::ServeOpenApiSpec() const
|
||||
{
|
||||
const std::filesystem::path specPath = mDocsRoot / "openapi.yaml";
|
||||
const std::string body = LoadTextFile(specPath);
|
||||
return body.empty()
|
||||
? HttpResponse{ "404 Not Found", "text/plain", "OpenAPI spec not found" }
|
||||
: HttpResponse{ "200 OK", GuessContentType(specPath), body };
|
||||
}
|
||||
|
||||
ControlServer::HttpResponse ControlServer::ServeSwaggerDocs() const
|
||||
{
|
||||
std::ostringstream html;
|
||||
html << "<!doctype html>\n"
|
||||
<< "<html lang=\"en\">\n"
|
||||
<< "<head>\n"
|
||||
<< " <meta charset=\"utf-8\">\n"
|
||||
<< " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n"
|
||||
<< " <title>Video Shader Toys API Docs</title>\n"
|
||||
<< " <link rel=\"stylesheet\" href=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui.css\">\n"
|
||||
<< "</head>\n"
|
||||
<< "<body>\n"
|
||||
<< " <div id=\"swagger-ui\"></div>\n"
|
||||
<< " <script src=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js\"></script>\n"
|
||||
<< " <script>SwaggerUIBundle({url:'/docs/openapi.yaml',dom_id:'#swagger-ui'});</script>\n"
|
||||
<< "</body>\n"
|
||||
<< "</html>\n";
|
||||
return { "200 OK", "text/html", html.str() };
|
||||
}
|
||||
|
||||
ControlServer::HttpResponse ControlServer::HandleApiPost(const HttpRequest& request)
|
||||
{
|
||||
JsonValue root;
|
||||
@@ -449,12 +487,16 @@ std::string ControlServer::LoadUiAsset(const std::string& relativePath, std::str
|
||||
return std::string();
|
||||
|
||||
const std::filesystem::path assetPath = mUiRoot / sanitizedPath;
|
||||
std::ifstream input(assetPath, std::ios::binary);
|
||||
contentType = GuessContentType(assetPath);
|
||||
return LoadTextFile(assetPath);
|
||||
}
|
||||
|
||||
std::string ControlServer::LoadTextFile(const std::filesystem::path& path) const
|
||||
{
|
||||
std::ifstream input(path, std::ios::binary);
|
||||
if (!input)
|
||||
return std::string();
|
||||
|
||||
contentType = GuessContentType(assetPath);
|
||||
|
||||
std::ostringstream buffer;
|
||||
buffer << input.rdbuf();
|
||||
return buffer.str();
|
||||
|
||||
Reference in New Issue
Block a user