users@jsr311.java.net

RE: JAX-RS: UriBuilder handling _at_Path values and placeholder regexes

From: Manger, James H <James.H.Manger_at_team.telstra.com>
Date: Fri, 1 Aug 2008 17:09:10 +1000

Marc,
> UriBuilder.fromPath("a").segment("b/{foo:.+}").build("c/d")
>
> I think the builder should do context-sensitive encoding of the value before doing anything with the regex so you'd get:
>
> a/b%2fc%2fd

> UriBuilder.fromPath("a").path("b/{foo:.+}").build("c/d")
>
> would yield
>
> a/b/c/d

I agree with the above behaviour.

> I don't see why path(@Path("{foo}")) should be treated differently to path("{foo}").

I assume ub.path(“{foo}”).build(“c/d”) succeeds, yielding “c/d”. [I hope I don’t need to write ub.path(“{foo:.+}”).]

If ub.path(@Path(“{foo}”)).build(“c/d”) also yields “c/d” it would then have to throw an exception as “c/d” does not match the default regex of [^/]+ for {foo} in a @Path. If would be better if it yields “c%2Fd” which does match the default regex so the call succeeds.

Consequently path(@Path) should be treated differently to path(String) to avoid unnecessary exceptions. That is, so callers do NOT have to do manual %-escaping of ‘/’s to avoid exceptions when UriBuilder uses path(@Path).

One issue is that the default regex [^/]+ is appropriate for @Path where it is defined, but it is not appropriate for a template passed to:
* path(String) – which should allow ‘/’s;
* queryParam(name,…) – where ‘=’ and ‘&’ are special, but ‘/’ is no different than other reserved chars;
* queryParam(…,value) – where ‘&’ is special, but ‘/’ is no different than other reserved chars;
* …



> I'd also prefer to validate against the regex rather than requiring the implementation to parse the regex.

It is not 1) validate or 2) parse.
It is validate, and either 1) parse or 2) throw unnecessary exceptions.
Or rephrasing: it is validate, and either 1) parse or 2) require callers to manually %-escape values based on a tight coupling to the template (to know what to %-escape).

> …I'm actually OK with the status quo where the onus falls on the developer
> to supply values consistent with the path vs path segment distinction.

I feel that almost defeats the purpose of a URI template. If the party supplying the variable values has to know how they are going to be put in to the URI so it can %-escape them accordingly, then it may as well construct the URI by passing the values directly to host/path/queryParam/fragment methods, instead of passing them to build(…).
The benefit of a URI Template is that a template author can design the URIs how they want (and change that choice), independently of the template user who supplies variable values. The author and user have to agree on the names and semantics of the variables – but that should be all.

> its too onerous to require implementations to be able to parse an arbitrary regex and formulate an encoding scheme to match.

I agree.

Fundamentally, UriBuilder needs to know which of the 18 reserved chars to %-escape for each placeholder. That is easy to determine if the only allowed regexes are [^xyz…]* or [^xyz…]+, where x, y, z… are any of the 18 reserved chars.

Perhaps, instead of {name[:regex]}, the placeholder syntax should be {name[|reserved]} where the reserved chars that are allowed are explicitly listed.

James Manger



_____________________________________________
From: Manger, James H
Sent: Monday, 28 July 2008 9:21 AM
To: 'users_at_jsr311.dev.java.net'
Subject: JAX-RS: UriBuilder handling @Path values and placeholder regexes


“For each placeholder in a @Path value:
1. If there is no regex, treat it as a segment placeholder (%-escape ‘/’s);
2. If the regex is “.*” or “.+”, treat it as a path placeholder (don’t escape ‘/’s);
3. For any other regex, %-escape all non-unreserved characters.
A JAX-RS implementation MAY relax the 3rd rule above by not %-escaping characters that it knows are allowed by the regex. An application should not rely on a JAX-RS implementation to recognize such situations.

A UriBuilderException shall be thrown if a placeholder value (after %-escaping) does not match the regex given in a @Path placeholder.

_____________________________________________
From: Marc.Hadley_at_Sun.COM [mailto:Marc.Hadley_at_Sun.COM]
Sent: Friday, 1 August 2008 1:24 AM
To: users_at_jsr311.dev.java.net

>> UriBuilder.fromResource( @Path(“widget/{id}/info”) ).build(“X/123”)
>> 1. “widget/X/123/info”; or
>> 2. “widget/X%2F123/info”

Currently 1.


I don't see why path(@Path("{foo}")) should be treated differently to path("{foo}"). In the ideal case either method should escape the value of foo according to its regex (either explicit or implicit) not based on where the template comes from.


I'd rather rename fromResource to fromPath so that the method name reflects the URI component being affected, but I think the current naming is also fine.


I'd also prefer to validate against the regex rather than requiring the implementation to parse the regex. Encoding based on specific regex values is bound to cause issues when a developer starts to use more specific regex values and I think its too onerous to require implementations to be able to parse an arbitrary regex and formulate an encoding scheme to match.

That said, I'm actually OK with the status quo where the onus falls on the developer to supply values consistent with the path vs path segment distinction.
_____________________________________________
From: Marc.Hadley_at_Sun.COM [mailto:Marc.Hadley_at_Sun.COM]
Sent: Friday, 1 August 2008 6:27 AM
To: users_at_jsr311.dev.java.net

A related issue is what to do with:

UriBuilder.fromPath("a").segment("b/{foo:.+}").build("c/d")

I think the builder should do context-sensitive encoding of the value before doing anything with the regex so you'd get:

a/b%2fc%2fd

rather than

a/b%2fc/d

whereas

UriBuilder.fromPath("a").path("b/{foo:.+}").build("c/d")

would yield

a/b/c/d

Marc.