Hi folks,
I wrote about this issue at some length last week about how the
container matches an incoming URI to an endpoint path (URI or level 1
URI template) is underspecified. In sum there are two problems and
here's what I propose the spec does to fix them. If you have serious
objections, please speak up soon with alternative fixes to the problems !
1) The default container match scheme is not fully defined.
This shows up in cases where an incoming URI may potentially exact match
one endpoint and also match another endpoint which uses a URI template.
And potentially matches a third endpoint that uses another URI template.
Which one gets the match ?
Here's what I propose:-
The container will attempt to match an incoming URI to an endpoint path
(URI or level 1 URI-template) as follows:-
The container will recursively try to exact match the longest shared
path prefix common to both incoming URI and endpoint path, done by
stepping down the paths one segment at a time, using '/' as the separator.
If the shared path prefix is the same as the endpoint path and also the
same as the incoming URI, then the paths match (end).
If the shared path prefix is the same as the endpoint path, but shorter
than the incoming URI, then the paths do not match (end).
If the shared path prefix is the same as the incoming URI, but shorter
than the endpoint path then the paths do not match (end).
Otherwise, there are more segments of both paths to compare, so taking
the next segment of both incoming URI and endpoint paths:-
If the next segment of the endpoint path is not a variable, it cannot
match the next segment in the incoming URI, otherwise the shared path
prefix would have included this path, so in this case, the paths do not
match (end).
If the next endpoint directory is a variable, assign the value of the
variable in the endpoint path to the value of the segment in the
incoming URI, and append the segment to the shared path prefix and call
it the new shared path prefix. Now repeat the steps above using the new
shared path prefix.
So, here are some examples of that in practice:-
suppose an endpoint has path /a/b/
the only incoming URI that matches this is /a/b/
suppose an endpoint is mapped to /a/{var}
incoming URIs that do match: /a/b (with var=b), /a/apple (with var=apple)
URIs that do NOT match: /a, /a/b/c (because empty string and strings
with reserved characters "/" are not valid URI-template level 1 expansions.)
suppose we have three endpoints and their paths:
endpoint A: /a/{var}/c
endpoint B: /a/b/c
endpoint C: /a/{var1}/{var2}
incoming URI: a/b/c matches B, not A or C, because an exact match is
preferred.
incoming URI: a/d/c matches A with variable var=d, because like
goldlocks, its just right :)
incoming URI: a/x/y/ matches C, with var1=x, var2=y
endpoint A: /{var1}/d
endpoint B: /b/{var2}
incoming URI: /b/d matches B with var2=d, not A with var1=b because the
matching process works from left to right.
2) The ServerEndpointConfig.Configurator.matchesURI(URI incoming, String
endpointPath) method cannot be supported without further specification
changes.
There are two problems: one is, does a developer provided match overrule
the default match algorithm ? And, second, if several
*Configurator.matchesURI()'s report a match, which one wins ?
As I wrote last week, we could resolve this by saying configurator
matchesURI wins over the default algorithm, and also imposing an order
on the endpoints, though this latter part would be a bit tricky to
specify properly. I suggested ordering what are currently Sets in the
returns from the ServerApplicationConfig methods, define the precedence
in relation to programmatically deployed endpoints. And use the order of
all that to give an order of precendence of the configurators matchesURI
results. But then we would still have the problem of how to order any
annotated endpoints deployed as a result of a scan when there is no
ServerApplicationConfig. Maybe we'd need some global priority ordering
scheme...
The issue that's hard to get away from is that for a proper URI matching
scheme, the scheme really needs to know ALL the endpoint paths in the
application in order to determine a best match out of several
candidates. Ordering the paths and picking off the first YES on a binary
endpoint-level YES/NO match is a special case of that, and while we
could define some kind of ordering, it neither feels especially useful
nor simple to put into practice for developers.
So I hate to remove API at this point, but I am proposing removing the
ServerEndpointConfig.Configurator.matchesURI() call and deferring the
ability to override the matching scheme until the next version when we
can define a proper application-level scheme for defining URI matching
policies instead of trying to make it work at the endpoint level.
(For the brave at heart that really need the override, you still are
able to override the handshake).
- Danny
--
<http://www.oracle.com> *Danny Coward *
Java EE
Oracle Corporation