HttpURLConnection always failing with 401 - java

I'm trying to use HttpURLConnection for connecting to server from Android app which I'm developing. For now, I'm testing the connection code not in an app but as a plain java program with main class. I guess this doesn't make any difference as far as HttpUrlConnection.
Please examine the code snippet. Another issue is even errorStream is throwing null. This I feel is because of malformed URL.
private static String urlConnectionTry() {
URL url; HttpURLConnection connection = null;
try {
String urlParameters = "email=" + URLEncoder.encode("email", "UTF-8") +
"&pwd=" + URLEncoder.encode("password", "UTF-8");
//Create connection
url = new URL("http://example.com/login");
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestProperty("uuid", getUuid());
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(true);
//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();
//Get Response
InputStream is = connection.getErrorStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
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();
}
}
}
private static String getUuid() {
try {
Document doc=Jsoup.connect("http://example.com/getUuid").get();
Elements metaElems = doc.select("meta");
for (Element metaElem : metaElems) {
if(metaElem.attr("name").equals("uuid")) {
return metaElem.attr("content");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

You're probably receiving 401 because the credentials that was sent to the server is not authorized- it's probably not registered or the password is incorrect.
As for the null error stream, take a look at this SO answer.
If the connection was not connected, or if the server did not have an error while connecting or if the server had an error but no error data was sent, this method will return null.
It is probably better if you check first the response code using HttpUrlConnection#getResponseCode(). Decide on whether you'll be checking the contents of the error stream based on the response code you get.

Related

Can't send JSON in a Java HTTP POST request

I'm getting a 'Server returned HTTP response code: 500' error although I have checked what I'm sending (I even tried sending it with an online tool and it worked). The API Key and the JSON are correct. I get this error when trying to read the input stream with 'connection.getInputStream()'. Where could this be comming frome ? Did I forget something ? I am trying to implement this feature from the openrouteservice API : https://openrouteservice.org/dev/#/api-docs/v2/directions/{profile}/post
public static UPSRoute getRoute(Location start, Location end, String language) {
if (language.equals("fr")) {
JSONObject jsonObject = null;
try {
URL url = new URL("https://api.openrouteservice.org/v2/directions/foot-walking");
String payload = "{\"coordinates\":[[" + start.getCoordinates() + "],[" + end.getCoordinates() + "]],\"language\":\"fr\"}";
System.out.println(payload); //{"coordinates":[[1.463478,43.562038],[1.471717,43.560787]],"language":"fr"}
byte[] postData = payload.getBytes(StandardCharsets.UTF_8);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", API_KEY);
connection.setRequestProperty("Accept", "application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8");
connection.setDoOutput(true);
try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
wr.write(postData);
}
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); // Error is right here
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
connection.disconnect();
jsonObject = new JSONObject(content.toString());
} catch (IOException | JSONException e) {
e.printStackTrace();
}
return new UPSRoute(jsonObject);
} else {
return getRoute(start, end);
}
}
Here is the error :
java.io.IOException: Server returned HTTP response code: 500 for URL: https://api.openrouteservice.org/v2/directions/foot-walking/json
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1913)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1509)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:245)
at UPSRouteService.getRoute(UPSRouteService.java:63)
at Main.main(Main.java:5)
Thanks to Andreas, it was just missing the line :
connection.setRequestProperty("Content-Type", "application/json");
It works fine now.

Java: Cannot write to a URLConnection if doOutput=false - call setDoOutput(true)

I'm a QA with desire to learn more about Java programming and problem I'm experiencing is this:
I'm trying to POST Employee data to the database of some fake Rest API, but I'm getting
Cannot write to a URLConnection if doOutput=false - call
setDoOutput(true)"
So far, I tried some ideas from StackOverflow, but inexperienced as I am, I could easily fall deeper into a problem.
So URL is: http://dummy.restapiexample.com/api/v1/create and firstly I created an Employee class of json object:
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
Employees em = new Employees();
em.setEmployeeName("Alex");
em.setEmployeeSalary("1234");
em.setEmployeeAge("28");
try{
URL url = new URL("http://dummy.restapiexample.com/api/v1/create");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Unsuccessful call: HTTP error : "
+ conn.getResponseCode());
}
// URLConnection urlc = url.openConnection();
// urlc.setDoOutput(true);
PrintWriter pw = new PrintWriter(conn.getOutputStream());
pw.print(new Gson().toJson(em));
pw.close();
pw.flush();
BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream())
);
String json = "";
String output;
while ((output = br.readLine()) != null) {
json += output;
}
conn.disconnect();
System.out.println("Employee name: " + em.getEmployeeName());
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Well, using one of your ideas and added next lines of code (it's commented in above code):
URLConnection urlc = url.openConnection();
urlc.setDoOutput(true);
So the code looks like:
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
Employees em = new Employees();
em.setEmployeeName("Alex");
em.setEmployeeSalary("1234");
em.setEmployeeAge("28");
try{
URL url = new URL("http://dummy.restapiexample.com/api/v1/create");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Unsuccessful call: HTTP error : "
+ conn.getResponseCode());
}
URLConnection urlc = url.openConnection();
urlc.setDoOutput(true);
PrintWriter pw = new PrintWriter(urlc.getOutputStream());
pw.print(new Gson().toJson(em));
pw.close();
pw.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(
(urlc.getInputStream())));
String json = "";
String output;
while ((output = br.readLine()) != null) {
json += output;
}
conn.disconnect();
System.out.println("Employee name: " + em.getEmployeeName());
}
catch (MalformedURLException e) {
e.printStackTrace(); }
catch (IOException e) {
e.printStackTrace();
}
}}
With this second code I'm not getting that error, but there is no inserting to the database(checking that using postman, with GET method)...
Well, what am I missing? I guess, I'm missing something basic...
Using url.openConnection twice means you get two different connections. You send the request to the second connection, and try to read the response from the first connection. You should call doOutput on the connection you open originally.
The second problem is you're calling getResponseCode before the request is sent. In http, the request must be sent entirely before the server sends a response. You should move the code that calls doOutput and writes the request body before the code that tries to check the response code.

Receiving null Value while using POST method in servlet?

I want to send a string by using POST method in servlet so that it can communicate with other servlet application present in other domain. But I am receiving null in my Input steam object.
My Code:
String content = "10 141 nahush123 01";
URL url = new URL("http://52.220.37.12:8080/servers/servers");
System.out.println(url.toString());
HttpURLConnection httpCon = (HttpURLConnection)url.openConnection();
httpCon.setDoInput(true);
httpCon.setDoOutput(true);
httpCon.setRequestMethod("POST");
httpCon.setRequestProperty("Content-Type", "text/plain;charset=UTF-8");
OutputStream os = httpCon.getOutputStream();
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(os));
out.write(content);
//br = BufferReader(out);
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
writer.println(httpCon.getResponseMessage());
httpCon.connect();
br = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
//reading response
//String resp;
//if(br != null){
content = br.readLine();
//}
System.out.println(content);
writer.println(content);
out.flush();
writer.flush();
writer.close();
out.close();
os.close();
Copy pasted your code in my servlet worked fine
Check that you overrided doPost method in the servlet
Check that you that your post metod work fine and return value, I use "DHC Rest Client" plugin for chrome. It is very cool tool
Try to remove httpCon.connect() line. It is not necessary.
From oracle docs about connect() method:
Operations that depend on being connected, like getContentLength, will
implicitly perform the connection, if necessary.
Operations getResponseMessage, getResponseCode perform the connection.
UPDATED
I tried to test with my local test url and it works. Then i tried with your url and it does not work.
You need to flush output stream before use input stream.
This code work and return "0#5#26#Temperature#Living_Room#555555581#0+0#7#0#Room1#Master_bedroom#555555581#1+1#7#0#Door1#Living_Room#555555581#2+1#6#0#frontdoor#Living_Room#555555581#2+0#6#0#doorback#Balcony#555555581#2+"
PrintWriter writer = res.getWriter();
String content = "10 141 nahush123 01";
URL url = new URL("http://52.220.37.12:8080/servers/servers");
System.out.println(url.toString());
HttpURLConnection httpCon = (HttpURLConnection)url.openConnection();
httpCon.setDoInput(true);
httpCon.setDoOutput(true);
httpCon.setRequestMethod("POST");
httpCon.setRequestProperty("Content-Type", "text/plain;charset=UTF-8");
OutputStream os = httpCon.getOutputStream();
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(os));
out.write(content);
out.flush();
//br = BufferReader(out);
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
writer.println(httpCon.getResponseMessage());
//httpCon.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
//reading response
//String resp;
//if(br != null){
content = br.readLine();
//}
System.out.println(content);
writer.println(content);
writer.flush();
writer.close();
out.close();
os.close();
Try with getparameter() function in the servlet
Call this method with your pass string parameter:
public String postData(String reqStr) {
ObjectOutputStream objOS = null;
ObjectInputStream objIS = null;
HttpURLConnection servletCon = null;
try {
if (reqStr != null) {
Thread.sleep(1000);
objOS.writeObject(reqStr);
} else {
throw new Exception("request is null.");
}
} catch (Exception ex) {
logger.error("Failed to send request to server.", ex);
}
String response = null;
try {
objIS = new ObjectInputStream(servletCon.getInputStream());
response = (String) objIS.readObject();
} catch (Exception ex) {
logger.error("Failed to get response from server.", ex);
response = null;
}
return response;
}
Initializing Connection like you but calling differently:
public void initializeUrlConnection(String servletURL, String contentType, String method) {
try {
logger.debug("Servlet URL " + servletURL);
url = new URL(servletURL);
servletCon = (HttpURLConnection) url.openConnection();
servletCon.setUseCaches(false);
servletCon.setDefaultUseCaches(false);
servletCon.setDoInput(true);
servletCon.setDoOutput(true);
servletCon.setRequestProperty("Content-Type", contentType);
servletCon.setRequestMethod(method);
objOS = new ObjectOutputStream(servletCon.getOutputStream());
} catch (IOException ex) {
logger.error("Failed to initialize Http Connection.", ex);
}
}
First of call initialize connection method with required parameter:
Object.initializeUrlConnection(url, contentType,method);
then call posDataMethod with your string/json parameter:
Object.postData(str);

Java program to call REST service that needs authentication

public class RestClient {
public static void main(String[] args) {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("fromSku","NONE" );
jsonObject.put("toSku","ASA5500-ENCR-K8" );
jsonObject.put("modelNo", "ASAV10");
jsonObject.put("serialNo", "ASATSTSN");
System.out.println(jsonObject);
URL url = new URL("http://licruleswb- dev.cloudapps.cisco.com/LicenseRules/rest/invokeASARule");
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
String encodedCredentials = new String(
org.apache.commons.codec.binary.Base64.encodeBase64
(org.apache.commons.codec.binary.StringUtils.getBytesUtf8("username:password"))
);
System.out.println(encodedCredentials);
connection.setRequestProperty ("Authorization", encodedCredentials);
connection.setRequestProperty("Content-Type", "application/json");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(jsonObject.toString());
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
System.out.println(in.toString());
while (in.readLine() != null) {
System.out.println(in.readLine());
}
System.out.println("\nREST Service Invoked Successfully..");
in.close();
} catch (Exception e) {
System.out.println("\nError while calling REST Service");
System.out.println(e);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Output:
<html><head>
</head><body>
<p>The document has moved here.</p>
null
REST Service Invoked Successfully..
Can anyone help me out to resolve this issue. This link is working perfectly fine if used in REST Client ad on But with this java program it's throwing a 302 error.
I came across your thread when trying something similar. For me the problem was solved by concatenating "Basic " with encodedCredentials variable, making it "Basic EncodedValue".

PHP to test Java class(about post data to web)

I wrote a program to send a String to Web URL, but before sending i need to test it use PHP on localhost. I never learn PHP. So would you guys help me out?
public class MessageSender {
public static Boolean sendMsg(String outboundUrl,String message) {
Boolean sendResult = false;
URL url;
HttpURLConnection connection = null;
try {
message = URLEncoder.encode("message", "UTF-8");
//Create connection
url = new URL(outboundUrl);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", "" +
Integer.toString(message.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches (false);
connection.setDoInput(true);
connection.setDoOutput(true);
//Send request
DataOutputStream wr = new DataOutputStream (connection.getOutputStream ());
wr.writeBytes (message);
wr.flush ();
//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
wr.close ();
rd.close();
String Whole=response.toString();
//System.out.println(Whole);
sendResult = true;
}
catch (Exception e) {
e.printStackTrace();
return sendResult;
}
finally {
if(connection != null) {
connection.disconnect();
}
}
return sendResult;
}
}
I do not know what to do to test use PHP on localhost
If you have installed php , make some folder ie /tmp/phppublic and place a index.php file there
PHP Server
index.php
<?php
var_dump($_POST);
?>
Console
cd /tmp/phppublic
php -S localhost:8000
To test your Java set
outboundUrl = "http://localhost:8000/index.php"

Categories

Resources