lightbug_http
lightbug_http copied to clipboard
Propose Middleware Solution
This is a proposal and code sample for adding middleware to the light bug project.
Proposal
The chain of responsibility design pattern is used to chain together pieces of middleware that will each handle some aspect of the Request/Response. This allows someone to choose which middleware they want and allow them to remove or replace anything they need. It also supports adding their own custom middleware.
The Context
is used to wrap the HTTPRequest
and provided a dictionary of parameters. It should support AnyType
of value so you can add middleware to handle authentication or parsing cookies, query strings, paths and provide that to other middleware or handlers.
In the middleware package, I've provided 8 example middleware handlers: Error, Compression, Logger, CORS, Basic Authentication, Static, Router, and NotFound.
The Router
middleware is special in that it allows for different leaf nodes to be registered for a particular Request Pattern. This can become complex with routing based on any method, path, header combination. Also, it will need to support variable paths. The one provided is very rudimentary. We will want one that uses a high speed tree structure for the best performance.
The HTTPHandler
trait is used by the Router for the leaf nodes. We can add a LambdaHandler and support Lambdas when they become available.
The NotFound
is the last item in the chain. If no other middleware handles the Request, it will return a 404, not found response. By not hard coding this in the Router, we can support multiple routers in the chain which provides flexibility for mounting other projects or have Authorized vs Unauthorized routes.
The MiddlewareChain handles creating the linked list of Middleware. I added support for the existing HTTPService trait so it can easily be used instead of the existing services.
The lightbug_http.mojo
was modified to demonstrate the use of the Middleware.
I also renamed the lightbug_welcome.html
to index.html
so the StaticMiddleware could be used.
Current Issues:
- Traits are not fully supported yet so the
next
in the middleware and theroot
in the chain are failing to compile:
/middleware/router.mojo:11:5: error: TODO: dynamic traits not supported yet, please use a compile time generic inste
ad of 'Middleware'
var next: Middleware
- The
Dict
collection requires the value to support the CollectionElement trait. Both the HTTPHandler and AnyType are traits and not implementations so this causes issues with the Dict in the Router and Dict in the Context that holds the parameters.
/middleware/router.mojo:12:30: error: 'Dict' parameter #1 has 'CollectionElement' type, but value has type 'AnyTrait
[HTTPHandler]'
var routes: Dict[String, HTTPHandler]