So I’ve been thinking about routes again.
When resources are an overlay, as in the example /*path, that's a problem for which Pedestal already has an elegant solution ("everything is an interceptor") and the alternative seems to be making routing complex and perhaps incomplete. For example, someone will want to use resources from two different places in the classpath, and they will set up two instances of /*path, which might initially work (?) but then they might start to care about which one took precedence... better to leverage Pedestal's architectural solution from the start, and use distinct interceptors, and therefore offering overlays in the routing table could be an investment that will lead to higher maintenance disproportionate to its utility.
It seems analogous to the problem of what if you wanted to use multiple overlapping routing tables. The answer would be distinct interceptors. All questions of relative priority of one URL interpretation over another are the domain of interceptors.
I guess the key is that half-measures are difficult to evaluate. And this seems to be half-measures to enable one routing table to behave more like two routing tables.
Two routing tables is not particular feasible if you want to keep route/url-for working. I’d like to be able to feed asset paths into url-for, just like I can dynamic resources.
If you look at how Sawtooth works, it keeps “subdividing” the routing space; first by the major parts of the request map (port, scheme, host, method/verb) then by peeling terms of the URI.
It can detect that two non-wild-path routes conflict when their terms all match (as wildcards match wildcards or any literal term). wild-path routes are harder to deal with and are already a special case.
So we’d be tweaking the definition of wild-card-path from “matches at least one term” to “matches at least one term that doesn’t match another route”.
What’s frustrating to people in 0.7 is that wild-card routes (single element or paths) always win when using prefix-tree. I see a constant stream of Nubankers complaining that their tests fail when they add a new route that silently conflicts with an existing one, and have to bend their URIs out of shape to accommodate.
I’m not 100% sure that partially inverting that behavior (wild-card paths always lose) is the final solution however.
But I would like a solution that has a single routing table and the current solution, using interceptors for resources, is effectively two routing tables.
The alternative is to rethink having resources be exposed as routes at all, and maybe move some of the optimizations I created for routed resources into the existing routing interceptors.
Which is why it’s still alpha.
If /*x is lower-priority than anything without an asterisk, then it might as well also be lower-priority than /y/*x . That is, the position of * in the route pattern is the unimportance level of the route. If there are to be 2 priority levels (no-star and star), there might as well be N levels.
I'm not sure I understand what the problem is though. If the right place to mount the resources is /, then routing has nothing to do with it. The routes take priority, and the resources are a catchall interceptor. Which means the resource interceptor's "enter" runs before routing (but does nothing) and its "leave" runs after routing's, and takes action only if the routes did not produce any response. And if resources' "leave" likewise yields no response then an outer catchall affixes a 404.
Yes, but in 0.8 you have the option of no resource interceptor, just resource routes in the routing table.
> I’m not 100% sure that partially inverting that behavior (wild-card paths always lose) is the final solution however. I think that is how it works for every other web application library/framework that I've used. Even CSS works that way (albeit in a clunky way): the most specific options always win.
Because Sawtooth is new, it’s not too late to change its behavior. I’m thinking about changing it as outlined in the issue. Essentially, wild-card paths (those with a “/*path” in the URI) are not considered until non-wild-card paths are exhausted. This would mean that mapping resources at “/*path” would not conflict with routes such as “/version” or “/api/project/:id” … but would still conflict with “/foo/*bar”. I think this would make mapping resources as routes (new in 0.8.0) rather than as interceptors prior to routing, more useful. As currently stands, you would need to, say, map resources as “/public/*path” to avoid route conflicts.
And that’s not ideal for a root index page, which you’d end up having to map as its own route. I’d prefer a solution where a single route covers incoming URLs “/”, “/index.html”, “/css/style.css”, etc., by mapping “/*path”.
If I need to stick with Java 8 for Reasons, I need Pedestal 0.5.10, right?
Clojure is still compatible with Java 8 AFAIK, but the Servlet API that underpins Jetty … I’d check those dependencies.
Yeah, I figured moving past Jetty 9 was the problem part.