diff --git a/examples/hero/heroserver/heroserver.vsh b/examples/hero/heroserver/heroserver.vsh new file mode 100755 index 00000000..d7432388 --- /dev/null +++ b/examples/hero/heroserver/heroserver.vsh @@ -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()! diff --git a/lib/hero/crypt/age.v b/lib/hero/crypt/age.v index c51e0849..d98764eb 100644 --- a/lib/hero/crypt/age.v +++ b/lib/hero/crypt/age.v @@ -1,6 +1,5 @@ module crypt -import freeflowuniverse.herolib.core.redisclient import freeflowuniverse.herolib.data.resp // Stateless AGE operations diff --git a/lib/hero/heroserver/ai_instructions_specs.md b/lib/hero/heroserver/ai_instructions_specs.md index ef060614..a848a2d4 100644 --- a/lib/hero/heroserver/ai_instructions_specs.md +++ b/lib/hero/heroserver/ai_instructions_specs.md @@ -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 + - + - + - - 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 - diff --git a/lib/hero/heroserver/factory.v b/lib/hero/heroserver/factory.v index 5980591d..078c8e2e 100644 --- a/lib/hero/heroserver/factory.v +++ b/lib/hero/heroserver/factory.v @@ -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 -} \ No newline at end of file + return &HeroServer{ + config: config + auth_manager: new_auth_manager() + handler_registry: new_handler_registry() + } +} diff --git a/lib/hero/heroserver/server.v b/lib/hero/heroserver/server.v index 96b776e0..f400c147 100644 --- a/lib/hero/heroserver/server.v +++ b/lib/hero/heroserver/server.v @@ -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 {