-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Propose Middleware Solution #33
base: main
Are you sure you want to change the base?
Propose Middleware Solution #33
Conversation
This looks really good! Thank you for this contribution. I looked at how this is done in other languages. Seems like middleware infrastructure is normally already included in basic libraries like
About the technical issues you mentioned:
|
Thanks for taking a look at the proposal. It looks like Mojo will need to mature a bit before we can build out a proper web framework. I'm hoping they provide a standard for creating middleware built-in to the Mojo standard library. The Crystal language did this and it helped with compatibility between frameworks. Regarding the issues, I think rust like traits, go like interfaces or OO inheritance will be needed for the duck typing to work. Looking forward to when Mojo properly supports this capability. |
Posted a thread on the |
@drujensen
I tried it out, seems to work! Compiler error went away. Guess I should've read Mojo docs more closely 😅 |
@drujensen should we continue to pursue this, since duck typing seems to work? |
@savioran I have tried the approach but haven't figured it out yet. I'm a nooby to Mojo and the metaprogramming stuff takes a bit to get used too. The documentation is sparse and copilot is useless. I do have the lsp working in neovim so that should help make the process a bit smoother. I will continue to look into this and see if I can get a working version. |
04187a0
to
393bdfe
Compare
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 theHTTPRequest
and provided a dictionary of parameters. It should supportAnyType
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
toindex.html
so the StaticMiddleware could be used.Current Issues:
next
in the middleware and theroot
in the chain are failing to compile: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.