Faq
Why doesn’t Frizzante have middleware?
Frizzante intentionally uses guards instead of middleware because of the following reasons - All middleware handlers must be invoked for each request
- It's difficult to understand which middleware handler checks which route
- Managing middleware execution order across different routes is complex
Instead, it favours guards because - Guards are applied only to specific routes, they don't check every single incoming request
- They are more explicit, you can see which guards protect which route just by looking at the route definition
- It's easy to compose and ensure a specific order of guards execution for each individual route
For more details see the guards page. Middleware Implementation
If you really want middleware-like behavior, you can easily implement it in your own project. package middlewares
import "main/lib/core/clients"
type Hook func(client *clients.Client, next func()) // Defines a hook function type which will be used by the middleware.
type Middleware struct { // Defines a structure holding multiple hooks.
Hooks []Hook // Defines the actual hooks slice.
} package middlewares
import (
"main/lib/core/clients"
"main/lib/core/routes"
)
func Apply(middleware *Middleware, routes []routes.Route) {
for _, route := range routes { // For each route...
handler := r.Handler // ...saves the route handler for later use.
route.Handler = func(client *clients.Client) { // Assigns a new wrapper route handler.
var quit bool // Creates flag used to interrupt the chain.
for _, hook := range middleware.Hooks { // Iterate over hooks.
quit = true // Prepares to quit.
if hook(client, func() { quit = false }); quit { // Invokes hook and checks if route should quit.
return // Quits.
}
}
handler(client) // Invokes the actual route handler.
}
}
} Note
Your implementation may vary.
This implementation doesn’t directly invoke the next hook, instead it use a flag to check when to stop.
This should reduce nesting in your stack trace and keep it a little more readable.
Middleware Usage
package main
import (
"embed"
"main/lib/core/clients"
"main/lib/core/routes"
"main/lib/core/servers"
"main/lib/core/view/ssr"
"main/lib/middlewares"
"main/lib/routes/fallback"
"main/lib/routes/todos"
"main/lib/routes/welcome"
"os"
)
//go:embed app/dist
var efs embed.FS
var server = servers.New()
var middleware = &middlewares.Middleware{
Hooks: []middleware.Hook{
func(client *clients.Client, next func()) {
// Hook logic goes here.
},
},
}
func main() {
defer servers.Start(server)
defer middlewares.Apply(middleware, server.Routes) // Applies middleware to server routes.
// Remember that deferred functions are executed in reverse,
// so this line will execute before the server starts.
server.Efs = efs // Sets embedded file system.
server.Routes = []routes.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},
}
} Can I use Frizzante with other frontend frameworks?
Yes you can, as long as Vite supports your framework. All you need to do is configure your app/app.client.ts and app/app.server.ts to render your framework. You can find an old Vue3 example here.