Why can't Google Maps static API handle my encoded URIs? - java

I'm trying to integrate some Google maps bits into my Java web app using the Google Maps static API. For the moment I'm just trying to get a map, any map. Their example:
http://maps.google.com/maps/api/staticmap?center=40.714728,-73.998672&zoom=12&size=400x400&sensor=false
works fine from my browser. However the Java HTTP client software I am using (the one from Apache's http components, version 4.0.2) insists that I encode my URIs, so I end up with this:
http://maps.google.com/maps/api/staticmap?center%3D40.714728%2C-73.998672%26zoom%3D12%26size%3D400x400%26sensor%3Dfalse
which doesn't work. I would happily not encode my URIs but the Apache client fails if I don't. So my question is how can I either:
persuade Apache's client to use the plain URI or
get the encoded URI into a form Google will accept
?

Only encode the parameters of the URI. Your first ?, then your = and your & shouldn't be URI encoded.
Your URI should be
http://maps.google.com/maps/api/staticmap?center=40.714728%2C-73.998672&zoom=12&size=400x400&sensor=false
The only URI-encoded character is %2C, the , between your coordinates.

As Pekka suggested you need to leave to & and = unencoded.
Your encoded url
http://maps.google.com/maps/api/staticmap?center%3D40.714728%2C-73.998672%26zoom%3D12%26size%3D400x400%26sensor%3Dfalse
vs unencoded & (%26) and = (%3D) (working)
http://maps.google.com/maps/api/staticmap?center=40.714728%2C-73.998672&zoom=12&size=400x400&sensor=false
Apache's HTTPComponents HTTP Client has a lot of interfaces with which you can build your request URL. To make sure that the proper parts of the URL are encoded I would suggest using this method:
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("center", "40.714728,-73.998672"));
qparams.add(new BasicNameValuePair("zoom", "12"));
qparams.add(new BasicNameValuePair("size", "400x400"));
qparams.add(new BasicNameValuePair("sensor", "false"));
URI uri = URIUtils.createURI("http", "maps.google.com", -1, "/maps/api/staticmap",
URLEncodedUtils.format(qparams, "UTF-8"), null);
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
More example http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html
API Docs http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/index.html

Related

Open non-http links in browser in java

I have an url in my app like "zoommtg://us04.zoom.com". I want to open it in browser by Intent. As it is not http or https, it can't be parsed by Uri.parse(url). Again if I try url="http://"+url; it works but deletes the ":" from "zoommtg://" resulting wrong url! I am using the solution of this Question
if it is working for https but not other requests, then you can try setting cleartexttraffic to true in your AndroidManifest.xml file.
Do tell if that fixes it. :)
zoommtg seems to be "custom protocol" declaration, which isn't resolveable by web browser, but if you are shure, that http(s) url version will work then just replace scheme
String url = "zoommtg://us04.zoom.com";
url = url.replaceFirst("zoommtg", "https")
if you really need to use unsecure http then you have to allow app to do such requests, see how to
btw. you still can use Uri class, it isn't limited to web protocols... check out some description of this structure
URI = scheme:[//authority]path[?query][#fragment]
you can parse your String to Uri and just replace scheme part
Uri.Builder builder = Uri.parse(url).buildUpon();
url = builder.scheme("https").build().toString();

How can I be sure that an HttpClient PostMethod contains UTF-8 strings in the parameters?

In our webapp, we have to send a POST request via HttpClient to an endpoint on our network, which will receive this and do some work with it. We are having trouble with character encoding, and I am having difficulties finding an answer to my question.
We have used the postMethod.getParams().setContentCharset("UTF-8") method when sending the request, but on the receiving end, it seems like the characters are still encoded in ISO 8859-1. I have determined this because when I inspect the String on the receiving side, it has garbage characters in it that go away once I follow the steps found at https://stackoverflow.com/a/16549329/1130549. Is there any extra steps I need to take on the sending end to ensure that I am actually writing characters in UTF-8 as expected? All we are doing now is using postMethod.addParameter(paramKey, paramValue) with native String objects.
Edit: Here is a very simple example of how we're sending the POST request. For what it's worth, the values are being taken from an XMLBeans object.
PostMethod postMethod = new PostMethod(url);
postMethod.getParams().setContentCharset("UTF-8");
postMethod.addParameter("key1", "value1");
postMethod.addParameter("key2", "value2");
HttpClient httpClient = new HttpClient();
int status = httpClient.executeMethod(postMethod);
EDIT
Simpler solution is to encode the value
postMethod.addParameter("key1", URLEncoder.encode("value1","UTF-8"));
To encode properly UTF-8, you can execute differently, using StringEntity and NameValuePair, e.g.:
try (CloseableHttpClient httpClient = HttpClients.custom().build()) {
URIBuilder uriBuilder = new URIBuilder(url);
HttpHost target = new HttpHost(uriBuilder.getHost(), uriBuilder.getPort(), uriBuilder.getScheme());
List<NameValuePair> nameValuePairs = new ArrayList<>();
nameValuePairs.add(new BasicNameValuePair("key1", "value1"));
nameValuePairs.add(new BasicNameValuePair("key2", "value2"));
String entityValue = URLEncodedUtils.format(nameValuePairs, StandardCharsets.UTF_8.name());
StringEntity entity = new StringEntity(entityValue, StandardCharsets.UTF_8.name());
post.setEntity(entity);
httpClient.execute(target, post);
First of all, you do need to make sure that the string that you are actually writing is encoded in UTF-8. I realized that you already know that but still double-check that it is so, as it would be the prime suspect of your problem. Also, I would recommend trying a much simpler HTTP client. Apache HTTP client (I believe that's the library that you are using) is an excellent library. But due to covering a very wide range of options it tends to be a bit bulky. So, or simple requests I would suggest a lightweight HTTP client that maybe not that comprehensive as Apache library but offers simplicity as a trade-off. Here how your code may look like:
private static void testHttpClient() {
HttpClient client = new HttpClient();
// client.setContentType("text/html; charset=utf-8");
client.setContentType("application/json; charset=utf-8");
client.setConnectionUrl("http://www.my-url.com");
String content = null;
try {
String myMessage = getMyMessage() // get the string that you want to send
content = client.sendHttpRequest(HttpMethod.POST, myMessage);
} catch (IOException e) {
content = client.getLastResponseMessage() + TextUtils.getStacktrace(e, false);
}
System.out.println(content);
}
It looks much more simple, I think. Also in the same library, there is another utility that allows you to convert any string in any language into a sequence of unicodes and vice-versa. This helped me numerous times to diagnose encoding thorny issues. For instance, if you see some gibberish symbols that could be a wrong display of a valid character or actual character loss. Here is an example of how it works:
result = "Hello World";
result = StringUnicodeEncoderDecoder.encodeStringToUnicodeSequence(result);
System.out.println(result);
result = StringUnicodeEncoderDecoder.decodeUnicodeSequenceToString(result);
System.out.println(result);
The output of this code is:
\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064
Hello World
That might help you to check if the string you passed is valid or not. The library is called MgntUtils and could be found at Maven Central or at Github It comes as maven artifact and with sources and Javadoc. Javadoc could be found separately here
Disclaimer: The MgntUtils library is written by me

How to set username and password using RESTEasy client builder?

I have a url which needs authentication (like a browser pop up appears asking username and password.)
Generally, we can use the following format to achieve this:
http://username:password#url.com
Using RESTEasy client builder
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://url.com");
How to achieve it without having to construct the http://username:password#url.com myself? I've seen if there are any methods which I could use to set it with no luck. Also I'm not sure how these credentials are passed, headers, cookies etc..
Looks like Basic Authentication. If that's the case, you just need to set the Authorization header to Basic base64encode(username:password).
For example:
String credentials = "username:password"
String base64encoded = Base64.getEncoder().encodeToString(credentials.getBytes());
Response response = target.request()
.header(HttpHeaders.AUTHORIZATION, "Basic " + base64encoded)....
The Base64 class I used is from Java 8. If you're not using Java 8, there are libraries that have Base64 support. Prior to Java 8, there's a com.sun internal Base64 class, but it's advised not to use those.
If you just want to run a quick test (and don't have Java 8 or don't want to go looking for a lib), you can go to this site and just type in your username:password and encode it, then just copy and paste to your code.
For example:
base64encode(username:password) == dXNlcm5hbWU6cGFzc3dvcmQ=

"Illegal Characters" in URL for HttpGet in Android get double-encoded

I am trying to find a solution to this the whole evening now...
I write an app which requests data from a web server. The Server answers in JSON format.
Everything works well except when I enter a umlaut like ä into my App.
In the following I assume the request URL is http://example.com/?q= and I am searching for "Jäger"
The correct call would then be h++p://example.com/?q=J%C3%A4ger
(Sorry for plus-signs but the spam protection doesnt let me post it correctly.)
So my problem is now:
When I give my URL String encoded or unencoded over to HttpGet it will always result in a doublee-encoded URL.
The Request to my Server is then http://example.com/?q=J%25C3%25A4ger (It encodes the percent signs)
which leads to the server searching in database for J%C3%A4ger what is obviously wrong.
So my question is how can I achive that if the user enters "Jäger" my app calls the correctly encoded URL?
Thanks for any help!
Here is the currently used code... Ist probably the worst possible idea I had...
URI url = new URI("http", "//example.com/?q=" + ((EditText)findViewById(R.id.input)).getText().toString(), null);
Log.v("MyLogTag", "API Request: " + url);
HttpGet httpGetRequest = new HttpGet(url);
// Execute the request in the client
HttpResponse httpResponse;
httpResponse = defaultClient.execute(httpGetRequest);
Update: Sorry, HttpParams isn't meant for request parameters but for configuring HttpClient.
On Android, you might want to use Uri.Builder, like suggested in this other SO answer:
Uri uri = new Uri.Builder()
.scheme("http")
.authority("example.com")
.path("someservlet")
.appendQueryParameter("param1", foo)
.appendQueryParameter("param2", bar)
.build();
HttpGet request = new HttpGet(uri.toString());
// This looks very tempting but does NOT set request parameters
// but just HttpClient configuration parameters:
// HttpParams params = new BasicHttpParams();
// params.setParameter("q", query);
// request.setParams(params);
HttpResponse response = defaultClient.execute(request);
String json = EntityUtils.toString(response.getEntity());
Outside of Android, your best bet is building the query string manually (with all the encoding hassles) or finding something similar to Android's Uri.Builder.

Apache HttpGet url encoding problem (plus sign, +)

I'm sending a GET request with HttpClient but the + is not encoded.
1.
If I pass the query parameter string unencoded like this
URI uri = new URI(scheme, host, path, query, null);
HttpGet get = new HttpGet(uri);
Then the + sign is not encoded and it is received as a space on the server. The rest of the url is encoded fine.
2.If I encode the parameters in the query string like this
param = URLEncoder.encode(param,"UTF-8");
Then I get a bunch of weird symbols on the server, probably because the url has been encoded twice.
3.If I only replace the + with %B2 like this
query = query.replaceAll("\\+","%B2");
Then %B2 is encoded when the GET is executed by HttpClient
How can I properly encode Get parameters with Apache HttpClient and make sure the + is encoded as well?
Ok, the solution was that instead of creating the URI like this
URI uri = new URI(scheme, host, path, query, null);
One should create it like this
URIUtils.createURI(scheme, host, -1, path, query, null);
The purpose of the URIUtils class is
A collection of utilities for URIs, to workaround bugs within the
class
no comment........
When you build the query string, use URLEncoder.encode(paramValue, "UTF-8") for each parameter value. Then when you send the request, use URLDecoder.decode(paramValue, "UTF-8") and the "weird symbols" will be decoded.

Categories