Android HttpURLConnection not working with cgi-bin? - android

I have simple code :
URL url;
BufferedReader in = null;
HttpURLConnection connection;
InputStream is = null;
InputStreamReader br = null;
setProgressTitle(progress, context.getString(R.string.loading));
setProgressMessage(progress, context.getString(R.string.loading_from_internet));
try {
url = new URL(urlStr);
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(Const.TIMEOUT);
is = connection.getInputStream();
...
If I have urlStr = "http://samlib.ru/w/waliduda_a_a/molochnischituran1.shtml" - all is work fine.
If I use urls like urlStr = "http://samlib.ru/cgi-bin/areader?q=jlist" - I got a error in connection.getInputStream();
**
03-04 15:37:52.459: ERROR/DataReader::loadDataFromInet(17281): Failed loading http://samlib.ru/cgi-bin/areader?q=jlist
03-04 15:37:52.459: ERROR/DataReader::loadDataFromInet(17281): java.io.FileNotFoundException: http://samlib.ru/cgi-bin/areader?q=jlist
03-04 15:37:52.459: ERROR/DataReader::loadDataFromInet(17281): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:521)
**
How can I upload data to a similar url?

There are a couple of reasons this might happen. Where I've personally seen it is when I've put in a URL that was subsequently redirected, HttpURLConnection doesn't handle that. I got the same response as you, I hit it with FF and it works fine. Its also possible that some sort of browser sniffing might be done on the recieving side.
Good Luck!

It looks like your cgi-bin/areader is not found. Getting an HTTP/404 response code:
wget http://samlib.ru/cgi-bin/areader?q=jlist
--2011-03-04 09:03:17-- http://samlib.ru/cgi-bin/areader?q=jlist
Resolving samlib.ru... 81.176.66.171
Connecting to samlib.ru|81.176.66.171|:80... connected.
HTTP request sent, awaiting response... 404 Not Found
2011-03-04 09:03:17 ERROR 404: Not Found.
Correct that then try again.

Related

HttpURLConnection getOutputStream class cast exception on Android

I'm trying to use HttpURLConnection to send and receive messages in an Android application. This code works fine in a java application, but when running on Android I get the following exception:
java.lang.ClassCastException: com.android.okio.RealBufferedSink$1 cannot be cast to java.io.ByteArrayOutputStream
The code where this occurs:
URL url = new URL(destURI.toString());
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// Set request properties and headers
con.setDoOutput(true);
con.setDoInput(true);
con.setRequestProperty(HEADER_CONTENT_TYPE, CONTENT_TYPE_LS);
con.setRequestProperty(HEADER_CONTENT_LENGTH, new Integer(wrapperBytes.length).toString());
con.setRequestMethod(METHOD_POST);
// Set connect and read timeouts
con.setConnectTimeout(timeoutInMillis);
con.setReadTimeout(timeoutInMillis);
// Write request content
ByteArrayOutputStream out = (ByteArrayOutputStream) con.getOutputStream();
out.write(wrapperBytes);
out.flush();
I've looked at the android reference pages and these seem to say what I'd expect, getOutputStream() returns an OutputStream. This should then be able to be cast to a ByteArrayOutputStream.
Where is the RealBufferedSink coming from? Why am I not getting an OutputStream back?
Any help would be greatly appreciated!
Casting
ByteArrayOutputStream out = (ByteArrayOutputStream) con.getOutputStream();
is not recommended,
you might try:
OutputStream out = new BufferedOutputStream(con.getOutputStream());

How to fix urlConnection.getResponseCode = 403

Here is my code:
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
int status = urlConnection.getResponseCode();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
return;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
Here is example of my JSON:
[{"Id":1,"Name":"Алупка","RegionId":1},{"Id":2,"Name":"Алушта","RegionId":1},{"Id":3,"Name":"Армянськ","RegionId":1}]
Here is URL: http://donor.ua/api/cities?sign=9u1AARsgKybup3vz9CaQnw==ivbCaKmrWpgz
But urlConnection.getResponseCode() still returns "403".
Please, tell me how to fix this!
Thanks in advance!
When I try to load the URL you provided in the question, it says that HTTPS is required. Using Firebug, I confirmed that the server is in fact returning 403 in this case. Changing the protocol from http to https returns the JSON as expected. So, in your code, when you create your URL object, make sure that the URL you specified starts with https:// instead of http://
The error could be due to server is rejecting the connection due to you are not sending "User-Agent".
add this line in order to fix it:
connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0");

HttpsUrlConnection EOFException

I'm using the following code for post requests
public String executeHttpPost(String uri, String data) {
HttpURLConnection conn = null;
URL url = null;
String s = null;
try {
url = new URL(uri);
conn = (HttpURLConnection) url.openConnection();
if (conn instanceof HttpsURLConnection) {
Log.d("HTTPS", "HttpsUrl");
}
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
DisplayResponseHeaders(conn);
s = readStream(conn.getInputStream());
Log.d("body", s);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
s = null;
e.printStackTrace();
} finally {
conn.disconnect();
}
return s;
}
When I use it over http, all works good , but over https I get
java.io.EOFException
at libcore.io.Streams.readAsciiLine(Streams.java:203)
at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:573)
at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:821)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:283)
libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)
ru.fors.remsmed.fragment.NetHelper.executeHttpPost(NetHelper.java:234)
ru.fors.remsmed.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:424)
ru.fors.remsmed.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:1)
android.os.AsyncTask$2.call(AsyncTask.java:287)
java.util.concurrent.FutureTask.run(FutureTask.java:234)
android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
java.lang.Thread.run(Thread.java:856)
threadid=14: thread exiting with uncaught exception (group=0x40a71930)
I found the issue about recycling connections bug in httpsurlconnection and possible solution :
if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {
conn.setRequestProperty("Connection", "close");
}
But it isn't work for me.
Try to change your code like this:
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded; charset: UTF-8");
byte[] output = data.getBytes("UTF-8");
conn.setFixedLengthStreamingMode(output.length);
os = conn.getOutputStream();
os.write(output);
os.flush();
os.close();
DisplayResponseHeaders(conn);
if (conn.getResponseCode() == 200) { // or other 2xx code like 204
s = readStream(conn.getInputStream());
Log.d("body", s);
}
else {
// handle error conditions like 404, 400, 500, ...
// now it may be necessary to read the error stream
InputStream errorStream = conn.getErrorStream();
// ...
}
AFAIK you should always close all streams you opened. I'm not sure whether conn.disconnect() is doing that for you.
If you want to code your HTTP(S) requests more conveniently, you can have a look at DavidWebb where you have a list of libraries helping you to avoid using cumbersome HttpURLConnection.
That EOFException suggests the response is malformed - perhaps lacking a blank line after the headers. Some HTTP client code is more forgiving in that case, for me iOS could handle my server responses fine but I was getting EOFException on Android using HttpURLConnection.
My server was using python SimpleHTTPServer and I was wrongly assuming all I needed to do to indicate success was the following:
self.send_response(200)
That sends the initial response header line, a server and a date header, but leaves the stream in the state where you are able to send additional headers too. HTTP requires an additional new line after headers to indicate they are finished. It appears if this new line isn't present when you attempt to get the result body InputStream or response code etc with HttpURLConnection then it throws the EOFException (which is actually reasonable, thinking about it). Some HTTP clients did accept the short response and reported the success result code which lead to me perhaps unfairly pointing the finger at HttpURLConnection.
I changed my server to do this instead:
self.send_response(200)
self.send_header("Content-Length", "0")
self.end_headers()
No more EOFException with that code. It's possible the "Connection: close" solutions trigger some behaviour on certain servers that might work around this (eg ensuring the response is valid before closing) but that wasn't the case with the python SimpleHTTPServer, and the root cause turned out to be my fault.
NB: There are some bugs on Android pre-Froyo (2.2) relating to keep-alive connections - see the blog post here: http://android-developers.blogspot.co.uk/2011/09/androids-http-clients.html. I'm yet to see convincing evidence of bugs with newer versions of Android.

Issue with HttpURLConnection on Android Nexus v4.0.2

The below code simply is not working on my Android Galaxy Nexus running v4.0.2 it works in the emulator and other older devices. When running on older devices and the emu the variable "is" is getting all the bytes as needed and all is good. While running on the Nexus it throws the file not found exception at "is" and "is" stays null. Then when I try to work with "is" further down the class it throws a null pointer because "is" is null. How can I fix this file not found error? The file is reachable on other devices/emu/browser.
I am getting java.io.FileNotFoundException: at is = urlConnection.getInputStream();
Here is the code:
// GET
InputStream is = null;
try {
// set the URL that points to a file to be downloaded
URL url = new URL(downloadURL);
// create the new connection
HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
// set up some things on the connection
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
// connect and download
urlConnection.connect();
// used in reading the data from the internet
is = urlConnection.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
urlConnection.setDoOutput(true);
Should be:
urlConnection.setDoOutput(false);
urlConnection.setDoOutput(true) effectively changes the method to POST, so probably your server doesn't respond to POST?
HTTPUrlConnection has an ugly and confusing interface indeed. Here's a recent writeup on its peculiarities:
http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection

ClassCastException with HttpsURLConnection

I try to establisch a HttpsURLConnection with:
HttpsURLConnection conn = (HttpsURLConnection) new URL(url).openConnection()
but I get an Exception:
E/JavaBinder( 901): java.lang.ClassCastException: org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection
But I can't find out, why. The same example is everywhere across the web.
The ClassCastException is telling you that the object being returned is not a HttpsUrlConnection. The cast you are doing is inherently unsafe, instead you should something like:
URLConnection conn = new URL(url).openConnection();
if (conn instanceof HttpsURLConnection) {
// do stuff
}
else {
// error?
}
As to the reason its not giving you an Https version, what url are you providing it with? My guess is you are giving it http:.. instead of https:...
What is the URL? It looks like you are using a plain "http:" scheme URL, but expecting an HTTPS connection.

Categories

Resources