How to let UriBuilder build an URI with decoded hash character? - java

I try to generate following uri
//host:port/name/#/name/name
with jersey URI Builder. The Problem is that the uri builder decode the hash character.
Does anyone how to build the given URI?
Thats what I have:
final URI build = uriInfo.getBaseUriBuilder().path("..").path("#").path("/clients/asd/").build();

# is not a valid character in a URI path; # and what follows it is actually a URI fragment.
What you need to do is therefore:
final URI build = uriInfo.getBaseUriBuilder().path("..")
.fragment("/clients/asd/").build();
(note: I don't use Jersey, actually; I looked up the javadoc here, as I suppose this is the same)

For me, this is what worked:
final URI build = UriBuilder.fromUri("{arg1}").fragment("{arg2}").buildFromEncoded("../","/clients/asd/");
Using .path("..").fragment("/clients/asd/").build() would generate
..#%2Fclients%2Fasd

Related

Java - how to build an URI using a query string that is already escaped?

LATER EDIT: not same problem as the suggested answer. In my case, I need to build the URI, relying on the fact that the original query string is not modified.
I have a String (coming from a request query String) that is already correctly escaped, like param1=%2Ffolder1%2Ffolder2%2Ffolder%26name%202&param2=9481dxcv234.
The decoded value of param1 is /folder1/folder2/folder&name 2. Obviously, I cannot unescape that String (because of the & char in this value)...
I need to build an URI which has that original string as query value.
I tried using org.apache.http.client.utils.URIBuilder but could not get it to work: if I provide the original String to the URI(... constructor, the resulting URL is double-escaped, like param1=%252Ffolder1%252Ffolder2%252Ffolder%2526name%25202&param2=9481dxcv234.
Can I somehow do what I need ? To build an URI by passing the query string already escaped and leave it unchanged ?
Thanks.
I think, the simplest way is unescape it first.
Then you can work with url as usualy.
You could use org.springframework.web.util.UriComponentsBuilder:
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
UriComponents components = builder.build(true); //EDIT: pass true when the URI was fully encoded already.
MultiValueMap<String, String> parameters = components.getQueryParams();
parameters.get("param1") //"%2Ffolder1%2Ffolder2%2Ffolder%26name%202"
You can then URLDecode to get what you need.
Edit:
Since you appear to be using Apache HttpClient,
List<NameValuePair> params = org.apache.http.client.utils.URLEncodedUtils.parse(new URI(url), Charset.forName("UTF-8"));
params.get("param1") //"/folder1/folder2/folder&name 2"

How to create URI/URL using MultiValueMap for parameters?

I have multimap of parameters, like this:
{
keyA: ["2+4", "4+8"],
keyB: ["Some words with special chars #ąęć"]
}
as spring MultiValueMap and I'm trying to create URI from this, I tried to use
URI uri = UriComponentsBuilder
.fromUriString(baseUri).path(somePath)
.queryParams(params.getQueryParameters())
.build().encode().toUri();
It seems to work for special chars, but it still does think that + sign is a space, I want to encode all parameters, is there existing solution for this other than manually encoding each value?
Assuming you are on Spring 5.0, this is discussed in detail in [SPR-16860] Spring is inconsistent in the encoding/decoding of URLs issue. More or less it boils down to this:
From an RFC 3986 perspecitve, "+" is a legal character. By default the RestTemplate leaves it as is.
UriComponents.encode() will leave + sign as is, to stay complaint with the RFC 3986. If you need it encoded one suggestion is to use UriUtils:
String value = "A+B=C";
value = UriUtils.encode(value, StandardCharsets.UTF_8); // A%2BB%3DC
URI uri = UriComponentsBuilder.newInstance()
.queryParam("test", value)
.build(true)
.toUri();
There is a change coming 5.0.8 as part of [SPR-17039] Support stricter encoding of URI variables in UriComponents which introduces new UriComponentsBuilder.encode() method. It should be enough to move encode() before build() in your example:
URI uri = UriComponentsBuilder
.fromUriString(baseUri).path(somePath)
.queryParams(params.getQueryParameters())
.encode()
.build()
.toUri();

When passing ampersand in the URI for file: schemes into ProducerTemplate.sendBodyAndHeader() it fails

When using ProducerTemplate.sendBodyAndHeader() to send a file using the "file" scheme to its destination, and the file path in the URI contains ampersands, it fails to deliver the file with the following errors.
org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint:
file:///c%7C/IMM_SAN/Marketing/f77333bd-f96f-4873-b846-2f1dc5531a5a/2596/PB&J%20Generic%2007064782/transcoded/21726
due to: Failed to resolve endpoint:
file:///c%7C/IMM_SAN/Marketing/f77333bd-f96f-4873-b846-2f1dc5531a5a/25964/PB&J%20Generic%2007064782/transcoded/21726
due to: Invalid uri syntax: no ? marker however the uri has & parameter separators. Check the uri if its missing a ? marker.
Spending a few days trying the different overloads to send the file send(), sendBody(), sendBodyAndHeader() and even sendBodyAndHeaders().
I tried to UrlEncoder.encode() it before hand and of course a no go.
I even debugged the URISupport.normalizeUri(String uri) from the camel-core source and discovered something interesting. Apparently no amount of encoding will do me any good before sending the body and header because it appears to be doing its own encoding and it appears to be totally incorrect. I think this is a bug in sendBodyAndHeader(). It encodes the ampersand back into the URI before sending it. This is bad. Why are we doing that? We have an application that reads files from one department and are written to a share and another system automatically picking those file up and delivering it when processing on the file is finished.
See below camel URISupport.normalizeUri(String uri) method is encoding the URI here and this puts the ampersand back into the file path.
URI u = new URI(UnsafeUriCharactersEncoder.encode(uri));
So you see no amount of preprocessing on the file path in the URI is going to work at all because sendBodyAndHeader is going to do whatever it feels like doing. I would like to add a new overload to this API to turn off normalization and just send the URI as is. But wanted to check here to see if anybody has any less drastic options. Please note this is a problem when ampersands are in the URI path for file schemes.
ProducerTemplate prod = exchange.getContext().createProducerTemplate();
destPath = destPath.replace(':', '|');
destPath = destPath.replaceAll("\\\\", "/");
destPath = destPath.replaceAll("&", "%26"); // replace the ampersand
String query = "file:///" + destPath;
prod.sendBodyAndHeader(query, exchange.getIn().getBody(), Exchange.FILE_NAME, destFileName);
Use the CamelFileName header to avoid messing up the endpoint URI with the reserved character & if you really need that character in the file path.
This example would put a file into c:\a&b
public void sendAnyFile(Exchange e){
ProducerTemplate pt = getContext().createProducerTemplate();
pt.sendBodyAndHeader("file:///c:/",e.getIn().getBody(String.class), "CamelFileName", "a&b/hej.txt");
}

Encode URL parameters using Java

I want to encode part of URL paramter in JAVA
http://statebuild-dev.com/iit-title/size.xml?id=(102T OR 140T)
to
http://statebuild-dev.com/iit-title/size.xml?id=(102%20OR%20140)
have tried using URI to encode but it also encodes ? which I do not want. In the URL I want to encode the part after '='
URI uri = new URI("http",
"statebuild-dev.com/iit-title", "/size.xml?id=(102 OR 140)", null);
//URL url = uri.toURL();
System.out.println(uri.toString());
System.out.println(url1);
Thank You
you want to use URLEncoder to encode each query parameter before adding to the url, e.g.:
String encodedValue = URLEncoder.encode("(102 OR 140)", "UTF-8");
This answer has a good discussion of encoding the various parts of a URI/URL. You're on the right track, but your specific problem is that you have the various parts of the URI wrong. You need to use the multi-part constructor that takes an authority, path, query, and fragment:
URI uri = new URI("http", "statebuild-dev.com", "/iit-title/size.xml", "id=(102 or 104)", null);
System.out.println(uri.toString());
System.out.println(uri.toASCIIString());
You used the wrong constructor.
Try this:
URI uri = new URI("http","statebuild-dev.com", "/iit-title/size.xml", "id=(102 OR 140)", null);
See also java.net.URLEncoder
The java.net.URI class can help; in the documentation of URL you find
Note, the URI class does perform escaping of its component fields in certain circumstances. The recommended way to manage the encoding and decoding of URLs is to use URI
Check this thread.

How to deal with URI and Uri in java?

I'm using a library that requires me to pass an Uri object as parameter.
Currently I'm doing this:
File file = new File(someFileDir, "test.pdf");
someObject.someFunction(file.toURI());
Note that the File object has the function toURI(). It returns an URI object.
Now my problem is that the function I call needs a Uri parameter, but it's complaining that I passed a URI object.
Aren't these things exactly the same? How can I output an Uri object? Or how do I convert URI to Uri?
Just deal with it as a string, It's easier.
you can use Uri.Builder() to create a Uri !
For you information, URI seem to come from the JAVA language (java.net.URI), and Uri, from the Android SDK specificaly (android.net.Uri). So I would advise you to use the "Uri" class...

Categories

Resources