drujensen
drujensen
MModular
Created by drujensen on 6/8/2024 in #questions
dynamic traits are not supported yet
Hello. Nooby question. I am working on some middleware for the lightbug project and want to build a chain-of-responsibility design pattern to handle the different aspects of processing a request / response:
## Middleware is an interface for processing HTTP requests.
## Each middleware in the chain can modify the request and response.
trait Middleware:
fn set_next(self, next: Middleware):
...
fn call(self, context: Context) -> HTTPResponse:
...

## MiddlewareChain is a chain of middleware that processes the request.
## The chain is a linked list of middleware objects.
struct MiddlewareChain(HTTPService):
var root: Middleware

fn add(self, middleware: Middleware):
if self.root == nil:
self.root = middleware
else:
var current = self.root
while current.next != nil:
current = current.next
current.set_next(middleware)

fn call(self, request: HTTPRequest) raises -> HTTPResponse:
var context = Context(request)
return self.root.call(context)
## Middleware is an interface for processing HTTP requests.
## Each middleware in the chain can modify the request and response.
trait Middleware:
fn set_next(self, next: Middleware):
...
fn call(self, context: Context) -> HTTPResponse:
...

## MiddlewareChain is a chain of middleware that processes the request.
## The chain is a linked list of middleware objects.
struct MiddlewareChain(HTTPService):
var root: Middleware

fn add(self, middleware: Middleware):
if self.root == nil:
self.root = middleware
else:
var current = self.root
while current.next != nil:
current = current.next
current.set_next(middleware)

fn call(self, request: HTTPRequest) raises -> HTTPResponse:
var context = Context(request)
return self.root.call(context)
This is how we would build the MiddlewareChain:
var middleware = MiddlewareChain()
middleware.add(CompressionMiddleware())
middleware.add(ErrorMiddleware())
middleware.add(LoggerMiddleware())
middleware.add(CorsMiddleware(allows_origin = "*"))
middleware.add(BasicAuthMiddleware("admin", "password"))
middleware.add(StaticMiddleware("static"))
middleware.add(router)
middleware.add(NotFoundMiddleware())
var middleware = MiddlewareChain()
middleware.add(CompressionMiddleware())
middleware.add(ErrorMiddleware())
middleware.add(LoggerMiddleware())
middleware.add(CorsMiddleware(allows_origin = "*"))
middleware.add(BasicAuthMiddleware("admin", "password"))
middleware.add(StaticMiddleware("static"))
middleware.add(router)
middleware.add(NotFoundMiddleware())
I'm getting the TODO: Dynamic traits are not supported yet. please use a compile time generic instead. I have tried using a Pointer[Middleware]` but you need the type to cast and make the call. I also tried passing in a concrete middleware type as a parameter at compile time but it requires some really ugly code to chain them together. Are there any other options? Let me know if anyone has a solution that doesn't look completely crazy.
6 replies