I'm making an http GET request. It works in about 70% of my attempts. For some reason, I sometimes get no response string from a successful connection. I just setup a button in my app which keeps firing the code below. One call might fail to reply with a string, the next call works fine:
private onButtonClick() {
try {
doit();
} catch (Exception ex) {
...
}
}
public void doit() throws Exception {
URL url = new URL("http://www.example.com/service");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setAllowUserInteraction(false);
connection.setReadTimeout(30 * 1000);
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Authorization",
"Basic " + Base64.encode("username" + ":" + "password"));
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = "";
StringBuilder sb = new StringBuilder();
while ((line = in.readLine()) != null) {
sb.append(line);
}
in.close();
connection.disconnect();
// Every so often this prints an empty string!
System.out.println(sb.toString());
}
am I doing something wrong here? It seems like maybe I'm not closing the connection properly from the last call somehow and the response gets mangled or something? I am also calling doit() from multiple threads simultaneously, but I thought the contents of the method are thread-safe, same behavior though,
Thanks
Thanks
That method looks fine. It's reentrant, so calls shouldn't interfere with each other. It's probably a server issue, either deliberate throttling or just a bug.
EDIT: You can check the status code with getResponseCode.
For checking ResponseCode:
BufferedReader responseStream;
if (((HttpURLConnection) connection).getResponseCode() == 200) {
responseStream = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
} else {
responseStream = new BufferedReader(new InputStreamReader(((HttpURLConnection) connection).getErrorStream(), "UTF-8"));
}
For empty content resposneCode is 204. So if u can get empty body just add one more "if" with 204 code.
We also came across with the similar scenario, I came across the following solution for this issue:
- Setting up a user agent string on URLConnection object.
URLConnection conn = url.openConnection();
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)");
more details
Related
I'm not trying to expose too many details of what I am trying to make, but basically I have a bot that sends a post request at a certain time. Basically, I'm racing against other people to send this post request first. When I test this code against no one, it gets responses almost instant. However, it seems when I go for these post requests against more people, it takes longer than normal to get a response.
Code to open connection:
httpURLConnection = (HttpURLConnection) (proxy != null ? url.openConnection(proxy) : url.openConnection());
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Content-Type", "application/json; utf-8");
httpURLConnection.setRequestProperty("Accept", "application/json");
Code to get response:
#SneakyThrows
public String getResponse() {
try (BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
return response.toString();
}
}
If you suspect the slowdown is on your end, you can try something like Jprofiler in order to determine what is causing your code to run slow. However, based on what you've said, it's very likely that it's simply the server being slow to respond. If you print or log when the request is sent and when the response is received, I suspect you'll find most of the time is there, waiting on the server to respond.
I've been working with the Slack API in java and have been trying to get an HTTP method that can be used like my below example block of code. That code block works, but the issue is I need to also include a 200 response code, and can't figure out how to get it to work.
Basically, how can I, In Java, send an HTTP post and also tag on the 200 status code using the URL and the content?
Current code:
public void httpRequest(URL url, String content) {
try {
byte[] contentBytes = content.getBytes("UTF-8");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Content-Length", Integer.toString(contentBytes.length));
connection.setRequestProperty("Status", Integer.toString(200));
OutputStream requestStream = connection.getOutputStream();
requestStream.write(contentBytes, 0, contentBytes.length);
requestStream.close();
String response = "";
BufferedReader responseStream;
response = "" + ((HttpURLConnection) connection).getResponseCode();
try {
if (((HttpURLConnection) connection).getResponseCode() == 200) {
responseStream = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
} else {
responseStream = new BufferedReader(new InputStreamReader(((HttpURLConnection) connection).getErrorStream(), "UTF-8"));
}
response = responseStream.readLine();
responseStream.close();
} catch (NullPointerException ignored) {
}
} catch (IOException e) {
e.printStackTrace();
}
}
The call to setDoOutput(true) triggers a post, i.e. you do not need to add
connection.setRequestMethod("POST");
Adding a status header to the request is possible, as you have done, but typically one associates status codes with http responses, not requests. - And off course, adding such custom header would only make sense if the server was designed to use this information to anything.
See this big, and highly up-voted answer on java.net.HttpURLConnection.
Also, you have some problems relating to your response variable as well as the BufferedReader. You accidentally override the value you initially assigned to the response field, instead of concatening. Also, your readLine() should probably be in a loop:
String tmp;
while ((tmp = responseStream.readLine()) !=null){
response += tmp;
}
so I'm trying to do a GET Request to my web service, and since I saw that the HttpGet class is being deprecated, I try to use the HttpURLConnection class instead, and I used it successfully with a 'POST' method... however when I try to do a simple 'GET' request - I get a 405 error (bad method).
I tested the link in DHC, and the link is fine.
Here's my method:
public JSONObject getClientByDeviceId (String link) {
try {
URL url = new URL(link);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// conn.setRequestMethod("GET");
// conn.setDoOutput(true);
// conn.setDoInput(true);
// conn.setUseCaches(false);
// conn.setAllowUserInteraction(false);
// conn.setRequestProperty("Content-Type", "application/json");
OutputStream outputStream = conn.getOutputStream();
outputStream.close();
if (conn.getResponseCode() != 200) {
Log.e("conn", "Error code: " + conn.getResponseCode());
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
conn.disconnect();
JSONObject returnedObject = new JSONObject(sb.toString());
if (returnedObject != null) {
Log.e("conn", "If 400, this is the object gained: " + returnedObject.getString("Message"));
} else {
Log.e("conn", "didn't get any JSON object");
}
conn.disconnect();
return returnedObject;
}
else {
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
Log.e("conn", "GREAT SUCCESS !!: " + conn.getResponseCode());
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
conn.disconnect();
JSONObject returnedObject = new JSONObject(sb.toString());
return returnedObject;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
Normally I would say that this problem is caused by trying to do a 'GET' request in a 'POST' URL. But without the two HttpGet and HttpPost classes I don't really know where to turn, all the properties that are commented out are like that because I tried them in the POST request and now I deleted one by one to try to get the method to work.
Any ideas ? or reference to an updated guide on how to properly use that HttpURLConnection class, since I couldn't find one.
Thanks in advance !
Solved it, apparently this code needed to be removed:
OutputStream outputStream = conn.getOutputStream();
outputStream.close();
I guess it was because I gave a GET URL and put that outputStream in my code and that caused the issues.
I still however don't understand why I got the "405: method GET not allowed" whereas I think I should have gotten the opposite: "POST" not allowed...
Anyway that is my solution, thanks a lot for your help guys !
HTTP 405 is caused by bad method call (Method not Allowed). That means you called GET method on POST request or vice-versa. You should add handling for you GET method on your Web-Service to get it working.
For anyone still reaching here from a search engine, my solution was similar -
I removed the line "conn.setDoOutput(true);" (or set it to false)
i'm trying to run a soap request in a basic http request...naturally i tried with external tools the message and is correct, like the endpoint i'm using as targetUrl, the wsdl is in something like
http://00.00.00.00/a-ws/services/basic?wsdl
and my actual end point is
http://00.00.00.00/a-ws/services/basic.targetservice
and i'm using this last as target url
URL url = new URL(targetUrl);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
connection.setRequestProperty("SOAPAction", action);
connection.setRequestProperty("User-Agent", "myagent");
connection.setRequestProperty("Host", "localhost");
//connection.setRequestProperty("Content-Length", "" + Integer.toString(message.getBytes().length));
connection.setUseCaches (false);
connection.setDoInput(true);
connection.setDoOutput(true);
//Send request
OutputStream wr = connection.getOutputStream ();
wr.write (message.getBytes());
wr.flush ();
wr.close ();
//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line=null;
StringBuffer response = new StringBuffer();
while( (line = rd.readLine()) != null) {
if (line!=null)
response.append(line);
}
rd.close();
return response.toString();
the raw message is tested with chrome plugin, the only thing i can't test is headers but the result is always an exception on getInputStream
java.io.IOException: Server returned HTTP response code: 500 for URL:
why?
It was a very stupid issue of encoding (like I was supposing)...i didn't escape double quote inside the message.
The evidence of problem was visible using a fake http server that just echo contents.
UPDATE:
Another thing nobody already pointed out is that is useful in case of exception to retrieve
connection.getErrorStream()
that contains the response in case of error!
I'm using the HttpURLConnection class to make http requests.
My code looks something like this-
while(true){
try{
connection=(HttpURLConnection)url.openConnection();
connection.setDoOutput(true);
connection.setConnectTimeout(2*1000);
InputStream in=connection.getInputStream();
}
catch(SocketTimeOutException e){}
catch(IOException e){}
}
I do some processing on the data once I retrieve the InputStream object. My problem is that if I let the program run long enough, the call to getInputStream blocks and I never get past that.
Am I missing something? Any pointers or help would be greatly appreciated. Thanks.
Set the read time out for the connection.
Also, close the streams in a finally block once you're done with them.
You should close connections that are not used. Here is example:
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setReadTimeout(2*1000);
connection.connect();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
stringBuilder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
stringBuilder.append(line + "\n");
}
String result = stringBuilder.toString();
reader.close();