pippo
pippo copied to clipboard
Requesting a path ending with / must find a route with or without / at the end
Hi all!
For Spring and Pippo, the table is as follows:
Case | Client request | Defined route | Spring match? | Pippo match? |
---|---|---|---|---|
1 | /user | /user | yes | yes |
2 | /user/ | /user | yes | no |
3 | /user | /user/ | no | no |
4 | /user/ | /user/ | yes | yes |
Tests made for http: GET and PUT methods. Spring by default is forward and not redirect. Pipo does nothing.
In Pippo the case [2] does not happen. There is TrailingSlashHandler, but it redirects and only works for GET.
I found this comment https://github.com/pippo-java/pippo/issues/366#issuecomment-307214009-permalink from @decebals about registering a RoutePreDispatchListener to modify the request's path, but this is not possible because the path attribute is private. Another problem with this approach is removing the /
at the end from the request path we will have a problem in the case [4].
Another excerpt from the same comment is:
We need a mechanism to modify the initial Request (and probably Response) object(s) before to call Router.findRoutes()
I think this is not the way out. I think that the uriMatcher.match method within Router.findRoutes, should match the case [2]. It seems to be the ideal point to check this.
It goes something like this: if the request path ends with /
you must find a route that ends with or without /
. Cases [2] and [4].
What do you think? Did I miss something?
I think that is a good idea to have a Pippo-Spring match (case 2).
I have relative an annoying bug relative on this subject.
// add routes for security (login, logout, ...)
// addRouteGroup(new SecurityRoutes(authenticator)); // natural, but PIppo is not capable to understand this
new SecurityRoutes(authenticator).getRoutes().forEach(this::addRoute); // workaround
where SecurityRoutes
looks like:
public class SecurityRoutes extends RouteGroup {
private Authenticator authenticator;
public SecurityRoutes(Authenticator authenticator) {
super("");
this.authenticator = authenticator;
// PAC4J config
Config config = getPac4jConfig();
// authentication filter
ANY(securePaths(), new Pac4jSecurityHandler(config, "FormClient"));
// login
GET("/login", routeContext -> { ... });
// other routes
}
}