How to encode comma in Spring UriComponentsBuilder? - java

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.

Related

How can I prevent the automatic decoding of RequestParam Strings in a Spring controller

I have an HTTP GET request controller endpoint where I take in a fileName as a query param and pass that on to another service. For this request the param the filename could include any sort of special characters and I would like to keep these values encoded when passing them on. 2 Characters that have been causing issues are spaces (%20) and +(%2B).
How can I keep these characters encoded in the request params.
So far I have tried using the #RequestParam annotation as well as retrieving the params via HttpServletRequest.getParameterValues(String) but both return the decoded values as spaces.
Any help is appreciated thanks!
Yes, these are automatically decoded by the servlet API. You should be able to re-encode them -
encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8);
I found out that I could get the actual value passed in by using the HttpServletRequest.getQueryString() method. Parsing this query string I was able to get the un-decoded version of the fileName being passed in. I hope this helps someone in the future.

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

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.

Encode URL query parameters

How can I encode URL query parameter values? I need to replace spaces with %20, accents, non-ASCII characters etc.
I tried to use URLEncoder but it also encodes / character and if I give a string encoded with URLEncoder to the URL constructor I get a MalformedURLException (no protocol).
URLEncoder has a very misleading name. It is according to the Javadocs used encode form parameters using MIME type application/x-www-form-urlencoded.
With this said it can be used to encode e.g., query parameters. For instance if a parameter looks like &/?# its encoded equivalent can be used as:
String url = "http://host.com/?key=" + URLEncoder.encode("&/?#");
Unless you have those special needs the URL javadocs suggests using new URI(..).toURL which performs URI encoding according to RFC2396.
The recommended way to manage the encoding and decoding of URLs is to use URI
The following sample
new URI("http", "host.com", "/path/", "key=| ?/#ä", "fragment").toURL();
produces the result http://host.com/path/?key=%7C%20?/%23ä#fragment. Note how characters such as ?&/ are not encoded.
For further information, see the posts HTTP URL Address Encoding in Java or how to encode URL to avoid special characters in java.
EDIT
Since your input is a string URL, using one of the parameterized constructor of URI will not help you. Neither can you use new URI(strUrl) directly since it doesn't quote URL parameters.
So at this stage we must use a trick to get what you want:
public URL parseUrl(String s) throws Exception {
URL u = new URL(s);
return new URI(
u.getProtocol(),
u.getAuthority(),
u.getPath(),
u.getQuery(),
u.getRef()).
toURL();
}
Before you can use this routine you have to sanitize your string to ensure it represents an absolute URL. I see two approaches to this:
Guessing. Prepend http:// to the string unless it's already present.
Construct the URI from a context using new URL(URL context, String spec)
So what you're saying is that you want to encode part of your URL but not the whole thing. Sounds to me like you'll have to break it up into parts, pass the ones that you want encoded through the encoder, and re-assemble it to get your whole URL.

Categories