Might want to take a look at section 12.1 "Use of URL Paths" in the Servlet
3.0 spec.
It seems like most of your questions have been answered in that spec.
(snip)
Upon receipt of a client request, the Web container determines the Web
application
to which to forward it. The Web application selected must have the longest
context
path that matches the start of the request URL. The matched part of the URL
is the
context path when mapping to servlets.
The Web container next must locate the servlet to process the request using
the path
mapping procedure described below.
The path used for mapping to a servlet is the request URL from the request
object
minus the context path and the path parameters. The URL path mapping rules
below are used in order. The first successful match is used with no further
matches
attempted:
1. The container will try to find an exact match of the path of the
request to the path of the servlet. A successful match selects the servlet.
2. The container will recursively try to match the longest path-prefix.
This is done by stepping down the path tree a directory at a time, using
the ’/’ character as a path separator. The longest match determines the
servlet selected.
3. If the last segment in the URL path contains an extension (e.g.
.jsp), the servlet container will try to match a servlet that handles
requests for the extension. An extension is defined as the part of the last
segment after the last ’.’ character.
4. If neither of the previous three rules result in a servlet match, the
container will attempt to serve content appropriate for the resource
requested. If a "default" servlet is defined for the application, it will
be used. Many containers provide an implicit default servlet for serving
content.
The container must use case-sensitive string comparisons for matching.
(/snip)
Couldn't we make the rules on matching order as such ...
1. Exact (non URI template) Endpoint path match on statically declared
paths (from @ServerEndpoint.value or ServerEndpointConfig.getPath())
2. Recursively match longest statically declared URI-template paths
(from @ServerEndpoint.value or ServerEndpointConfig.getPath())
3. If no match on the above, use dynamic path matching from application
provided collection of ServerEndpointConfig.Configurator.matchesURI() calls.
4. If no match from Configurator's, then the connection cannot be
upgraded.
(This is really off the cuff, and how Jetty has it initially planned out,
heavily influenced by the Servlet spec)
The point raised about Set vs List declaration is useful.
While I think List is the better choice, we could still get away using Set
if we document the undetermined behavior.
--
Joakim Erdfelt <joakim_at_intalio.com>
webtide.com <http://www.webtide.com/>
Developer advice, services and support
from the Jetty & CometD experts
eclipse.org/jetty - cometd.org
On Thu, Mar 14, 2013 at 11:34 AM, Danny Coward <danny.coward_at_oracle.com>wrote:
> Hi folks,
>
> Really following on from what I wrote about the default matching algorithm
> and how it handles a mixture of URIs and URI-templates in an application,
> it has raised an issue that I can't yet think of a solution for.
>
> We have a scheme for allowing endpoints to override the URI matching
> algorithm. The
>
> public boolean matchesURI(String path, URI requestUri, Map<String, String>
> templateExpansion)
>
> method on the ServerEndpointConfig.Configurator. Unfortunately, I can't
> think of a way to make this work correctly in all situations without some
> changes and/or further specification. Here's why:-
>
> We know that the default match (i.e. if no configurators are provided)
> gives us an unambiguous answer as to which endpoint matches an incoming
> URI, even in case like this:-
>
> EndpointA: /hello
> EndpointB: /{greeting}
>
> where two endpoint paths potentially match on the incoming URI /hello (see
> previous email on that).
>
> But as soon as one or more endpoints provide a configurator which
> overrides matchesURI, then the implementation has to answer a few
> questions:-
>
> 1) Which configurator do I call first ?
> 2) What if more than one configurator declares a match ?
> 3) What if the default match algorithm also yields a match on an endpoint.
> Is that more or less important ?
>
> There isn't enough information in the application (as currently specified)
> to answer any of these questions, so the answers are going to be
> implementation dependent. i.e. your application might have different
> endpoints being called per incoming URI depending on which implementation
> you are running on.
>
> The options I can think of to fix this are:-
>
> 1) Remove matchesUri from the ServerEndpointConfig.Configurator (rather
> draconian, but it would remove all the ambiguity)
>
> 2) Define a deployment order on the endpoints (all deployment methods
> change from Set to List) and define a how the match precedence works in
> relation to the endpoint ordering, e.g.
> call the developer provided endpoint configurators first in deployment
> order, first configurator to give a match wins. if no match:-
> use the default algorithm to determine the best match.
> (I'm not sure this works yet, I'd be grateful if someone could check it
> would in parallel with me)
>
> Can anyone think of a better option then these that does not require
> creating new APIs or functions ?
>
> Thanks,
>
> - Danny
>
>
> --
> <http://www.oracle.com> * Danny Coward *
> Java EE
> Oracle Corporation
>