How to Close HttpsURLConnection Java - java

I am trying to request data from the server using HttpsURLConnection; I currently have the server requiring the user to enter a username and password via a prompt. In a web browser after you enter the correct username and password, the browser would save the username and password as a session cookie in your browser so you can visit other pages within site without being prompted for your credentials. But for the client which is in Java, it does not save the username and password. I am trying to use .disconnect() to close the connection, but I keep getting the following error:
java.lang.IllegalStateException: Already connected
at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:3053)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.setRequestProperty(HttpsURLConnectionImpl.java:316)
My Java Code:
private static void sendPost(String _url) throws Exception {
String url = _url;
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
int responseCode = con.getResponseCode();
Auth(con);
if (responseCode == 200) {
label.setText("Sucssesfully Scanned: " + StudID.getText());
} else {
label.setText("Error, please scan again");
}
con.disconnect();
}
private static ArrayList<String> Get(String _url) throws Exception {
ArrayList<String> list = new ArrayList<>();
JsonParser parser = new JsonParser();
String url = _url;
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
Auth(con);
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
con.disconnect();
JsonElement element = parser.parse(response.toString());
if (element.isJsonObject()) {
JsonObject data = element.getAsJsonObject();
for (int i = 0; i < data.get("chapels").getAsJsonArray().size(); i++) {
JsonObject jObj = (JsonObject) data.get("chapels").getAsJsonArray().get(i);
list.add(jObj.get("Name").toString().replaceAll("\"", "") + " - " + jObj.get("Loc").toString().replaceAll("\"", ""));
}
}
return (list);
}
private static void Auth(HttpsURLConnection con){
String encodedBytes = Base64.getEncoder().encodeToString((BCrypt.hashpw("swheeler17", BCrypt.gensalt(10)) + ":" + BCrypt.hashpw("Trinity", BCrypt.gensalt(10))).getBytes());
con.setRequestProperty("authorization", "Basic " + encodedBytes);
}
Example of username and password prompt: https://chapel-logs.herokuapp.com/chapel

java.lang.IllegalStateException: Already connected
That exception means that you have attempted to set the property giving the authorization for the request after it has been sent.
This is probably where it happens:
int responseCode = con.getResponseCode();
Auth(con);
and Auth calls setRequestProperty.
Asking for the response code causes the request to be sent if if hasn't already been sent. (Obviously ... you can't get the response code until you get the response, and the server can't give you one unless the request is sent.)
To answer your question, calling disconnect on the connection will disconnect the connection.
But that's not what is causing your problem. The stacktrace shows clearly that the exception is happening when something is calling setRequestProperty.

Based off of Stephen C's answer I determined the swap the order of:
int responseCode = con.getResponseCode();
Auth(con);
So the working solution is:
Auth(con);
int responseCode = con.getResponseCode();
I'm assuming ResponseCode() creates a request to the server if a request has not already been made, otherwise ResponseCode() uses the pre-existing request. Upon further testing, I concluded there is no need to call .disconnect().

Related

OutputStream os = con.getOutputStream() throws NullPointerException

I am trying to build an android app for a website and I need to post some value to this page first.
Here is my code:
private void sendPOST(String user,String pass) throws IOException {
String POST_PARAMS = "username="+user+"&password="+pass;
URL obj = new URL("http://xx.xx.xx.xx/mysite/test.php");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
//----------------------------------------------------------- For POST only - START---------------------------------------------
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write(POST_PARAMS.getBytes());
os.flush();
os.close();
// ------------------------------------------------------------For POST only - END----------------------------------------------------
int responseCode = con.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) { //success
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// print result
Toast.makeText(getApplicationContext(), response.toString()==""?"No Result":response.toString(), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),"POST request failed", Toast.LENGTH_LONG).show();
}
}
when this line is executed OutputStream os = con.getOutputStream();
a null exception occurs.
I am unable to proceed further. Please suggest what i must do to remove this exception.
put your delevelopment server in another locatation other than localhost (try using the real IP, something like: 192.168.0.1).
sometimes you will receive a successfull connection from HttpUrlConnection.openConnection() (it returns non null object) and this not guarantee the subsequents calls to success. In other words, when you call con.getOutputStream() it throws an exception no matter if con is non-null.
It's the old question but I might have to answer on it because I have face to it today. When you ping http (instead https) have to put in manifest -> application: android:usesCleartextTraffic="true"
I think this would helped you years ago...
try(OutputStream os = con.getOutputStream()) {
byte[] input = POST_PARAMS.getBytes("utf-8");
os.write(input, 0, input.length);
}
maybe you should try to "connect" first before doing anything with your created HttpURLConnection con.
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.connect();
do more stuff with con...
I hope this helps you :)
URL obj = new URL("http://xx.xx.xx.xx/mysite/test.php");
URL Class object "obj" can't reach to your mentioned URL properly.
Try this instead:
URL obj = new URL("http://"+"xx.xx.xx.xx/mysite/test.php");

Difference between Java Post Request and browser post request

I am trying to use api of one popular russian social networks. I am using OAuth via Java HttpUrlConnection. The problem is, when I send post data via Java, I get 401 response code. When I copy request and paste it browser, I get redirect to URL containing access token I need. That means that my post request is correct, but why when I send it with Java I get 401 error? When I send request with incorrect password, I get 200. It means that request is correct too.
private void getHomeAuth() throws Exception {
String url = "https://oauth.vk.com/authorize?client_id=APP_ID&scope=friends&redirect_uri=https://oauth.vk.com/blank.html&display=page&v=5.34&response_type=token";
URL oauth = new URL(url);
HttpURLConnection connection = (HttpURLConnection) oauth.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = connection.getResponseCode();
System.out.println("Response code: " + responseCode);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while((inputLine = reader.readLine()) != null)
response.append(inputLine + "\n");
reader.close();
PrintWriter writer = new PrintWriter("auth.html");
writer.print(response);
writer.close();
parse();
cookies = connection.getHeaderField("Set-Cookie");
referer = connection.getURL().toString();
}
private void postAuth() throws Exception {
email = URLEncoder.encode("example#gmail.com", "UTF-8");
password = "password";
_origin = URLEncoder.encode(_origin, "UTF-8");
String url = "https://login.vk.com/?act=login&soft=1";
URL post = new URL(url);
String urlParameters = "ip_h=" + ip_h + "&_origin=" + _origin + "&to=" + to + "&expire=" + expire + "&email=" + email + "&pass=" + password;
HttpsURLConnection con = (HttpsURLConnection) post.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Cookie", cookies);
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("Sent post. Response code: " + responseCode + "\nRequest: " + post.toString() + urlParameters + "\nRequestMethod: " + con.getRequestMethod());
}
I also tryied to send this request via addon in browser, and the result was correct. I obtained access token from redirect link.
Maybe the problem is that something inside request is incorrect. I have tried to monitor requests from java app, but I failed.
My experience with this kind of problem is that the http request that first authenticates the user also puts cookies (scope varies from case to case) into the response and subsequent http requests are expected to contain those cookies. Look very closely at the complete returned response headers to see what cookies might have been returned.

Paypal update invoice rest api HTTP response code: 500

i am currently trying to use REST api provided by Paypal to create my own service using servlet. I manage to transfer the cURL code into HttpsURLConnection using java.
Here is my code:
JSONObject returnJson = new JSONObject();
PrintWriter out = response.getWriter();
JSONParser jparser = new JSONParser();
try{
String inputStr = request.getParameter("input");
System.out.println(inputStr);
JSONObject inputJson = (JSONObject) jparser.parse(inputStr);
String accessToken = (String) inputJson.get("access_token");
String invoiceId = (String) inputJson.get("invoiceId");
String url = "https://api.sandbox.paypal.com/v1/invoicing/invoices/"+invoiceId;
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("PUT");
con.setRequestProperty("Accept-Language", "text/html; charset=UTF-8");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Authorization", "Bearer "+accessToken);
//Tentatively, the input is hard coded, after integration, the input comes from http request.
//However, only merchant email in mandatory for invoice creation in sand box so far
//For details of invoice attributes please refer to this link--> https://developer.paypal.com/docs/api/#update-an-invoice
String urlJsonString = "{\"id\":\""+invoiceId+"\",\"status\":\"DRAFT\",\"merchant_info\":{\"email\":\"rui.song.2013-facilitator#sis.smu.edu.sg\",\"first_name\":\"Dennis\",\"last_name\":\"Doctor\",\"business_name\":\"MedicalProfessionals,LLC\",\"phone\":{\"country_code\":\"US\",\"national_number\":\"5032141716\"},\"address\":{\"line1\":\"1234MainSt.\",\"city\":\"Portland\",\"state\":\"LALA\",\"postal_code\":\"97217\",\"country_code\":\"US\"}},\"billing_info\":[{\"email\":\"sally-patient#example.com\"}],\"shipping_info\":{\"first_name\":\"Sally\",\"last_name\":\"Patient\",\"business_name\":\"Notapplicable\",\"address\":{\"line1\":\"1234BroadSt.\",\"city\":\"Portland\",\"state\":\"LALA\",\"postal_code\":\"97216\",\"country_code\":\"US\"}},\"items\":[{\"name\":\"Sutures\",\"quantity\":100,\"unit_price\":{\"currency\":\"USD\",\"value\":\"250\"}}],\"invoice_date\":\"2014-01-07PST\",\"payment_term\":{\"term_type\":\"NO_DUE_DATE\"},\"tax_calculated_after_discount\":false,\"tax_inclusive\":false,\"note\":\"MedicalInvoice16Jul,2013PST\",\"total_amount\":{\"currency\":\"USD\",\"value\":\"250\"}}";
System.out.println(urlJsonString);
con.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(urlJsonString);
wr.close();
int responseCode = con.getResponseCode();
System.out.println("Response Code : " + responseCode);
out.print(responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer res= new StringBuffer();
while ((inputLine = in.readLine()) != null) {
res.append(inputLine);
}
in.close();
returnJson = (JSONObject) jparser.parse(res.toString());
System.out.println(returnJson);
}catch(Exception e){
e.printStackTrace();
returnJson.put("message", e);
}
out.print(returnJson);
I am testing the service on localhost, and i will manually pass in TWO parameters: "access_token" and "invoiceId" like this:
http://localhost:8080/Authentication/PaypalUpdateInvoiceServlet?input={"access_token":"A015Rv3XNo4fmFh4JC2sJiGjl1oEQ5w-B9azU.H6nlzMm1s","invoiceId":"INV2-9TRP-2S2R-OPBD-XK9T"}
These two pieces of info are obtained by me using the similar code i mentioned above.
I only modified codes in the entier HttpsURLConnection part to correspond with the cURL request and response sample provided in Paypal site. Link -->(https://developer.paypal.com/docs/api/#update-an-invoice)
Thus far, i successfully implement Create, Retrieve for invoice. I use the same way to make the servlet call with the specific parameters required and are able to get the expected response show on Paypal site.
BUT Now i am stuck with update invoice. When i make the servlet call.
i will receive:
500{"message":java.io.IOException: Server returned HTTP response code: 500 for URL: https://api.sandbox.paypal.com/v1/invoicing/invoices/IINV2-9TRP-2S2R-OPBD-XK9T}
Can anyone help me explain why i get this error and how shall i fix this?

Java : How to avoid hand-shake mode with HttpURLConnection authentication?

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.

Keywords object is empty when making authenticated YouTube API call with Java YouTubeService class

I am trying to fetch videos from MY OWN YouTube account, so that I get the keywords/tags for each video. I'm trying to use the most simple approach for making an authenticated call to get my videos with keywords/tags.
Here is my Java code:
String clientID = "XXXXXXXXXXXX.apps.googleusercontent.com";
String devKey = "MY-DEVELOPER-KEY";
String userEmail = "MY-GMAIL-EMAIL";
String userPassword = "MY-GMAIL-PASSWORD";
String authorName = "MY-YOUTUBE-ACCOUNT-NAME";
String url = "https://gdata.youtube.com/feeds/api/videos";
YouTubeService service = new YouTubeService( clientID, devKey );
service.setUserCredentials( userEmail, userPassword );
YouTubeQuery query = new YouTubeQuery( new URL( url ) );
query.setAuthor( authorName );
VideoFeed videoFeed = service.query( query, VideoFeed.class );
Please, help me understand what I am doing wrong, to authenticate and get those media keywords.
If you are going to refer me to another authentication option, please, show an example of using that other option for my specific scenario.
You're running into the behavior described in this blog post: your API calls are going against the search index, and those results will never have the keywords in them.
There's an example that shows how you could request the uploads feed in Java using v2 of the Data API; you can modify that example to use the channel name default instead of username and you'll automatically pull in the uploads feed for the currently authenticated account.
Here is what finally worked for me to get JSON-C feed with tags (keywords):
/** AUTHENITICATION **/
// HTTP connection
URL url = new URL("https://www.google.com/accounts/ClientLogin");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
// Form the POST parameters
StringBuilder content = new StringBuilder();
content.append("Email=").append(URLEncoder.encode("MY-GMAIL-LOGIN", "UTF-8"));
content.append("&Passwd=").append(URLEncoder.encode("MY-GMAIL-PASSWORD", "UTF-8"));
content.append("&service=").append(URLEncoder.encode("youtube", "UTF-8"));
OutputStream outputStream = urlConnection.getOutputStream();
outputStream.write(content.toString().getBytes("UTF-8"));
outputStream.close();
// Check response status
int responseCode = urlConnection.getResponseCode();
if( responseCode != HttpURLConnection.HTTP_OK ) {
// EXCEPTION
}
// Get the token from the response
String token;
InputStream inputStream = urlConnection.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while((line = in.readLine()) != null) {
if ( line.indexOf("Auth=") > -1 ) {
token = line.split("=")[1];
}
}
/** JSON-C FEED WITH TAGS **/
HttpClient client = new HttpClient();
GetMethod method = new GetMethod("http://gdata.youtube.com/feeds/api/users/default/uploads?v=2&alt=jsonc&max-results=50&start-index=1");
// set the authentication headers
method.setRequestHeader("Authorization", "GoogleLogin auth=" + token);
method.setRequestHeader("X-GData-Key", "key=MY-DEV-KEY");
method.setRequestHeader("GData-Version", "2");
method.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
// Make the call
int statusCode = client.executeMethod(method);
if ( statusCode != HttpStatus.SC_OK ) {
// EXCEPTION
}
String JSON = method.getResponseBodyAsString();

Categories