cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Rubén Pérez <ruben.pe...@uni-koeln.de>
Subject Re: Possible bug in UriBuilder?
Date Tue, 20 Jun 2017 17:36:20 GMT
Hi all,

A possible use case for building a relative URI can be, for instance, to 
issue a redirect as a response to servlet request. We can, of course, 
extract the URL from the ServletRequest and create a UriBuilder from it 
(I never said that there was not a workaround, after all :D), but it's 
also perfectly valid to call HttpServletResponse#sendRedirect(String) 
with a relative URL. That's was actually my first idea, until I found 
the bug.

I don't see why the UriBuilder may get confused, when the URI class does 
not. The URI opaque="mailto:testuser@sun.com?query=queryvalue#fragment" 
has the following components:

  * Scheme: mailto
  * Scheme-specific part: testuser@sun.com?query=queryvalue
  * Authority: null
  * Path: null
  * Query: null
  * Fragment: fragment

, while the URI "nonOpaque" defined as new URI(null, 
opaque.getSchemeSpecificPart(), opaque.getFragment()) has these:

  * Scheme: null
  * Scheme-specific part: testuser@sun.com?query=queryvalue
  * Authority: null
  * Path: testuser@sun.com
  * Query: query=queryvalue
  * Fragment: fragment

The "UriBuilder#uri" method says:
> Copies the non-null components of the supplied URI to the UriBuilder 
> replacing any existing values for those components.
So, the way I see it is:

 1. If the provided URI is opaque, the UriBuilder's new URI should be:
    URI(scheme, schemeSpecificPart, fragment), where schemeSpecificPart
    is the provided URI's (because that component can never be null),
    while the scheme and fragment parts are those of the provided URI,
    unless any of them is null, in which case the corresponding
    component of the UriBuilder's URI will be used.
 2. If the provided URI is not opaque, then you should use the
    constructor URI(scheme, authority, path, query, fragment)|| if the
    provided URI's authority is null (in which case the authority used
    should be the UriBuilder's). Path, query and fragment should be
    checked the same way.
 3. If the provided URI is not opaque, and the provided URI's authority
    is not null, then you should use the constructor URI(scheme,
    userInfo, host, port, path, query, fragment), where each component
    belongs to the provided URI, unless that specific component is null.
    I am not sure how to proceed with the port, because it can never be
    null, so I guess it always gets overwritten.

When I mention the constructors, what I mean is "the URI backing the 
UriBuilder should be constructed this way", or "the URI represented by 
the current state of the UriBuilder should be constructed this way".


I think that algorithm correctly in the problematic cases you mentioned 
and should not break any more usual use cases. What do you think?


Cheers


P.S: By the way, the RFC-3986 (https://tools.ietf.org/html/rfc3986) 
obsoletes RFC-2396 (https://tools.ietf.org/html/rfc2396), on which the 
current Java's URI implementation is based. In the new RFC, the 
structure is much better explained IMHO. For instance, it is clearly 
said that the path of a URI is never undefined, although it can be 
empty, the concept of "opaque URIs" disappear, and instead "opaque 
paths" are mentioned (i.e. "mailto:testuser@java.com" is no longer an 
opaque URI, but a URI with an opaque --or "non hierarchical"-- path). 
That does not help much in this case since UriBuilder should cope with 
the particularities of the current URI implementation anyway.


On 20/06/17 13:05, Sergey Beryozkin wrote:
> Hi Gary
>
> It was provided at the start of this thread, in general, if one has 
> something like
>
> UriBuilder.fromUri("relativePath")
>
> then the subsequent builder update methods have no effect because the 
> implementation treats this case as if URI has been opaque.
>
>
> I'm not sure why do in the real code something like
>
> UriBuilder.fromUri("relativePath").queryParam("name", "value")
>
> as opposed to
>
> UriBuilder.fromUri("http://host/relativePath").queryParam("name", 
> "value")
>
> but purely from the techincal point of view I guess CXF UriBuilder 
> impl should support this case...
>
> Cheers, Sergey
> On 20/06/17 03:56, Gary Gregory wrote:
>> Hi Sergey,
>>
>> Can you formulate the issue you are seeing in the form of a failing unit
>> test?
>>
>> Gary
>>
>> On Mon, Jun 19, 2017 at 9:02 AM, Sergey Beryozkin <sberyozkin@gmail.com>
>> wrote:
>>
>>> Hi
>>>
>>> Awhile back, may be 5-6 years back, I had to deal with the following 
>>> TCK
>>> test:
>>>
>>>              assertEquals("mailto:testuser@sun.com",
>>>
>>>                 UriBuilder.fromUri(new 
>>> URI("mailto:java-net@java.sun.com")).uri(new
>>> URI(null, "testuser@sun.com", null)).
>>>                      build();
>>>
>>>
>>> new URI("mailto:java-net@java.sun.com") is opaque, while
>>> new URI(null, "testuser@sun.com", null) is not.
>>>
>>> At a time I found that the only way for this test to pass was to 
>>> block any
>>> rawPaths not starting from "/" causing the confusion in the code, 
>>> such that
>>> in this test, when
>>>
>>> new URI(null, "testuser@sun.com", null).
>>>
>>> is submitted, the original "mailto" scheme is preserved, and the 
>>> original
>>> scheme specific part, "java-net@java.sun.com" is overridden as 
>>> expected,
>>> otherwise there would be some 'conflict; in the internal state, 
>>> after the
>>> 1st pass the 'path' is undefined because it was an opaque URI, and 
>>> in the
>>> second pass we suddenly get a path component value which is meant to
>>> replace an origin schemeSpecificPart where the path component was 
>>> not even
>>> defined...
>>>
>>> I realize that is not the most robust approach, but that worked at a 
>>> time.
>>>
>>> I see that UriBuilder.fromPath() does work in this case.
>>>
>>> Can you think of the fix that can address your issue such that the
>>> original UriBuilderImplTest tests continue passing ?
>>>
>>> Thanks, Sergey
>>>
>>>
>>>
>>>
>>> On 17/06/17 00:23, Rubén Pérez wrote:
>>>
>>>> Hi,
>>>>
>>>> Sorry for the double mail.
>>>>
>>>> I forgot to add that, while I know the .jar versions are not the 
>>>> latest,
>>>> I checked the code in Fisheye and from what I understood the issue
>>>> corresponds with the latest code. The problems seems to arise from 
>>>> the code
>>>> in the line 627 <https://fisheye.apache.org/br
>>>> owse/cxf/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxr
>>>> s/impl/UriBuilderImpl.java?hb=true#to627> [2]: if the path does not
>>>> start with a "/", the varirable schemeSpecificPart is set to null, 
>>>> which in
>>>> turn prevents the code block in the line 161 <
>>>> https://fisheye.apache.org/browse/cxf/rt/frontend/jaxrs/src
>>>> /main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java?hb=true#to161>

>>>>
>>>> [3] to run.
>>>>
>>>> Regards
>>>>
>>>>
>>>> On 16/06/17 23:52, Rubén Pérez wrote:
>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>> This is my first email to the list, so I hope I will not miss 
>>>>> something
>>>>> or do something wrong. I'm writing here instead of reporting a bug
>>>>> directly, mainly because I'm not sure if I can even register in 
>>>>> the bug
>>>>> tracker, so apologies if that was the expected way to go.
>>>>>
>>>>> Cutting to the chase, I believe there is a bug in the UriBuilderImpl.
>>>>> Specifically, when an instance of the class is created through the
>>>>> '.fromURI' method, and the provided URI does not start with a "/" 
>>>>> (i.e. it
>>>>> has no schema and authority and its path is not absolute), 
>>>>> UriBuilderImpl
>>>>> assumes incorrectly that the URI is non-hierarchical and therefore 
>>>>> the
>>>>> '.build()' method will always return the provided URI without 
>>>>> modification,
>>>>> regardless of which edit methods (e.g. "queryParam", "path", etc.) 
>>>>> are
>>>>> called on the instance.
>>>>>
>>>>> In order to illustrate what I mean, I created a very simple program
>>>>> (attached). I compiled it with:
>>>>>
>>>>>      javac -cp '.:<path_to_the_jar>/javax.ws.rs-api-2.0.1.jar'
>>>>> UriBuilderBug.java
>>>>>
>>>>> and runned it with:
>>>>>
>>>>>      java -cp '.:/<path_to_the_jar>/javax.ws
>>>>> .rs-api-2.0.1.jar:<path_to_the_jar2>/cxf-rt-frontend-jaxrs-
>>>>> 3.1.11.jar:<path_to_the_jar3>/cxf-core-3.1.11.jar' UriBuilderBug
>>>>>
>>>>> The RFC-3986, in its section 4.2 <https://tools.ietf.org/html/r
>>>>> fc3986#section-4.2> [1] defines the syntax for valid relative URI
>>>>> references and explicitly allows references without schema or 
>>>>> authority
>>>>> that do *not* start with a forward slash. Perhaps part of the 
>>>>> confusion
>>>>> comes from the fact that the ABNF defining the relative references 
>>>>> is as
>>>>> follows:
>>>>>
>>>>>      relative-part = "//" authority path-abempty
>>>>>                     / path-absolute
>>>>>                     / path-noscheme
>>>>>                     / path-empty
>>>>>
>>>>> , where the "/" symbol representing the different alternatives can be
>>>>> easily mistaken for a literal "/" in the URI itself.
>>>>>
>>>>> So that's it. Thanks for reading till here. Please let know your
>>>>> opinions about this and, if I'm right, it would be great to get it 
>>>>> fixed
>>>>> soon. If something is not clear or you have any questions, I'm 
>>>>> willing to
>>>>> answer them. If there's a reason for the current behaviour, or if 
>>>>> I am
>>>>> incorrectly interpreting the standard, I'd also be very glad to know.
>>>>>
>>>>> Best regards
>>>>> -- 
>>>>> Rubén Pérez Vázquez
>>>>>
>>>>> *Universität zu Köln*
>>>>> /Regionales Rechenzentrum (RRZK)/
>>>>> Weyertal 121, Raum 4.05
>>>>> D-50931 Köln
>>>>> ✆: +49-221-470-89603
>>>>>
>>>>> [1] https://tools.ietf.org/html/rfc3986#section-4.2
>>>>>
>>>>
>>>>
>>>
>>> -- 
>>> Sergey Beryozkin
>>>
>>> Talend Community Coders
>>> http://coders.talend.com/
>>>
>>

-- 
Rubén Pérez Vázquez

*Universität zu Köln*
/Regionales Rechenzentrum (RRZK)/
Weyertal 121, Raum 4.05
D-50931 Köln
✆: +49-221-470-89603

[1] https://tools.ietf.org/html/rfc2396
[2] https://tools.ietf.org/html/rfc3986

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message