FAQ
Why doesn’t Frizzante have middleware?
Section titled “Why doesn’t Frizzante have middleware?”Frizzante intentionally uses guards instead of middleware.
Middleware have some limitations.
- All middleware must be invoked for each request
- Some middleware may contain path-checking logic while others may not, which introduces ambiguity and more details to remember as a developer
- Managing middleware execution order across different routes is complex
While guards have some advantages.
- Explicit - you can see exactly which routes use which guards by looking at their tags
- Efficient - guards only execute when their tags match - no wasted computation
- Composable - easy to manage execution order per route
For more details see the guard page.
Middleware Implementation
Section titled “Middleware Implementation”If you really want middleware-like behavior, you can easily implement it in your own project.
package middleware
import "main/lib/core/client"
type Hook func(c *client.Client, next func()) // Defines a hook function type which will be used by the middleware.
type Middleware struct { // Defines a structure holds multiple hooks. Hooks []Hook // Defines the actual hooks slice.}
package middleware
import ( "main/lib/core/client" "main/lib/core/route")
func Apply(mid *Middleware, routes []route.Route) { for _, _route := range routes { // For each route... handler := _route.Handler // ...saves the route handler for later use. _route.Handler = func(c *client.Client) { // Assigns a new wrapper route handler. var quit = true // Creates flag used to interrupt the chain. for _, hook := range mid.Hooks { // For each hook... quit = true // ...prepares to quit... hook(c, func() { quit = false }) // ...invokes the hook... if quit { // Checks if route should quit. return // Quits. } } handler(c) // Invokes the actual route handler. } }}
Middleware Usage
Section titled “Middleware Usage”package main
import ( "embed" "main/lib/core/client" "main/lib/core/route" "main/lib/core/server" "main/lib/core/svelte/ssr" "main/lib/middleware" "main/lib/routes/handlers/fallback" "main/lib/routes/handlers/todos" "main/lib/routes/handlers/welcome" "os")
//go:embed app/distvar efs embed.FSvar srv = server.New()var dev = os.Getenv("DEV") == "1"var render = ssr.New(ssr.Config{Efs: efs, Disk: dev})
var mid = &middleware.Middleware{ // Creates middleware. Hooks: []middleware.Hook{ // Creates hooks. func(c *client.Client, next func()) { // Adds hook. // Logic goes here. }, },}
func main() { defer server.Start(srv) defer middleware.Apply(mid, srv.Routes) // Applies middleware to server routes. // Remember that deferred functions are executed in reverse, // so this line will execute before the server starts. srv.Efs = efs srv.Render = render srv.Routes = []route.Route{ {Pattern: "GET /", Handler: fallback.View}, {Pattern: "GET /welcome", Handler: welcome.View}, {Pattern: "GET /todos", Handler: todos.View}, {Pattern: "GET /check", Handler: todos.Check}, {Pattern: "GET /uncheck", Handler: todos.Uncheck}, {Pattern: "GET /add", Handler: todos.Add}, {Pattern: "GET /remove", Handler: todos.Remove}, }}