Repository navigation
CXF-7986: WebClient.path method overwrites base URL when given absolute URL as input - #3596
Conversation
coheigea
left a comment
There was a problem hiding this comment.
@reta Claude tells me it causes a TCK regression:
The Jakarta REST TCK test ee.jakarta.tck.ws.rs.api.rs.core.uribuilder.JAXRSClientIT calls UriBuilder.fromPath(...) with an absolute URI 25 times. Examples are fromPath(LOCALHOST), where LOCALHOST = "http://localhost:8080", and replaceMatrixParamTest3 / replaceMatrixTest2, which use fromPath("http://localhost:8080;name=x=;..."). It expects the absolute URI to come back.
Suggested fix:
if (isAbsoluteUriPath(path) && scheme == null && host == null
&& schemeSpecificPart == null && paths.isEmpty()) {
// existing URI.create / TCK-hack branch, unchanged
}
This still fixes CXF-7986, because a WebClient base always has a scheme and host, so path("http://bar") gets appended. fromPath("http://…") stays TCK-compatible, and the unit-test rewrites, the expected-value changes and the JAXBElementProvider change can be reverted. The three new WebClientTest cases should still pass. I’d also add a UriBuilderImplTest case such as fromUri("http://foo").path("http://bar"), so the fix is covered in rt/frontend/jaxrs itself.
Some other points:
Inconsistency. replacePath(String) (around line 781) still treats http:/https: as a full URI, so path() and replacePath() now disagree.
Appended URL loses a slash. path("http://www.bar.com") now gives …/http:/www.bar.com, because the // is collapsed. That’s harmless, but it shows the input isn’t being encoded faithfully. The new tests only check the host and a startsWith, so they don’t pin this down.
|
Problems that remain
|
|
There is one remaining gap - the ; case that was kept for the TCK still writes the path straight after the host with no /. @ is a legal path character, so it isn’t encoded. Possible fix: in the originalPathEmpty && thePath.startsWith(";") branch of buildUriString, encode @ as %40 before appending. |
@coheigea with this one we opened a pandora box, sadly:
But it is not just
The only reliable way that I found is to use leading slash in front of path (but that will change the behavior of Alternatively, we could fail with an exception but that could be surprising. |
There was a problem hiding this comment.
A few small, non-blocking points on the latest commit:
- Javadoc on
needsLeadingSlash: it says "The URI parsing logic seems to be flawed", butjava.net.URIfollows RFC 3986 here.;,&and+are valid userinfo characters, so inhttp://foo.com;@evil.comthe userinfo isfoo.com;and the host isevil.com. Suggested wording:;,&and+are valid userinfo characters (RFC 3986), so a path glued to the host that contains@is parsed as userinfo and the text after@becomes the host. To prevent that, always insert a leading/when the path contains@. - Double negative in
buildURI:!(thePath.startsWith("/") || !needsLeadingSlash(thePath))reads more easily as!thePath.startsWith("/") && needsLeadingSlash(thePath). - Test names: the new
testUserInfoAnd...DoesNotChangeHosttests check@in the path or matrix parameters, not userinfo. A name liketestAtSignInMatrixDoesNotChangeHostwould describe them better. - Formatting:
- The comment in
testUserInfoAndPathWithMatrixis misindented (// The URI will treat…). - These lines have trailing whitespace: the blank line before the
needsLeadingSlashjavadoc, its*lines, the blank line beforetestPathWithUserInfoDoesNotChangeHost, and// Always include the leading slash in order to prevent host overrides.
- The comment in
- PR description: it still argues that a path is always relative. It would help to describe the actual rule instead: an absolute URI passed to
path()/replacePath()replaces the URI only when no scheme or host is set yet, and otherwise it's appended as a path.
Thanks @coheigea , addressed a majority of them, also included |
CXF-7986: WebClient.path method overwrites base URL when given absolute URL as input. The
UriBuilderis pretty clearly states that path represents a relative URI:However,
UriBuilderImpldoes override the whole URI when path is supplied with absolute URI.