Using Apache URIBuilder '&' symbol in the query parameter gets encoded twice - java

I am trying to hit a webservice URL with a query parameter as foo & bar with the URL as encoded. To achieve encoding, I am using Apache URIBuilder. The code is as follows:
URIBuilder ub = new URIBuilder("http://example.com/query").setParameter("q", "foo & bar");
URI uri = ub.build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
I get the following as output: http://example.com/query?q=+foo+%2526+bar
I am new to this JAR file and have 2 questions:
Why is the space in the query param replaced with a '+' sign and not with %20 special character.
Why is the '&' symbol in the query param getting encoded twice and how to avoid it.

Why is the space in the query param replaced with a '+' sign and not with %20 special character.
In URI encoding, plus sign and %20 are interchangeable. However, another encoding may be used in different environment. For example when you are uploading using multipart/form-data, it will use different encoding. Thus you can't use neither %20 nor +.
Why is the '&' symbol in the query param getting encoded twice and how to avoid it.
It is not encoded twice, but it is URI encoded.
When you put query=A&B, you are sending two parameters:
query with value A
B with no value
This way, you can't send the actual &. To send & as a parameter, you must encode the parameter. If you send query=+foo+%2526+bar, you are sending only 1 parameter:
query with value foo & bar
To send q=foo&bar, you need to write this code:
URIBuilder ub = new URIBuilder("http://example.com/query");
ub.setParameter("q", "foo");
ub.setParameter("bar", "");
URI uri = ub.build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());

Related

Springboot : Prevent double encoding of % by Resttemplate

Our code uses Asyncresttemplate as follows
String uri = http://api.host.com/version/test?address=%23&language=en-US&format=json
getAysncRestTemplate().getForEntity(uri, String.class);
But %23 is double encoded in Rest template as %2523 and the url becomes
http://api.host.com/version/test?address=%2523&language=en-US&format=json,
But I need to pass encoded string, It doesn't encode if I pass decoded data '#'
How can I send this request without double encoding the URL?
Already tried using UriComponentsBuilder
Avoid Double Encoding of URL query param with Spring's RestTemplate
The uri argument (of type String) passed to the RestTemplate is actually a URI template as per the JavaDoc. The way to use the rest template without the double encoding would be as follows:
getAysncRestTemplate().getForEntity(
"http://api.host.com/version/test?address={address}&language=en-US&format=json",
String.class,
"#"); // (%23 decoded)
If you know you already have a properly encoded URL you can use the method that has a URI as the first parameter instead:
restTemplate.getForEntity(
new URI("http://api.host.com/version/test?address=%23&language=en-US&format=json"),
String.class);
You can avoid this by not encoding any part of it yourself, e.g use # rather than %23

How to encode comma in Spring UriComponentsBuilder?

I have following code:
String convertedBuilder = builder.toUriString();
convertedBuilder = convertedBuilder.replace(",", "\\,");
URI uri = UriComponentsBuilder.fromUriString(convertedBuilder)
.build().toUri();
The idea is to replace a single comma ',' by a '\,' (slash and comma).
Originated URL should be something like
'server-url'?name=te%5C%2Cst for parameter value 'te\,st.
However Spring generates this one:
'server-url'?name=te%5C%252Cst
What am I doing wrong?
Regards,
I had a similar requirement where I had to call a service with a GPS coordinate like this:
http://example.com/path?param1=40.678806%2C-73.943244
UriComponentsBuilder alone would either:
not encode the , (comma) within the parameter value
encode the encoded comma if I already had encoded the parameter with URLEncoder, thus producing the value 40.678806%252C-73.943244
I resolved by explicitly encoding the query parameter with URLEncoder and telling UriComponentsBuilder that the URL was already encoded:
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com/path")
.queryParam("param1" , URLEncoder.encode("40.678806,-73.943244", "UTF-8"));
ResponseEntity<String> resp = template.exchange(
builder.build(true).toUri(),
HttpMethod.GET,
null, new ParameterizedTypeReference<String> () {}
);
How to encode comma in Spring UriComponentsBuilder?
UriComponentsBuilder doesn't encode the comma since RFC doesn't require it to be encoded. You will have to encode it manually as suggested by Andreas in the comments.
However Spring generates this one:
'server-url'?name=te%5C%252Cst
No, it doesn't, as also mentioned by Andreas. It encodes the backslash but not the comma. Please fix the question if you need any more information.

encode special character in URL

{URL}/text=Congratulations%21+You+are+eligible+for+.%0A
%0A = New line encoded character
I am passing encoded new line syntax in parameter. But the problem is that when I am building the above URL then its again encoded the % as %25
so above URL become {URL}/text=Congratulations%21+You+are+eligible+for+.%250A
I am not able to understand why URLBuilder encode already encoded character.
Used below code for building URLBuilder
URI url = new URIBuilder("URL").build();
If you don't need url encoding why do you use URIBuilder at all? You could simply create a new URI.
You need #buildFromEncoded if you want to feed in pre-encoded strings.

Extract parameters from URL

I have problems with the character +(and maybe others) at the URIBuilder is suppose to get a decoded url but when I extract the query the + is replaced
String decodedUrl = "www.foo.com?sign=AZrhQaTRSiys5GZtlwZ+H3qUyIY=&more=boo";
URIBuilder builder = new URIBuilder(decodedUrl);
List<NameValuePair> params = builder.getQueryParams();
String sign = params.get(0).getValue();
the value of sing is AZrhQaTRSiys5GZtlwZ H3qUyIY= with a space instead +. How can I extract the correct value?
other way is:
URI uri = new URI(decodedUrl);
String query = uri.getQuery();
the value of query is sign=AZrhQaTRSiys5GZtlwZ+H3qUyIY=&more=boo in this case is correct, but I have to strip it. Is there another way to do that?
Use it differently:
String decodedUrl = "www.foo.com";
URIBuilder builder = new URIBuilder(decodedUrl);
builder.addParameter("sign", "AZrhQaTRSiys5GZtlwZ+H3qUyIY=");
builder.addParameter("more", "boo");
List<NameValuePair> params = builder.getQueryParams();
String sign = params.get(0).getValue();
addParameter method is responsible for adding parameters as to the builder. The constructor of the builder should include the base URL only.
If this URL is given to you as is, then the + is already decoded and stands for the space character. If you are the one who generates this URL, you probably skipped the URL encoding step (which can be done using the code snipped above).
Read a bit about URL encoding: http://en.wikipedia.org/wiki/Query_string#URL_encoding
That is because if you send space as parameter in url it is encoded as +. This happens because there are some rules which characters are valid in URL. See URL RFC.
It is necessary to encode any characters disallowed in a URL, including spaces and other binary data not in the allowed character set, using the standard convention of the "%" character followed by two hexadecimal digits.
If you want to have + as symbol in url you need to encode it into %2B. For example 2+2 is encoded as 2%2B2 and i am as i+am. So in your case I believe you have to correct result as AZrhQaTRSiys5GZtlwZ+H3qUyIY decodes into AZrhQaTRSiys5GZtlwZ H3qUyIY.

Pass a sentence to a webservice URL

I have a webservice URL in which I have to pass a value having spaces
but webservice is terming it as illegal
String path = java.net.URLDecoder.decode((CommonConstants.END_POINT_URL.concat(CommonConstants.DELETE_APPOINTMENT_REASON).replace("{id}", appointmentID).replace("{reason}", reason)),"UTF-8");
WebTarget target = client.target(path);
System.out.println(target);
targets gets printed as :
JerseyWebTarget { http://abc-def/SchServices/api/appointment/51574e11-b794-e411-824b-1cc1de6ebf5a?reason=Test Appointment Reason }
Spaces between test and appointment is not permitting it to hit webservice. URL encode is also not working....because it encodes complete thing...Please suggest
Change
.replace("{reason}", reason))
to something like
.replace("{reason}", URLEncoder.encode(reason, "UTF-8")))
which will encode the spaces for the url. Spaces are illegal in a well-formed URL, and there are two possible encodings %20 or +.

Categories