refactor: Simplify handler signatures and add server runner
- Pass URL params as direct arguments to handlers - Use `ctx.get_custom_header` to retrieve session key - Add a runnable script to start the heroserver - Clean up formatting in documentation and code - Remove unused redisclient import
This commit is contained in:
6
examples/hero/heroserver/heroserver.vsh
Executable file
6
examples/hero/heroserver/heroserver.vsh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.hero.heroserver
|
||||
|
||||
mut server := heroserver.new_server(port: 8080)!
|
||||
server.start()!
|
||||
@@ -1,6 +1,5 @@
|
||||
module crypt
|
||||
|
||||
import freeflowuniverse.herolib.core.redisclient
|
||||
import freeflowuniverse.herolib.data.resp
|
||||
|
||||
// Stateless AGE operations
|
||||
|
||||
@@ -6,29 +6,27 @@ and the implementation of the example of how webserver is see lib/schemas/openrp
|
||||
specs for the heroserver
|
||||
|
||||
- a factory (without globals) creates a server, based on chosen port
|
||||
- the server does basic authentication and has
|
||||
- register method: pubkey
|
||||
- authreq: pubkey, it returns a unique key (hashed md5 of pubkey + something random). (is a request for authentication)
|
||||
- auth: the user who wants access signs the unique key from authreq with , and sends the signature to the server, who then knows for sure I know this user, we return as sessionkey
|
||||
- the server does basic authentication and has
|
||||
- register method: pubkey
|
||||
- authreq: pubkey, it returns a unique key (hashed md5 of pubkey + something random). (is a request for authentication)
|
||||
- auth: the user who wants access signs the unique key from authreq with , and sends the signature to the server, who then knows for sure I know this user, we return as sessionkey
|
||||
- all consequent requests need to use this sessionkey, so the server knows who is doing the requests
|
||||
- the server serves the openrpc api behind api/$handlertype/... the $handlertype is per handler type, so we can register more than 1 openrpc hander
|
||||
- the server serves an html endpoint for doc/$handlertype/
|
||||
|
||||
|
||||
for the doc (html endpoint)
|
||||
|
||||
- use bootstrap from cdn
|
||||
- https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css
|
||||
- https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js
|
||||
- https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js
|
||||
- <https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css>
|
||||
- <https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js>
|
||||
- <https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js>
|
||||
- create an html template in lib/hero/heroserver/template/doc.md (template for v language)
|
||||
- the template uses the openrpc spec obj comes from lib/schemas/openrpc and lib/schemas/jsonrpc for the schema's
|
||||
- so first fo the spec decode to the object from schemas/openrpc then use this obj to populate the template
|
||||
- in the template make a header 1 for each rootobject e.g. calendar, then dense show the methods with directly in the method a dense representation of the params and return
|
||||
- each object e.g. pub fn (self Comment) description(methodname string) string { has a description and pub fn (self Comment) example(methodname string) (string, string) wich returns description per method, if not filled in then its for the full rootobject, and also example, make sure to use those in the template for the documentation
|
||||
- the template is markdown, we will have to use a .md to .html conversion (best to do in browser itself) and get .md from the webserver directly and convert
|
||||
- the purpose is to have a very nice documentation done per object so we know what the object does, and how to use it
|
||||
- the template uses the openrpc spec obj comes from lib/schemas/openrpc and lib/schemas/jsonrpc for the schema's
|
||||
- so first fo the spec decode to the object from schemas/openrpc then use this obj to populate the template
|
||||
- in the template make a header 1 for each rootobject e.g. calendar, then dense show the methods with directly in the method a dense representation of the params and return
|
||||
- each object e.g. pub fn (self Comment) description(methodname string) string { has a description and pub fn (self Comment) example(methodname string) (string, string) wich returns description per method, if not filled in then its for the full rootobject, and also example, make sure to use those in the template for the documentation
|
||||
- the template is markdown, we will have to use a .md to .html conversion (best to do in browser itself) and get .md from the webserver directly and convert
|
||||
- the purpose is to have a very nice documentation done per object so we know what the object does, and how to use it
|
||||
|
||||
make clear instructions what code needs to be written and which steps are needed
|
||||
we are in architecture mode
|
||||
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
module heroserver
|
||||
|
||||
|
||||
@[params]
|
||||
pub struct ServerConfig {
|
||||
pub:
|
||||
port int = 8080
|
||||
host string = 'localhost'
|
||||
port int = 8080
|
||||
host string = 'localhost'
|
||||
}
|
||||
|
||||
// Factory function to create new server instance
|
||||
pub fn new_server(config ServerConfig) !&HeroServer {
|
||||
mut server := &HeroServer{
|
||||
config: config
|
||||
auth_manager: new_auth_manager()
|
||||
handler_registry: new_handler_registry()
|
||||
}
|
||||
return server
|
||||
}
|
||||
return &HeroServer{
|
||||
config: config
|
||||
auth_manager: new_auth_manager()
|
||||
handler_registry: new_handler_registry()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,13 +40,9 @@ pub fn (mut s HeroServer) auth(mut ctx Context) veb.Result {
|
||||
|
||||
// API endpoints
|
||||
@['/api/:handler_type'; post]
|
||||
pub fn (mut s HeroServer) api(mut ctx Context) veb.Result {
|
||||
handler_type := ctx.params['handler_type'] or {
|
||||
return ctx.request_error('handler_type not found in params')
|
||||
}
|
||||
|
||||
pub fn (mut s HeroServer) api(mut ctx Context, handler_type string) veb.Result {
|
||||
// Validate session
|
||||
session_key := ctx.req.header.get('Authorization') or { '' }
|
||||
session_key := ctx.get_custom_header('Authorization') or { '' }
|
||||
if !s.auth_manager.validate_session(session_key) {
|
||||
return ctx.request_error('Invalid session')
|
||||
}
|
||||
@@ -65,11 +61,7 @@ pub fn (mut s HeroServer) api(mut ctx Context) veb.Result {
|
||||
|
||||
// Documentation endpoints
|
||||
@['/doc/:handler_type'; get]
|
||||
pub fn (mut s HeroServer) doc(mut ctx Context) veb.Result {
|
||||
handler_type := ctx.params['handler_type'] or {
|
||||
return ctx.request_error('handler_type not found in params')
|
||||
}
|
||||
|
||||
pub fn (mut s HeroServer) doc(mut ctx Context, handler_type string) veb.Result {
|
||||
handler := s.handler_registry.get(handler_type) or { return ctx.not_found() }
|
||||
|
||||
doc_html := s.generate_documentation(handler_type, handler) or {
|
||||
|
||||
Reference in New Issue
Block a user