add actor openapi interface swagger ui support

This commit is contained in:
timurgordon
2025-01-21 02:32:33 +00:00
parent eef88b5375
commit 135866e5b0
8 changed files with 83 additions and 11 deletions

View File

@@ -4,14 +4,33 @@ import freeflowuniverse.herolib.schemas.openrpc { OpenRPC }
import freeflowuniverse.herolib.baobab.stage.interfaces { HTTPServer, Context }
import veb
pub fn new_http_server() !&HTTPServer {
@@[params]
pub struct ServerParams {
pub:
base_url string
port int = 8080
}
pub fn new_http_server(params ServerParams) !&HTTPServer {
mut s := interfaces.new_http_server()!
mut openrpc_controller := new_openrpc_http_controller()!
@if openrpc
mut openrpc_controller := new_openrpc_http_controller(ServerParams{
...params,
base_url: '@{dollar}{params.base_url}/openrpc'
})!
s.register_controller[openrpc.HTTPController, Context]('/openrpc', mut openrpc_controller)!
@end
@if openapi
mut openapi_controller := new_openapi_http_controller(ServerParams{
...params,
base_url: '@{dollar}{params.base_url}/openapi'
})!
s.register_controller[openapi.HTTPController, Context]('/openapi', mut openapi_controller)!
@end
return s
}
pub fn run_http_server() ! {
mut server := new_http_server()!
veb.run[HTTPServer, Context](mut server, 8082)
pub fn run_http_server(params ServerParams) ! {
mut server := new_http_server(params)!
veb.run[HTTPServer, Context](mut server, params.port)
}

View File

@@ -7,11 +7,15 @@ pub fn new_openapi_interface() !&interfaces.OpenAPIInterface {
return interfaces.new_openapi_interface(client.Client)
}
@if http
// creates HTTP controller with the actor's OpenAPI Handler
// and OpenAPI Specification
pub fn new_openapi_http_controller() !&openapi.HTTPController {
pub fn new_openapi_http_controller(params ServerParams) !&openapi.HTTPController {
return openapi.new_http_controller(
base_url: params.base_url
specification: openapi_specification
specification_path: openapi_spec_path
handler: new_openapi_interface()!
)
}
@end

View File

@@ -2,6 +2,8 @@ fn test_new_openapi_interface() ! {
new_openapi_interface()!
}
@if http
fn test_new_openapi_http_controller() ! {
new_openapi_http_controller()!
}
@end

View File

@@ -7,11 +7,13 @@ pub fn new_openrpc_interface() !&interfaces.OpenRPCInterface {
return interfaces.new_openrpc_interface(client.Client)
}
@if http
// creates HTTP controller with the actor's OpenRPC Handler
// and OpenRPC Specification
pub fn new_openrpc_http_controller() !&openrpc.HTTPController {
pub fn new_openrpc_http_controller(params ServerParams) !&openrpc.HTTPController {
return openrpc.new_http_controller(
specification: openrpc_specification
handler: new_openrpc_interface()!
)
}
@end

View File

@@ -2,6 +2,8 @@ fn test_new_openrpc_interface() ! {
new_openrpc_interface()!
}
@if http
fn test_new_openrpc_http_controller() ! {
new_openrpc_http_controller()!
}
@end

View File

@@ -1,4 +1,7 @@
#!/usr/bin/env -S v -w -n -enable-globals run
import pet_store_actor
pet_store_actor.run_http_server()!
pet_store_actor.run_http_server(
base_url: 'http://localhost:8080'
port: 8080
)!

View File

@@ -4,11 +4,17 @@ import veb
import freeflowuniverse.herolib.schemas.jsonschema {Schema}
import x.json2 {Any}
import net.http
import os
const templates = os.join_path(os.dir(@FILE), 'templates')
pub struct HTTPController {
veb.StaticHandler
Handler // Handles OpenAPI requests
pub:
base_url string
specification OpenAPI
specification_path string
}
pub struct Context {
@@ -16,15 +22,27 @@ pub struct Context {
}
// Creates a new HTTPController instance
pub fn new_http_controller(c HTTPController) &HTTPController {
return &HTTPController{
pub fn new_http_controller(c HTTPController) !&HTTPController {
mut ctrl := HTTPController{
...c,
Handler: c.Handler
}
if c.specification_path != '' {
if !os.exists(c.specification_path) {
return error('OpenAPI Specification not found in path.')
}
ctrl.serve_static('/openapi.json', c.specification_path)!
}
return &ctrl
}
pub fn (mut c HTTPController) index(mut ctx Context) veb.Result {
return ctx.html($tmpl('templates/swagger.html'))
}
@['/:path...'; get; post; put; delete; patch]
pub fn (mut c HTTPController) index(mut ctx Context, path string) veb.Result {
pub fn (mut c HTTPController) endpoints(mut ctx Context, path string) veb.Result {
println('Requested path: $path')
// Extract the HTTP method

View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="SwaggerUI" />
<title>SwaggerUI</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@@5.11.0/swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@@5.11.0/swagger-ui-bundle.js" crossorigin></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: '@{c.base_url}/openapi.json',
dom_id: '#swagger-ui',
});
};
</script>
</body>
</html>