-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to send requests with literal '+' character in URI query part #287
Comments
you're using the api incorrectly.
the addQueryParameter method will url encode the value
your server should be able to parse this just fine because, within a query string, in other words these two urls are to be considered effectively the same
in both cases, the server must parse the query string then url decode the value to get the original |
@bpossolo Thank you very much for your reply!
If this was the case, the documentation for that method has to be updated.
And by "URL", I would expect it to accept a URL according to RFC 1738, section 3.3 or RFC 3986.
You assume that I control the remote server, which is not the case. While
Yes, and that's the problem. It shouldn't encode "bob+jenkins" (which is perfectly fine) to "bob%2Bjenkins". It's not possible to create an HTTP request to a URL which contains a literal '+' character. If it is possible, please show me how. Here's the updated test with the changes you've recommended: import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.junit.Rule;
import org.junit.Test;
import play.libs.ws.WSClient;
import play.libs.ws.WSRequest;
import play.libs.ws.WSResponse;
import play.libs.ws.ahc.AhcWSClient;
import play.shaded.ahc.org.asynchttpclient.DefaultAsyncHttpClient;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.junit.Assert.assertEquals;
public class WSRequestQueryParametersTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule();
@Test
public void uriEncode() throws Exception {
WSClient wsClient = new AhcWSClient(new DefaultAsyncHttpClient(), null);
String requestUrl = wireMockRule.url("/path");
stubFor(get(urlEqualTo("/path?the+plus+must+remain")).willReturn(aResponse()
.withStatus(200)
.withBody("OK")));
WSRequest wsRequest = wsClient.url(requestUrl)
.addQueryParameter("the+plus+must+remain", "");
String url = wsRequest.getUrl();
assertEquals("Request URL and WSRequest.Url should be identical", requestUrl, url);
WSResponse wsResponse = wsRequest.get().toCompletableFuture().get();
assertEquals(200, wsResponse.getStatus());
verify(getRequestedFor(urlMatching("/path")).withQueryParam("the+plus+must+remain", equalTo("")));
}
@Test
public void uriEncode2() throws Exception {
WSClient wsClient = new AhcWSClient(new DefaultAsyncHttpClient(), null);
String requestUrl = wireMockRule.url("/path");
stubFor(get(urlEqualTo("/path?the+plus+must+remain")).willReturn(aResponse()
.withStatus(200)
.withBody("OK")));
WSRequest wsRequest = wsClient.url(requestUrl)
.setQueryString("the+plus+must+remain");
String url = wsRequest.getUrl();
assertEquals("Request URL and WSRequest.Url should be identical", requestUrl, url);
WSResponse wsResponse = wsRequest.get().toCompletableFuture().get();
assertEquals(200, wsResponse.getStatus());
verify(getRequestedFor(urlMatching("/path")).withQueryParam("the+plus+must+remain", equalTo("")));
}
} Failing output:
|
I think you’re misunderstanding how URL encoding works. The + character becomes %2B when url encoded. Are you saying your server can’t understand %20 in a query string? Because if it doesn’t then the server is seriously broken. Using a + instead of %20 is simply a convenience. |
@bpossolo Thanks again for your swift reply!
Thanks, I think I understand it perfectly well. 😉
Correct. And my problem is that I want (or rather have) to use a literal '+' character in the HTTP request because the remote service otherwise cannot process the request.
Correct. That's why I've asked how to provide raw or pre-encoded values.
Welcome to the Internet. This being said, a URL with literal '+' characters is still a valid URL, so if WSClient/WSRequest isn't able to build and send requests with that character, then they're broken (which is why I've opened this issue in the first place). Is there a way to provide a pre-encoded query string via WSClient/WSRequest? |
The same issue still exists on Play WS 2.0.0-RC1. I've created a repository with reproducible test cases for Play WS 1.1.12 and 2.0.0-RC1 at https://github.com/joschi/play-ws-issue-287. |
I've added a successful test case using |
I've updated the repository to demonstrate the issue with Play WS 2.0.0. |
|
I want to send a request to a remote HTTP service which has some strict encoding rules.
For example, HTTP requests to
http://example.com/path?query+string
are working, but requests tohttp://example.com/path?query%2Bstring
are not working.Unfortunately, Play WS always encodes the URL as
http://example.com/path?query%2Bstring
without the option to skip unnecessary encoding or to provide a raw query string.Play WS Version
Play WS 2.6.20
API (Scala / Java / Neither / Both)
Java
Operating System
MacOS 10.13.6
JDK
Expected Behavior
WSRequest
with valid URL viaWSClient#url(String)
, for examplehttp://example.com/path?query+string
.WSRequest#get()
.WSRequest
(http://example.com/path?query+string
).Actual Behavior
WSRequest
with valid URL viaWSClient#url(String)
, for examplehttp://example.com/path?query+string
.WSRequest#get()
.http://example.com/path?query%2Bstring
).Reproducible Test Case
The text was updated successfully, but these errors were encountered: