Details
-
Bug
-
Status: Resolved
-
Minor
-
Resolution: Fixed
-
3.4.3, 3.5.0
-
None
-
Unknown
Description
When declaring an http endpoint for an URL with a query string using endpoint dsl the target URL is incorrect due to appended value to the last parameter.
Consider the following route snippet:
... .to(http("myhost/mypath?param1=a¶m2=b").httpMethod("GET")) ...
The endpoint URI computed by AbstractEndpointBuilder is: myhost/mypath?param1=a¶m2=b?httpMethod=GET (spot the double question mark) }}and this leads to a wrong http request to {{http://myhost/mypath?param1=a¶m2=b%3FhttpMethod%3DGET.
If the query string is removed from the URI and provided as Exchange.HTTP_QUERY header the final HTTP URL is correct.
The same route without endpoint dsl works fine
… to("http://myhost/mypath?param1=a¶m2=b&httpMethod=GET") …
The problem may be in the following code in AbstractEndpointBuilder.computeUri, where a query string computed with endpoint parameters
is added to the target path without checking for the presence of a question mark.
String query = URISupport.createQueryString(params, encode); answer = new NormalizedUri(targetScheme + "://" + targetPath + "?" + query);
I don't know if this is the desired behavior and potential query string part of URIs should be provided in other ways (eg as header) or if it is a bug.
Here is a test to replicate the problem
@Override protected RoutesBuilder createRouteBuilder() throws Exception { return new EndpointRouteBuilder() { @Override public void configure() throws Exception { restConfiguration().port(9999); rest().get("path/xyz") .to("log:myLogger?level=INFO&showAll=true") .to("mock:result"); from(direct("test")) .to(http("localhost:9999/path/xyz?param1=1¶m1=2").httpMethod("GET")); from(direct("test2")) .to("http://localhost:9999/path/xyz?param1=1¶m2=2&httpMethod=GET"); } }; } // Test passes @Test public void testRoute() throws InterruptedException { MockEndpoint mockEndpoint = getMockEndpoint("mock:result"); mockEndpoint.expectedHeaderReceived("param1", "1"); mockEndpoint.expectedHeaderReceived("param2", "2"); template.sendBody("direct:test2", null); mockEndpoint.assertIsSatisfied(); } // Test fails with // java.lang.AssertionError: mock://result Header with name param1 for message: 0. Expected: <1> but was: <[1, 2%3FhttpMethod%3DGET]> // Expected :<1> // Actual :<[1, 2%3FhttpMethod%3DGET]> @Test public void testEndpointDslRoute() throws InterruptedException { MockEndpoint mockEndpoint = getMockEndpoint("mock:result"); mockEndpoint.expectedHeaderReceived("param1", "1"); mockEndpoint.expectedHeaderReceived("param2", "2"); template.sendBody("direct:test", null); mockEndpoint.assertIsSatisfied(); }