I want to integrate MailChimp API in my java project. When I call Rest call using HttpURLConnection class, it responds with 401 code.
Here is my code:
URL url = new URL("https://us13.api.mailchimp.com/3.0/lists");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "apikey <my-key>");
String input = "<json data>";
OutputStream os = conn.getOutputStream();
//os.write(input.getBytes());
os.flush();
if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
I will suggest using Apache Commons Codec package for encoding.
It support various formats such as Base64 and Hexadecimal.
Earlier I was also facing the same issue. I am sharing the code that I used in my application for authenticating to Mailchimp API v-3.0
//basic imports
import org.apache.commons.codec.binary.Base64;
.
.
.
//URL to access and Mailchimp API key
String url = "https://us9.api.mailchimp.com/3.0/lists/";
//mailchimp API key
String apikey = xxxxxxxxxxxxxxxxxxxxxxxxxxx
// Authentication PART
String name = "Anything over here!";
String password = apikey; //Mailchimp API key
String authString = name + ":" + password;
byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
String authStringEnc = new String(authEncBytes);
URL urlConnector = new URL(url);
HttpURLConnection httpConnection = (HttpURLConnection) urlConnector.openConnection();
httpConnection.setRequestMethod("GET");
httpConnection.setDoOutput(true);
httpConnection.setDoInput(true);
httpConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
httpConnection.setRequestProperty("Accept", "application/json");
httpConnection.setRequestProperty("Authorization", "Basic " + authStringEnc);
InputStream is1 = httpConnection.getInputStream();
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(is1, "utf-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
Now you can use StringBuilder Object sb to parse the output as required
Hope it resolves your issue :)
HTTP 401 response code means "not authorized".
You didn't set or pass your credentials properly. Is the certificate from the client set up? Here's an example of an HTTPS client.
HTTP 401 simply means you're not Authorized to send this request.
you can set username any string (the MailChimp docs suggest using anystring as a username) and your API key as a password.
In case of Postman request, you can set under the Authorization tab choose Basic Auth to set username and password. Below image shows the same.
More info about Adding/ Getting Members to/ from a Mailing List on MailChimp API 3.0, I find this article very useful.
Related
I am using Quickblox REST APIs. When i am trying to run from POSTMAN , it is giving me proper output. but , when i am using it through my java code. It is showing me below error :
auth_key is required
Here is my java code :
URL url = new URL("https://api.quickblox.com/session.json");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
String current_date = dateFormat.format(cal.getTime());
Date newdt = dateFormat.parse(current_date);
long unixTime = newdt.getTime() / 1000;
String nonce = randomString(5);
String message ="application_id=XXXXX&auth_key=XXXXX&nonce=xxxxtimestamp=xxxx";
JSONObject arrayElement = new JSONObject();
arrayElement.put("application_id", "xxxxxx");
arrayElement.put("auth_key", "xxxxxxx");
arrayElement.put("nonce", nonce);
arrayElement.put("timestamp", unixTime);
arrayElement.put("signature", hmacDigest(message, secret, "HmacSHA1"));
conn.setRequestProperty("data", arrayElement.toJSONString());
conn.connect();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
HashMap hmdata = new HashMap();
while ((inputLine = in.readLine()) != null) {
hmdata.put("data", inputLine);
}
in.close();
Can anybody help me to resolve this error?
If you send as json then add the following header:
conn.setRequestProperty("Content-Type", "application/json");
because the server does not understand in what format you send the request's payload
I try to update my DDNS (No-IP) in a android client.
I make a request to the following URL.(Discription)
http://username:password#dynupdate.no-ip.com/nic/update?hostname=mytest.testdomain.com&myip=1.2.3.4
When i am using my webbrowser, everything works fine.
"good [ip-address]"
But my android client only gets the response "nochange"
URL url = new URL("http://" + USERNAME + ":" + PASSWORD + "#dynupdate.no-ip.com/nic/update?hostname=" + HOSTNAME + "&myip=" + IP_ADDRESS);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
int i = conn.getResponseCode();
stringBuilder = new StringBuilder();
bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line + "\n");
}
From http://www.noip.com/integrate/request:
When making an update it is important that your http request include an HTTP User-Agent to help No-IP identify different clients that access the system. Clients that do not supply a User-Agent risk being blocked from the system.
So you'll probably need to set the UserAgent as described on that page, specifically, something like this (replace these details with the datails of your own app):
User-Agent: NameOfUpdateProgram/VersionNumber maintainercontact#domain.com
See here for details of how to set the UserAgent when using HttpUrlConnection, something like this should work:
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
hc.setRequestProperty("User-Agent", "NameOfUpdateProgram/VersionNumber maintainercontact#domain.com");
I need to send a post request to url which is formed as follows:
www.abc.com/service/postsomething?data={'name':'rikesh'}&id=45
Using HttpPost client in java, how can post request to such query strings
I could connect from javascript easily through ajax but from java client, it's failing.
(I know sending querystring in post request is stupid idea. Since I am connecting to someone else's server I cannot not change the way it is)
Here is one way to send JSON in a POST request using Java (without Apache libraries). You might find this helpful:
//init
String json = "{\"name\":\"rikesh\"}";
String requestString = "http://www.example.com/service/postsomething?id=45";
//send request
URL url = new URL(requestString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
OutputStream os = conn.getOutputStream();
os.write(json.getBytes());
os.flush();
int responseCode = conn.getResponseCode();
//get result if there is one
if(responseCode == 200) //HTTP 200: Response OK
{
String result = "";
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String output;
while((output = br.readLine()) != null)
{
result += output;
}
System.out.println("Response message: " + result);
}
I am calling a REST Web Service with HttpURLConnection like so (this is not the actual URL and credentials, of course I changed the values before posting on a public forum)...
String uri = "http://99.82.36.238:8443/media/crowd?";
String query = String.format("office_code=%s&content_type_code=%s",
URLEncoder.encode("USA"), URLEncoder.encode("SGV"));
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "text/xml");
String username = "userNewbie";
String password = "password";
conn.setRequestProperty("Authorization", CredentialsEncoder.userNamePasswordBase64(username,password));
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode() + " because " + conn.getResponseMessage());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
The problem is that the service that I am calling does not work in a hand-shake mode. Meaning it needs me to send the creds the first time the request is made, rather than making the request and getting the 403 and then sending the cred.
Can anyone suggest how to modify the above code to meet that requirement?
Thanks.
What is the best way to use preemptive basic http authentication using HttpUrlConnection. (Assume for now I can't use HttpClient).
EDIT for clarification: I'm setting the un/pw correctly in the request header using Base64 encoding. Are there any additional flags or properties that need to be set, or is the fact that I'm setting the basic auth headers for the request all that is needed for preemptive basic auth?
If you are using Java 8 or later, java.util.Base64 is usable:
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
String encoded = Base64.getEncoder().encodeToString((username+":"+password).getBytes(StandardCharsets.UTF_8)); //Java 8
connection.setRequestProperty("Authorization", "Basic "+encoded);
Then use the connection as normal.
If you're using Java 7 or lower, you'll need a method to encode a String to Base64, such as:
byte[] message = (username+":"+password).getBytes("UTF-8");
String encoded = javax.xml.bind.DatatypeConverter.printBase64Binary(message);
Yes, that's all you have to do in order to use Basic Auth. The code above to set the Request Property should be done immediately after opening the connection and before getting the Input or Output streams.
Incidentally, in case someone else runs into the same, the android problem, is also present if you use org.apache.commons.codec.binary.Base64 and do Base64.encodeBase64String(). You need to do Base64.encodeBase64() and get a byte[] then construct the string.
It caught me offguard entirely that the results would be different for the line ending between those two methods.
You can use java.net.Authenticator to configure basic auth. globally for every request send by your application, see :
http://docs.oracle.com/javase/7/docs/technotes/guides/net/http-auth.html
http://developer.android.com/reference/java/net/Authenticator.html#getPasswordAuthentication()
you need to do this just copy paste it be happy
HttpURLConnection urlConnection;
String url;
// String data = json;
String result = null;
try {
String username ="danish.hussain#gmail.com";
String password = "12345678";
String auth =new String(username + ":" + password);
byte[] data1 = auth.getBytes(UTF_8);
String base64 = Base64.encodeToString(data1, Base64.NO_WRAP);
//Connect
urlConnection = (HttpURLConnection) ((new URL(urlBasePath).openConnection()));
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Authorization", "Basic "+base64);
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10000);
urlConnection.connect();
JSONObject obj = new JSONObject();
obj.put("MobileNumber", "+97333746934");
obj.put("EmailAddress", "danish.hussain#dhl.com");
obj.put("FirstName", "Danish");
obj.put("LastName", "Hussain");
obj.put("Country", "BH");
obj.put("Language", "EN");
String data = obj.toString();
//Write
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
writer.write(data);
writer.close();
outputStream.close();
int responseCode=urlConnection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
//Read
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
result = sb.toString();
}else {
// return new String("false : "+responseCode);
new String("false : "+responseCode);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
I was having this problem too.
And Now I have solved this problem.
My code is :
URL url = new URL(stringUrl);
String authStr = "MyAPIKey"+":"+"Password";
System.out.println("Original String is " + authStr);
// encode data on your side using BASE64
byte[] bytesEncoded = Base64.encodeBase64(authStr .getBytes());
String authEncoded = new String(bytesEncoded);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", "Basic "+authEncoded);
It may help many others.
Best of luck.
Regarding the Base64 encoding problem, I found this library: http://sourceforge.net/projects/migbase64/
I have not fully vetted it but I am using it for the Basic Authentication solution shown above (as well as for image encoding/decoding), and it works well. It provides a parameter for whether or not to include the newline.