-
Notifications
You must be signed in to change notification settings - Fork 2
Run application middlewares on routing errors #27
Run application middlewares on routing errors #27
Conversation
Codecov Report
@@ Coverage Diff @@
## main #27 +/- ##
==========================================
+ Coverage 76.65% 76.84% +0.18%
==========================================
Files 83 83
Lines 2039 2047 +8
==========================================
+ Hits 1563 1573 +10
+ Misses 417 415 -2
Partials 59 59
Continue to review full report at Codecov.
|
Thank you! Looks like a nice solution. I will test and play with it later today. |
http/routing/route_collection.go
Outdated
@@ -143,6 +144,8 @@ func (c *RouteCollection) Middleware(middleware ...inter.HttpMiddleware) inter.R | |||
route.SetMiddleware(middleware) | |||
} | |||
|
|||
c.globalMiddlewares = append(c.globalMiddlewares, middleware...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only problem is that the globalMiddlewares
is also filled in groups from other routes, but is not used there. But maybe not so bad.
We can also make use of Fallback Routes. We put it on the api route group and on the web route group (in api.go or in route_service_provider.go). Then it is clear which middlewares are executed and which are not. In addition, you have more control over the difference between web and api. How do you think of that?
https://confetti-framework.github.io/docs/the-basics/routing.html#fallback-routes
Example:
var Api = Group(
Get("/ping", controllers.Ping).Name("ping"),
Fallback(func(request inter.Request) inter.Response {
return outcome.Json(map[string]string{"message": "not found"}).Status(net.StatusNotFound)
}),
).
Prefix("/api").
Middleware(middleware.Api...).
Name("api.")
Or:
var Api = Group(
Get("/ping", controllers.Ping).Name("ping"),
Fallback(controllers.FallbackJson),
).
Prefix("/api").
Middleware(middleware.Api...).
Name("api.")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not sure whether I fully understand the problem about middlewares from other routes. Do you mean that the name globalMiddlewares
is inaccurate because for a route collection that is not bound as routes
singleton on the app, the middlewares aren’t actually global in the scope of the application? If so yes, that’s true. Maybe we could rename it to just middlewares
.
I was trying to make a middleware that serves static files from the disk. I didn’t want to manually create a fallback route because I wanted to keep the normal error behavior of encoder.ErrorToHtml
to fall back to the error page without writing any code for it.
Using a fallback route here sounds like an interesting idea. This would implicitly alleviate the issue that global middlewares don’t run when a route is not registered for the path. When a fallback route is present on the Web
group, all global and route-specific middlewares are executed.
How would you roughly go about adding a standard fallback (if that’s what you’re suggesting 😅) while retaining the standard not-found behavior?
Edit: this is the global fallback that I’ve added to my test app. We don’t have access to the app-specific views
package in foundation though.
// in RouteServiceProvider.Boot
collection.Merge(routing.Fallback(func(request inter.Request) inter.Response {
return outcome.Html(views.Error(request.App(), routing.RouteNotFoundError))
}))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You totally convinced me. After some thinking, I don't think a fallback route is a very nice solution.
Actually now my only objection is the naming of globalMiddlewares
. Renaming it to middlewares
is indeed much better. Than we can use that for something else later too. If you change that, I'll merge it 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thank you 😄 I’ve renamed the slice to middlewares
, back to you! 🏓
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Released in v0.11.1
I also pasted the HEAD together with the GET in that release (same as in Laravel)
If a request is made to an URI which doesn’t resolve to a route, Confetti will currently not execute a middleware. This makes it impossible to add behavior for handling these soft errors gracefully or log the request. Therefore, this makes application middlewares run on routing errors by storing the middlewares on the RouteCollection and setting them when creating an error route.
6f4271a
to
284d3a2
Compare
If a request is made to an URI which doesn’t resolve to a route,
Confetti will currently not execute a middleware. This makes it
impossible to add behavior for handling these soft errors gracefully or
log the request.
Therefore, this makes application middlewares run on routing errors by
storing the middlewares on the RouteCollection and setting them when
creating an error route.