users@jax-rs-spec.java.net

[jax-rs-spec users] [jsr339-experts] Re: Re: Re: UriBuilder.segment and build with encodePathSlash

From: Markus KARG <markus_at_headcrashing.eu>
Date: Tue, 23 Oct 2012 18:56:12 +0200

Sergey, in fact I do not understand why you roll up again the completed
discussion again. What do you not understand with the user's expectation
that values (including slashes) provided to the build() method have to be
encoded ALWAYS as they are APPLICATION DATA (= decided by the user), while
values provided to any other methods like path() or segment() will be
encoded if this is needed due to the particular syntax of that URI part as
they form URI SYNTAX (= decided by the program)? Why can you not accept that
simple rule (maybe I miss something important)?

> 1. assertEquals("a/b", uriBuilder.fromPath("").path("a/b").build());
> 2. assertEquals("a%2Fb",
> uriBuilder.fromPath("").path("{a}").build("a/b"));
>
> 3. assertEquals("a%2Fb",
> uriBuilder.fromPath("").segment("a/b").build());
> 4. assertEquals("a%2Fb",
> uriBuilder.fromPath("").segment("{a}").build("a/b"));
>
>
> Note 3 and 4 produce the consistent output - it is easy to see why -
> the
> literal value as well as the "{a}" substitution are 'segments'
>
> 1 and 2 produce the inconsistent results, why, because Markus thought
> it
> was logical to get "/" encoded by default, despite UriBuilder saying
> loudly the encoding rules are scoped by the specific URI scheme rules.
> This breaks 2 of CXF tests and I wonder are we breaking the
> expectations
> of the users migrating from 1.1 or not (the fact TCK is silent on that
> does not count IMHO).
>
> Let me step back and review the actual original issue.
> We have '?' (meaning unclear) in
>
> assertEquals(?, uriBuilder.fromPath("").path("{a}").build("a/b"));
>
> Should "/" in "a/b" be encoded or left as is, who knows ? What if we
> have "build(readFromDB())" - where "a/b" is read from the db, etc.

It MUST be encoded ALWAYS as it is provided to the BUILD() method. Fullstop.

> How we solve this issue ?

What issue? I do not see any issue.
 
> We introduce 4 new methods (2 from the build and 2 from replaceTemplate
> families) with this extra flag dedicated to dealing with "/", a single
> symbol which happens to be important for the URI path component.
>
> We have 1. and 2. above producing inconsistent output where UriBuilder
> package-level documentation conflicts with the special rules for
> encoding "/".

There is no special rule for slash. The rules of URIs are clear: APPLICATION
DATA is to be encoded.

> We have 4 extra methods which don't make sense with a dangling boolean
> flag to be used when no template vars are found in the path component
> as
> opposed to the regular build functions which always make sense.

The flag exists solely for backwards compatibility to the FALSE assumption
what users expect in JAX-RS 1.1. You cannot omit it without breaking
something.

> So what could've been done instead, to address a tricky issue of
>
> uriBuilder.fromPath("").path("{a}").build(readFromDb()),
> where a return value may have contain "/" which have to be encoded ?
>
> Well, recommend users, when they face the issue like this, to use
>
> uriBuilder.fromPath("").segment("{a}").build(readFromDb())

The following three reasons had already been discussed and accepted by this
EG:

(1) This workaround was already discussed in the past and it did not work
due to a bug in the RI (Jersey), which incorrectly implemented segment().

(2) Also it does not work in case you do fromResource, where the parameter
is contained in the @Path already.

(3) "Segment" is not an official part of the URI specification (read it
carefully and you will notice), so we cannot expect people to use segment()
instead of path(), as it is counter-intuitive.

> and get the implementation to remember the 'origin' of the template
> var,
> i.e., whether it came from path() or segment(), we would then see
> consistently:
>
>
> 1. assertEquals("a/b", uriBuilder.fromPath("").path("a/b").build());
> 2. assertEquals("a/b",
> uriBuilder.fromPath("").path("{a}").build("a/b"));
>
> 3. assertEquals("a%2Fb",
> uriBuilder.fromPath("").segment("a/b").build());
> 4. assertEquals("a%2Fb",
> uriBuilder.fromPath("").segment("{a}").build("a/b"));
>
>
> Well, I've updated CXF code to support the current approach at the cost
> of getting the two failing tests 'fixed', but I felt I had to type the
> above
>
>
> Sergey
>
> >> Marek
> >>