Twitter call request - java

I have problem with my source code for twitter request. Response that is returned from twitter is blank String. Can you advice where can be problem?
I have registered my app normally on dev.twitter.com. It is called Reach Count.
This code is brought from this tutorial: http://www.coderslexicon.com/demo-of-twitter-application-only-oauth-authentication-using-java/
package count_reach_twitter;
//import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import javax.net.ssl.HttpsURLConnection;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONArray;
import org.json.JSONObject;
/**
*
* #author Martin
*/
public class TwitterCall {
// Encodes the consumer key and secret to create the basic authorization key
private static String encodeKeys(String consumerKey, String consumerSecret) {
try {
String encodedConsumerKey = URLEncoder.encode(consumerKey, "UTF-8");
String encodedConsumerSecret = URLEncoder.encode(consumerSecret, "UTF-8");
String fullKey = encodedConsumerKey + ":" + encodedConsumerSecret;
byte[] encodedBytes = Base64.encodeBase64(fullKey.getBytes());
return new String(encodedBytes);
}
catch (UnsupportedEncodingException e) {
return new String();
}
}
// Writes a request to a connection
private static boolean writeRequest(HttpsURLConnection connection, String textBody) {
try {
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
wr.write(textBody);
wr.flush();
wr.close();
return true;
}
catch (IOException e) { return false; }
}
// Reads a response for a given connection and returns it as a string.
private static String readResponse(HttpsURLConnection connection) {
try {
StringBuilder str = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = "";
while((line = br.readLine()) != null) {
str.append(line + System.getProperty("line.separator"));
}
return str.toString();
}
catch (IOException e) { return new String(); }
}
// Constructs the request for requesting a bearer token and returns that token as a string
private static String requestBearerToken(String endPointUrl) throws IOException {
HttpsURLConnection connection = null;
String encodedCredentials = encodeKeys("My customer key","My customer secret key");
try {
URL url = new URL(endPointUrl);
connection = (HttpsURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Host", "api.twitter.com");
connection.setRequestProperty("User-Agent", "Reach Count");
connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
connection.setRequestProperty("Content-Length", "29");
connection.setUseCaches(false);
//writeRequest(connection, "grant_type=client_credentials");
// Parse the JSON response into a JSON mapped object to fetch fields from.
System.out.println("Response: " + readResponse(connection));
System.out.println("End");
JSONObject obj = new JSONObject(readResponse(connection)); //(JSONObject)JSONValue.parse(readResponse(connection));
//obj.
if (obj != null) {
String tokenType = (String)obj.get("token_type");
String token = (String)obj.get("access_token");
return ((tokenType.equals("bearer")) && (token != null)) ? token : "";
}
return new String();
}
catch (MalformedURLException e) {
throw new IOException("Invalid endpoint URL specified.", e);
}
finally {
if (connection != null) {
connection.disconnect();
}
}
}
// Fetches the first tweet from a given user's timeline
public static String fetchTimelineTweet(String endPointUrl) throws IOException {
HttpsURLConnection connection = null;
try {
URL url = new URL(endPointUrl);
connection = (HttpsURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("GET");
connection.setRequestProperty("Host", "api.twitter.com");
connection.setRequestProperty("User-Agent", "Reach Count");
connection.setRequestProperty("Authorization", "Bearer " + requestBearerToken("https://api.twitter.com/oauth2/token"));
connection.setUseCaches(false);
// Parse the JSON response into a JSON mapped object to fetch fields from.
JSONArray obj = new JSONArray(readResponse(connection));//(JSONArray)JSONValue.parse(readResponse(connection));
if (obj != null) {
String tweet = ((JSONObject)obj.get(0)).get("text").toString();
return (tweet != null) ? tweet : "";
}
return new String();
}
catch (MalformedURLException e) {
throw new IOException("Invalid endpoint URL specified.", e);
}
finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
Main function is calling next method:
System.out.println(TwitterCall.fetchTimelineTweet("https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=Dj_Fedy&count=50"));
Thank you

I'm not sure why your code gets a 403 from Twitter. I can think of two things:
According to the bottom of Application-only authentication doc, a 403 response is given when you use a bearer token on endpoint which doesn't support application-only auth. I cannot find whether a GET on statuses/user_timeline is allowed with application-only auth.
According to the GET statuses/user_timeline doc, you can only request tweets for a protected user when the authenticated user either "owns" the timeline or is an approved follower of the owner. I'm not sure whether this is the case for you.

Related

Send HTTP POST reqeust with Graphql query form java

I want to create a ticket on monday.com. I wrote HTTP method which makes POST call on specific monday server and as a parameter I'm passing graphql query. but unfortunately with no success, I think I'm passing query parameters in a wrong way, but I can't figure what exactly I'm doing wrong.
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class Monday {
static int id = 1249501957;
static String token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
static String query = "mutation {\n"
+ " create_item(item_name:\"heyyyyyyy\", board_id:" + id + "){\n"
+ " id\n"
+ " }\n"
+ "}";
static String targetURL = "https://levank707.monday.com/projects";
public static void main(String[] args) throws Exception {
executePost(targetURL,query);
}
public static String executePost(String targetURL, String query) {
HttpURLConnection connection = null;
try {
//Create connection
URL url = new URL(targetURL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/graphql");
connection.setRequestProperty("Content-Length",
Integer.toString(query.getBytes().length));
connection.setRequestProperty("Authorization",token );
connection.setUseCaches(false);
connection.setDoOutput(true);
//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream());
wr.writeBytes(query);
wr.close();
//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+
String line;
while ((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}}

Getting Http code 400 while calling MS Graph API from console based java application to read excel file stored in onedrive

I am trying to read an Excel file stored in my onedrive through microsoft graph api . For this in this console based application i provided my tenant id , client secret & client id which i generated through Microsoft azure console .Through post api i passed those information with the authentication URL but whenever i am running the code i am getting status code 400 which means bad request. Why it returning 400 status code ? Any error in my approach ?
Code :
Authenticator.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.microsoft.graph.authentication.IAuthenticationProvider;
import com.microsoft.graph.http.IHttpRequest;
public class Authenticator {
public final static String clientId = "XXXXXXXXXXXX";
public final static String clientSecret = "XXXXXXXXXXXXXX";
public final static String tenant = "XXXXXXXXXXXXXX";
private String grantType = "client_credentials";
private String tokenEndpoint = "https://login.microsoftonline.com/" +tenant + "/oauth2/v2.0/token";
private String scope = "https%3A%2F%2Fgraph.microsoft.com%2F.default";
private String accessToken = null;
protected IAuthenticationProvider authenticationProvider = null;
public Authenticator() { }
public IAuthenticationProvider getAuthenticationProvider()
{
if (authenticationProvider == null) {
try {
System.out.println(accessToken);
accessToken = getAccessToken().replace("\"", "");
System.out.println(accessToken);
authenticationProvider = new IAuthenticationProvider() {
public void authenticateRequest(final IHttpRequest request) {
request.addHeader("Authorization",
"Bearer " + accessToken);
}
};
}
catch (Exception e)
{
throw new Error("Could not create authentication provider: " + e.getLocalizedMessage());
}
}
return authenticationProvider;
}
private String getAccessToken()
{
try {
URL url = new URL(tokenEndpoint);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
String line;
StringBuilder jsonString = new StringBuilder();
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setInstanceFollowRedirects(false);
conn.connect();
String secret = clientSecret.replace("+", "%2B").replace("=", "%3D").replace("/", "%2F");
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
String payload = String.format("grant_type=%1$s&scope=%2$s&client_id=%3$s&client_secret=%4$s",
grantType,
scope,
clientId,
secret);
writer.write(payload);
writer.close();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while((line = br.readLine()) != null){
jsonString.append(line);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
throw new Error("Error reading authorization response: " + e.getLocalizedMessage());
}
conn.disconnect();
JsonObject res = new GsonBuilder().create().fromJson(jsonString.toString(), JsonObject.class);
return res.get("access_token").toString().replaceAll("\"", "");
} catch (Exception e) {
throw new Error("Error retrieving access token: " + e.getLocalizedMessage());
}
}
}
ReadExcel.java
import com.microsoft.graph.authentication.IAuthenticationProvider;
import com.microsoft.graph.models.extensions.IGraphServiceClient;
import com.microsoft.graph.models.extensions.WorkbookRange;
import com.microsoft.graph.requests.extensions.GraphServiceClient;
public class ReadExcel {
public static IGraphServiceClient graphClient;
public static void main(String[] args) {
Authenticator authenticator = new Authenticator();
IAuthenticationProvider authenticationProvider = authenticator
.getAuthenticationProvider();
IGraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider( authenticationProvider ).buildClient();
WorkbookRange workbookRange = graphClient.me().drive().items("XXXXXXXXXX").workbook().worksheets("Sheet1")
.range("A1:B2")
.buildRequest()
.get();
}
}
Error :
java.io.IOException: Server returned HTTP response code: 400 for URL: https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/oauth2/v2.0/token
Example code to authenticate graph api will be highly appreciated. Thanks in advance.
Update-1:
Updated the code and Used "oauth2-oidc-sdk" for authentication. Updated my code as described in Micrsoft Graph tutorial sample code.
Github Link : https://github.com/microsoftgraph/console-java-connect-sample
But got this error -
{"error":"invalid_grant","error_description":"AADSTS9002313: Invalid request. Request is malformed or invalid.\r\nTrace ID: c77ba129-89ec-4869-993d-55475fab4800\r\nCorrelation ID: 34ce3c6b-b125-4c24-b57f-9716f320462c\r\nTimestamp: 2020-09-16 06:18:36Z","error_codes":[9002313],"timestamp":"2020-09-16 06:18:36Z","trace_id":"c77ba129-89ec-4869-993d-55475fab4800","correlation_id":"34ce3c6b-b125-4c24-b57f-9716f320462c","error_uri":"https://login.microsoftonline.com/error?code=9002313"}

Download file using REST API

I am trying to call a REST API using Java client.
The Rest API https://api.gdc.cancer.gov/data has files data.
When I append file name to the URL (https://api.gdc.cancer.gov/data/556e5e3f-0ab9-4b6c-aa62-c42f6a6cf20c) I can download the given file from using browser.
here filename is 556e5e3f-0ab9-4b6c-aa62-c42f6a6cf20c.
can you please let me know,How can i achieve in this JAVA. The code I am using.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class DownloadFilesAPI {
public DownloadFilesAPI() {
super();
}
public static String sendPostRequest(String requestUrl) {
StringBuffer jsonString = new StringBuffer();
try {
URL url = new URL(requestUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// connection.setRequestMethod("POST");
// connection.connect();
//Get the response status of the Rest API
// int responsecode = connection.getResponseCode();
//System.out.println("Response code is: " +responsecode);
//connection.getResponseMessage();
// System.out.println(connection.getResponseMessage());
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json");
// System.out.println(connection.getResponseMessage());
// System.out.println( JsonPath.from(requestUrl));
OutputStreamWriter writer = new
OutputStreamWriter(connection.getOutputStream());
writer.write(requestUrl);
writer.close();
/* BufferedReader br = new BufferedReader(new
InputStreamReader(connection.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
jsonString.append(line);
}
br.close(); */
connection.disconnect();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return jsonString.toString();
}
public static void main(String[] args) {
List<String> values = new ArrayList<>();
// values.add("556e5e3f-0ab9-4b6c-aa62-c42f6a6cf20c");
String requestUrl = "https://api.gdc.cancer.gov/data/556e5e3f-0ab9-4b6c-aa62-c42f6a6cf20c";
sendPostRequest(requestUrl);
}
private static String preparePayload(List<String> values) {
StringBuilder sb = new StringBuilder();
for (String value : values) {
sb.append("\"" + value + "\",");
}
String Requiredvalue = sb.toString().substring(0, sb.toString().length() - 1);
return "{ \"ids\":[" + Requiredvalue + "] } } }";
}
}
You can't just output a String since you are trying to download a pdf. If you simply want to download the File there is an easier method adapted from this answer:
String requestUrl = "https://api.gdc.cancer.gov/data/556e5e3f-0ab9-4b6c-aa62-c42f6a6cf20c";
URL url = new URL(requestUrl);
InputStream in = url.openStream();
Files.copy(in, Paths.get("your_filename.pdf"), StandardCopyOption.REPLACE_EXISTING);
in.close();
System.out.println("finished!");
I have tested it for the URL you provided and got the pdf File without problems.

Not getting result back from Flickr API using Java's HttpURLConnection

I'm having problems querying Flickr REST API for searching photos:
https://www.flickr.com/services/api/explore/flickr.photos.search
I'm writing a small test app in Android using HttpURLConnection and I do not want to use any frameworks (such as OkHttp etc.) as this is just simple learning exercise.
The problem that I am having is that although my HttpURLConnection returns a 200, there is no JSON response. But when I take the constructed REST URL from my logs, for example:
https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=API_KEY&tags=basketball&format=json&nojsoncallback=1&api_sig=API_SIG
and copypaste it to a browser, I can see proper JSON.
This is A snippet of the JSON that the browser returns:
{"photos":{"page":1,"pages":2614,"perpage":100,"total":"261380","photo":[{"id":"39168832065","owner":"23023080#N02","secret":"1fb9ee772a","server":"4615","farm":5,"title":"_MG_2714_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"26194325488","owner":"23023080#N02","secret":"3bc00e37ee","server":"4656","farm":5,"title":"_MG_2719_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"39168829925","owner":"23023080#N02","secret":"15580858ce","server":"4695","farm":5,"title":"_MG_2723_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"26194323798","owner":"23023080#N02","secret":"c5e445bd6e","server":"4743","farm":5,"title":"_MG_2727_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"39168828415","owner":"23023080#N02","secret":"89b54b28bc","server":"4648","farm":5,"title":"_MG_2729_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"26194322658","owner":"23023080#N02","secret":"7eff365389","server":"4648","farm":5,"title":"_MG_2732_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"39168826725","owner":"23023080#N02","secret":"2eda660b60","server":"4723","farm":5,"title":"_MG_2734_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"26194321108","owner":"23023080#N02","secret":"0c794e38a8","server":"4765","farm":5,"title":"_MG_2735_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"40034887842","owner":"23023080#N02","secret":"6269997f0f","server":"4755","farm":5,"title":"_MG_2737_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"26194319778","owner":"23023080#N02","secret":"32991c9151","server":"4763","farm":5,"title":"_MG_2739_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"26194319168","owner":"23023080#N02","secret":"4dd5555f5c","server":"4709","farm":5,"title":"_MG_2746_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"40034885802","owner":"23023080#N02","secret":"3f9c5031db","server":"4671","farm":5,"title":"_MG_2747_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"26194317818","owner":"23023080#N02","secret":"e20b503f8f","server":"4668","farm":5,"title":"_MG_2757_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"40067785161","owner":"23023080#N02","secret":"4ab87667fd","server":"4612","farm":5,"title":"_MG_2760_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"40034884132","owner":"23023080#N02","secret":"235b7dc32d","server":"4744","farm":5,"title":"_MG_2762_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"40067784231","owner":"23023080#N02","secret":"0bbae58322","server":"4622","farm":5,"title":"_MG_2763_edit","ispublic":1,"isfriend":0,"isfamily":0},{"id":"40034882942","owner":"23023080#N02","secret":"30345b6b7b","server":"4626","farm":5,"title":"_MG_2764_edit","ispublic":1,"isfriend":0,"isfamily":0},
Why is the code not getting/reading the JSON from connection's input stream?
package com.bing.ary.xyz;
import android.os.AsyncTask;
import android.util.Log;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.net.ssl.HttpsURLConnection;
import java.net.URL;
public class SearchFlickerAsync extends AsyncTask<String, Void, flikrPhotosResponse> {
private static final String TAG = "SearchFlickerAsync";
private String query;
public SearchFlickerAsync(String query) {
this.query = query;
}
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected flikrPhotosResponse doInBackground(String... query) {
Log.i(TAG,"doInBackground(), SearchFlickerAsync input param:"+query);
HttpsURLConnection httpURLConnection = null;
flikrPhotosResponse FlikrPhotosResponse = null;
JsonElement jsonElemnt = null;
JsonObject jsonObject = null;
String queryUrl = null;
StringBuilder queryBuilder = null;
try {
//create url string
queryBuilder = new StringBuilder();
queryBuilder.append(flickerApi.baseUrl);
queryBuilder.append(flickerApi.searchFlicker);
queryBuilder.append(flickerApi.flickrQuery_key + flickerApi.Key);
queryBuilder.append(flickerApi.flickrQuery_tag);
queryBuilder.append(this.query);
queryBuilder.append("&format=json");
queryBuilder.append("&nojsoncallback=1&api_sig=be97f5275f5a128fbe69dc2cde2560b9");
//instantiate url for connection
URL url = new URL(queryBuilder.toString());
httpURLConnection = (HttpsURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setUseCaches(false);
httpURLConnection.setAllowUserInteraction(false);
httpURLConnection.setRequestProperty("Content-length", "0");
httpURLConnection.connect();
//no authorization token needed public API httpURLConnection.setRequestProperty("Authorization", "");
Log.i(TAG,"doInBackground(), http request:"+url.toString());
int status = httpURLConnection.getResponseCode();
switch (status) {
case 200:
case 201:
Log.i(TAG,"doInBackground(), http response status:"+status);
BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
Log.i(TAG,"doInBackground(), http response line:"+line);
jsonElemnt = new JsonParser().parse(sb.toString());
jsonObject = jsonElemnt.getAsJsonObject();
/*Further parse & instantiate FlikrPhotosResponse = */
br.close();
break;
//TODO: ERRORS https://www.flickr.com/services/api/flickr.groups.search.html
default:
Log.e(TAG,"doInBackground(), http response error status:"+status);
//TODO: handle error responses
break;
}
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (httpURLConnection != null) {
try {
httpURLConnection.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
return FlikrPhotosResponse;
}//end doInBackgroud
protected void onPostExecute(flikrPhotosResponse FlikrPhotosResponse) {
Log.i(TAG,"onPostExecute(), FlikrPhotosResponse:"+FlikrPhotosResponse);
}
}//end class
Relevant logs there is no errpr or exception:
02-04 13:24:12.037 3750-4270/com.bing.ary.skywelltest I/SearchFlickerAsync: doInBackground(), http request:https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=37ae86d629a2e4a62917253419cb9e94&tags=basketball&format=json&nojsoncallback=1&api_sig=be97f5275f5a128fbe69dc2cde2560b9
02-04 13:24:12.220 3750-4270/com.bing.ary.skywelltest I/SearchFlickerAsync: doInBackground(), http response status:200
02-04 13:24:12.221 3750-4270/com.bing.ary.skywelltest I/SearchFlickerAsync: doInBackground(), http response line:null
I also
You're logging the wrong thing:
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
Log.i(TAG,"doInBackground(), http response line:"+line);
Of course line is null at this point. That's why the loop terminated. You should be logging sb.toString().
NB:
You don't need any of the following:
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Content-length", "0");
httpURLConnection.connect();
The numerous claims in comments that you need to use HttpsURLConnection are not correct. Using HttpURLConnection is perfectly valid even if the URL is an HTTPS one, as long as you don't need the extra methods of HttpsURLConnection, as HttpsURLConnection extends HttpURLConnection.

How do I make an http request using cookies on Android?

I'd like to make an http request to a remote server while properly handling cookies (eg. storing cookies sent by the server, and sending those cookies when I make subsequent requests). It'd be nice to preserve any and all cookies, but really the only one I care about is the session cookie.
With java.net, it appears that the preferred way to do this is using java.net.CookieHandler (abstract base class) and java.net.CookieManager (concrete implementation). Android has java.net.CookieHandler, but it does not seem to have java.net.CookieManager.
I could code it all by hand by inspecting http headers, but it seems like there must be an easier way.
What is the proper way to make http requests on Android while preserving cookies?
It turns out that Google Android ships with Apache HttpClient 4.0, and I was able to figure out how to do it using the "Form based logon" example in the HttpClient docs:
https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientFormLogin.java
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
/**
* A example that demonstrates how HttpClient APIs can be used to perform
* form-based logon.
*/
public class ClientFormLogin {
public static void main(String[] args) throws Exception {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("https://portal.sun.com/portal/dt");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println("Login form get: " + response.getStatusLine());
if (entity != null) {
entity.consumeContent();
}
System.out.println("Initial set of cookies:");
List<Cookie> cookies = httpclient.getCookieStore().getCookies();
if (cookies.isEmpty()) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.size(); i++) {
System.out.println("- " + cookies.get(i).toString());
}
}
HttpPost httpost = new HttpPost("https://portal.sun.com/amserver/UI/Login?" +
"org=self_registered_users&" +
"goto=/portal/dt&" +
"gotoOnFail=/portal/dt?error=true");
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("IDToken1", "username"));
nvps.add(new BasicNameValuePair("IDToken2", "password"));
httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
response = httpclient.execute(httpost);
entity = response.getEntity();
System.out.println("Login form get: " + response.getStatusLine());
if (entity != null) {
entity.consumeContent();
}
System.out.println("Post logon cookies:");
cookies = httpclient.getCookieStore().getCookies();
if (cookies.isEmpty()) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.size(); i++) {
System.out.println("- " + cookies.get(i).toString());
}
}
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
}
}
A cookie is just another HTTP header. You can always set it while making a HTTP call with the apache library or with HTTPUrlConnection. Either way you should be able to read and set HTTP cookies in this fashion.
You can read this article for more information.
I can share my peace of code to demonstrate how easy you can make it.
public static String getServerResponseByHttpGet(String url, String token) {
try {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
get.setHeader("Cookie", "PHPSESSID=" + token + ";");
Log.d(TAG, "Try to open => " + url);
HttpResponse httpResponse = client.execute(get);
int connectionStatusCode = httpResponse.getStatusLine().getStatusCode();
Log.d(TAG, "Connection code: " + connectionStatusCode + " for request: " + url);
HttpEntity entity = httpResponse.getEntity();
String serverResponse = EntityUtils.toString(entity);
Log.d(TAG, "Server response for request " + url + " => " + serverResponse);
if(!isStatusOk(connectionStatusCode))
return null;
return serverResponse;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Since Apache library is deprecated, for those who want to use HttpURLConncetion , I wrote this class to send Get and Post Request with the help of this answer:
public class WebService {
static final String COOKIES_HEADER = "Set-Cookie";
static final String COOKIE = "Cookie";
static CookieManager msCookieManager = new CookieManager();
private static int responseCode;
public static String sendPost(String requestURL, String urlParameters) {
URL url;
String response = "";
try {
url = new URL(requestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
if (msCookieManager.getCookieStore().getCookies().size() > 0) {
//While joining the Cookies, use ',' or ';' as needed. Most of the server are using ';'
conn.setRequestProperty(COOKIE ,
TextUtils.join(";", msCookieManager.getCookieStore().getCookies()));
}
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
if (urlParameters != null) {
writer.write(urlParameters);
}
writer.flush();
writer.close();
os.close();
Map<String, List<String>> headerFields = conn.getHeaderFields();
List<String> cookiesHeader = headerFields.get(COOKIES_HEADER);
if (cookiesHeader != null) {
for (String cookie : cookiesHeader) {
msCookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
}
}
setResponseCode(conn.getResponseCode());
if (getResponseCode() == HttpsURLConnection.HTTP_OK) {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = br.readLine()) != null) {
response += line;
}
} else {
response = "";
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
// HTTP GET request
public static String sendGet(String url) throws Exception {
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", "Mozilla");
/*
* https://stackoverflow.com/questions/16150089/how-to-handle-cookies-in-httpurlconnection-using-cookiemanager
* Get Cookies form cookieManager and load them to connection:
*/
if (msCookieManager.getCookieStore().getCookies().size() > 0) {
//While joining the Cookies, use ',' or ';' as needed. Most of the server are using ';'
con.setRequestProperty(COOKIE ,
TextUtils.join(";", msCookieManager.getCookieStore().getCookies()));
}
/*
* https://stackoverflow.com/questions/16150089/how-to-handle-cookies-in-httpurlconnection-using-cookiemanager
* Get Cookies form response header and load them to cookieManager:
*/
Map<String, List<String>> headerFields = con.getHeaderFields();
List<String> cookiesHeader = headerFields.get(COOKIES_HEADER);
if (cookiesHeader != null) {
for (String cookie : cookiesHeader) {
msCookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
}
}
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
public static void setResponseCode(int responseCode) {
WebService.responseCode = responseCode;
Log.i("Milad", "responseCode" + responseCode);
}
public static int getResponseCode() {
return responseCode;
}
}
I do not work with google android but I think you'll find it's not that hard to get this working. If you read the relevant bit of the java tutorial you'll see that a registered cookiehandler gets callbacks from the HTTP code.
So if there is no default (have you checked if CookieHandler.getDefault() really is null?) then you can simply extend CookieHandler, implement put/get and make it work pretty much automatically. Be sure to consider concurrent access and the like if you go that route.
edit: Obviously you'd have to set an instance of your custom implementation as the default handler through CookieHandler.setDefault() to receive the callbacks. Forgot to mention that.

Categories