> If we go with adding support for regexs for parameters I was thinking we might support optional validation of template values in UriBuilder.
Validation will not be trivial. The regex needs to be applied to the %-escaped param value, but that requires knowing which <reserved> chars to %-escape and which to leave raw. @Path currently implies a lenient rule that is simple for paths: %-escape ‘?’, ‘#’, and optionally ‘/’, but not the other 15 <reserved> chars. The URI template draft is quite different, saying %-escape all <reserved> chars.
> The issue though is that we are then diverging from the likely path of the URI template specification which is what gives me pause on the whole regex idea.
Divergence for the URI path matching syntax should not be an issue as the URI template draft spec is adamant that its templates “were not designed for that use case [URI path matching], nor are they appropriate for that purpose” [§1.3 Applicability].
Avoiding divergence for the UriBuilder syntax would be nice.
JAX-RS’s hassle is that it reuses the same @Path values for both tasks.
This reuse will always fall foul of Postel’s Law: “be liberal in what you accept, and conservative in what you send”.
@Path needs to be liberal as it is used to accept URIs from other parties.
UriBuilder needs to be conservative as it builds URIs to send to other parties (eg as HTTP requests).
A @Path {name} placeholder accepting most <reserved> chars (other than ‘?’, ‘#’ and optionally ‘/’) is a sensibly lenient rule.
UriBuilder %-escaping all non-<unreserved> chars in parameter values is a sensible conservative rule [though not the current rule].
Every time we try to add a useful feature to parsing (such limited=true/false) or to building (such as {-list|/|foo}) there will be pain if the two are tightly coupled.
> Currently '/' isn't classed as an illegal character but we could make it so if limited==true for the template parameter.
That helps a little, but it is not a clean solution. The limited=true/false feature can only currently be specified with an annotation. We would probably want to specify it directly with UriBuilder. For instance, add a new method
UriBuilder.fromPath(String path, boolean encode, boolean limited);
Alternatively, define build(MultivaluedMap values) now. For a limited=true placeholder only the first value is used. For a limited=false placeholder each value provides a single segment.
>> (or replaced by an empty string if the parameter is not defined).
> That is currently an error and I think it should stay that way.
That diverges from the URI templates draft that substitutes an empty string.
>> UriBuilder.isEncoded() does NOT apply to parameters passed to UriBuilder.build() – they always get encoded.
> I don't think that is necessary.
The URI templates draft finds it necessary. Without it, a param value can basically rewrite to whole URI (eg “/tag/{tags}” with tags=”../people” produces “/people” which is not what the template author was expecting.
>> • The name in {name} should be a valid Java identifier
> The former isn't far from where we are now.
>> Future versions of JAX-RS may give special meaning to other names, though implementations of this version of JAX-RS must treat them all the same.
>Current versions should flag an error for invalid names so an attempt to use an incompatible future template with a 1.0 implementation won't silently cause an application to break.
Maybe. My more lenient approach could cause “silent breakage”, but it also allows a v2.0 template to be used in a v1.0 implementation as long as the caller is aware of this and passes, say, the param “-list|/|foo” as well as “foo” to the v1.0 implementation.
>> UriBuilder.fromPath(FooResource.class.getAnnotation(Path.class).value());
> I don't like this, building URIs to resources seems like a pretty common use case and making it harder doesn't in the way you suggest is a step backwards.
I would like to keep fromResource(…), but not if URI matching and URI building interpret the same @Path value in inconsistent ways.