improve & fix openrpc handler and http interface

This commit is contained in:
timurgordon
2025-01-03 01:42:21 -05:00
parent d49e94e412
commit a6ba22b0b1
5 changed files with 117 additions and 73 deletions

View File

@@ -0,0 +1,52 @@
module openrpc
import veb
import freeflowuniverse.herolib.schemas.jsonrpc
// Main controller for handling RPC requests
pub struct HTTPController {
Handler // Handles JSON-RPC requests
// pub mut:
// handler Handler @[required]
}
pub struct Context {
veb.Context
}
// Creates a new HTTPController instance
pub fn new_http_controller(c HTTPController) &HTTPController {
return &HTTPController{
...c,
Handler: c.Handler
}
}
// Parameters for running the server
@[params]
pub struct RunParams {
pub:
port int = 8080 // Default to port 8080
}
// Starts the server
pub fn (mut c HTTPController) run(params RunParams) {
veb.run[HTTPController, Context](mut c, 8080)
}
// Handles POST requests at the index endpoint
@[post]
pub fn (mut c HTTPController) index(mut ctx Context) veb.Result {
// Decode JSONRPC Request from POST data
request := jsonrpc.decode_request(ctx.req.data) or {
return ctx.server_error('Failed to decode JSONRPC Request ${err.msg}')
}
// Process the JSONRPC request with the OpenRPC handler
response := c.handler.handle(request) or {
return ctx.server_error('Handler error: ${err.msg}')
}
// Encode and return the handler's JSONRPC Response
return ctx.json(response)
}

View File

@@ -20,7 +20,6 @@ fn handler(request jsonrpc.Request) !jsonrpc.Response {
fn test_new_server() {
specification := new(path: specification_path)!
new_controller(
specification: specification
handler: Handler{
specification: specification
handler: handler
@@ -31,7 +30,6 @@ fn test_new_server() {
fn test_run_server() {
specification := new(path: specification_path)!
mut controller := new_controller(
specification: specification
handler: Handler{
specification: specification
handler: handler

View File

@@ -0,0 +1,15 @@
module openrpc
import veb
import freeflowuniverse.herolib.schemas.jsonrpc
// Main controller for handling RPC requests
pub struct WebSocketController {
pub mut:
handler Handler @[required] // Handles JSON-RPC requests
}
// Creates a new HTTPController instance
pub fn new_websocket_controller(c WebSocketController) &WebSocketController {
return &WebSocketController{...c}
}

View File

@@ -0,0 +1,50 @@
module openrpc
import x.json2
import freeflowuniverse.herolib.schemas.jsonrpc
pub struct Handler {
pub:
specification OpenRPC @[required] // The OpenRPC specification
pub mut:
handler IHandler
}
pub interface IHandler {
mut:
handle(jsonrpc.Request) !jsonrpc.Response // Custom handler for other methods
}
@[params]
pub struct HandleParams {
timeout int = 60 // Timeout in seconds
retry int // Number of retries
}
// Handle a JSON-RPC request and return a response
pub fn (mut h Handler) handle(req jsonrpc.Request, params HandleParams) !jsonrpc.Response {
// Validate the incoming request
req.validate() or {
return jsonrpc.new_error_response(req.id, jsonrpc.invalid_request)
}
// Check if the method exists
if req.method == 'rpc.discover' {
// Handle the rpc.discover method
spec_json := h.specification.encode()!
return jsonrpc.new_response(req.id, spec_json)
}
// Validate the method exists in the specification
if req.method !in h.specification.methods.map(it.name) {
return jsonrpc.new_error_response(req.id, jsonrpc.method_not_found)
}
// Enforce timeout and retries (dummy implementation)
if params.timeout < 0 || params.retry < 0 {
return jsonrpc.new_error_response(req.id, jsonrpc.invalid_params)
}
// Forward the request to the custom handler
return h.handler.handle(req)
}

View File

@@ -1,71 +0,0 @@
module openrpc
import veb
import x.json2
import freeflowuniverse.herolib.schemas.jsonrpc
// Main controller for handling RPC requests
pub struct Controller {
pub:
specification OpenRPC @[required] // OpenRPC specification
pub mut:
handler Handler @[required] // Handles JSON-RPC requests
}
pub struct Context {
veb.Context
}
// Creates a new Controller instance
pub fn new_controller(c Controller) &Controller {
return &Controller{...c}
}
// Parameters for running the server
@[params]
pub struct RunParams {
pub:
port int = 8080 // Default to port 8080
}
// Starts the server
pub fn (mut c Controller) run(params RunParams) {
veb.run[Controller, Context](mut c, 8080)
}
// Handles POST requests at the index endpoint
@[post]
pub fn (mut c Controller) index(mut ctx Context) veb.Result {
req_raw := json2.raw_decode(ctx.req.data) or {
return ctx.server_error('Invalid JSON body') // Return error if JSON is malformed
}
req_map := req_raw.as_map() // Converts JSON to a map
// Create a jsonrpc.Request using the decoded data
request := jsonrpc.Request{
jsonrpc: req_map['jsonrpc'].str()
id: req_map['id'].str()
method: req_map['method'].str()
params: req_map['params'].str()
}
// Process the request with the handler
response := c.handler.handle(request) or {
return ctx.server_error('Handler error: ${err.msg}')
}
// Return the handler's response as JSON
return ctx.json(response)
}
pub struct Handler {
specification OpenRPC
pub mut:
handler fn(jsonrpc.Request) !jsonrpc.Response
}
// Handle a request and return a response
pub fn (h Handler) handle(req jsonrpc.Request) !jsonrpc.Response {
return h.handler(req)!
}