I want to see the exact headers my android app is sending while making a web request so I thought I'd simply create a simple server app in java on my local machine and have my android app make a call to it. Then simply dump the request to the console so I could see what the app is sending. However when I tried to connect, the app hangs and stops responding.
I created a simple server the only accepts a connection and sysouts the data it gets. The server runs fine and if I hit it from a web browser on my computer will print the headers from the web browsers request. So I know the server works fine.
Here's the code from my app:
URL url = new URL("http://192.168.1.11:9000");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.connect();
PrintWriter writer = new PrintWriter(connection.getOuputStream(), true);
writer.write("hi");
writer.close();
Simple. I only want the headers after all. Now I started without a post and using:
URL url = new URL("http://192.168.1.11:9000");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
in.close();
but that doesn't work. The app stops responding on the getInputStream() request. It just stops and won't continue. The server gets no connection request either.
So in all, the app is blocking on the url connection's getInputStream and I can't figure out why.
Now I've searched for awhile and found these:
Android app communicating with server via sockets
socket exception socket not connected android
Android embedded browser cant connect to server on LAN
Using java.net.URLConnection to fire and handle HTTP requests
Client Socket cannot connect to running Socket server
But nothing helps. I'm not using the localhost like everyone with this problem seems to be and I've tried using the androids 10.0.0.2 but that doesnt work either.
I'm not on a network that restricts anything (I'm home) and I've tried using the first set of code shown in order to send a message to my server but not even that works (it runs fine but the server never gets a client. Hows that work?).
I tried using both URLConnection and HttpURLConnection, they both have the same problem.
I'm also using the internet permission in my app, so it does have the permission needed.
I'm at a loss at this point. Why can't I make a simple call to my server?
EDIT
I used the exact code from androids documentation:
private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
// Only display the first 500 characters of the retrieved
// web page content.
int len = 500;
try {
URL url = new URL("http://10.0.2.2:9000");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
int response = conn.getResponseCode();
is = conn.getInputStream();
// Convert the InputStream into a string
String contentAsString = readIt(is, len);
return contentAsString;
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
}
but even that doesn't work. It still hangs. Only now it hangs on the getResponseCode(). Then throws a timeout exception. The server never gets a request though.
Your address must start with 'http://", try again!
I think the root of your issue is that Android is FCing your app before the connection completes, because I assume you haven't wrapped this in a Loader, AsyncTask or Thread. I suggest you follow the training guide Google provides, wrapping your call in an AsyncTask and seeing if that corrects the issue.
I have a Java class I use for making HTTP GET requests, I'm guessing its near identical to the android code your using so below I've dumped the relevant part of the code. I've used this class many times in Java applications (not on Android).
currentUrl = new URL(getUrl);
conn = (HttpURLConnection)currentUrl.openConnection();
conn.setRequestProperty("Cookie", getCookies(currentUrl.getHost()));
conn.setRequestProperty("User-Agent", "robadob.org/crawler");
if(referrer!=null){conn.setRequestProperty("Referrer",referrer);}
conn.setRequestMethod("GET");
conn.connect();
//Get response
String returnPage = "";
String line;
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = rd.readLine()) != null) {
returnPage+=line+"\n";
}
rd.close();
I can't see anything obvious that would be causing your code to fail, but hopefully you can spot something from this. The setRequestProperty is me setting headers, so you shouldn't need those.
If that fails, flood your code with System.out's so you can see which statement its stalling at.
Related
I am sending commands to a server using http, and I currently need to parse a response that the server sends back (I am sending the command via the command line, and the servers response appears in my browser).
There are a lot of resources such as this: Saving a web page to a file in Java, that clearly illustrate how to scrape a page such as cnn.com. However, since this is a response page that is only generated when the camera receives a specific command, my attempts to use the method described by Mike Deck (in the link above) have met with failure. (Specifically, when my program requests the page again the server returns a 401 error.)
The response from the server opens a new tab in my browser. Essentially, I need to know how to save the current web page using java, since reading in a file is probably the most simple way to approach this. Do any of you know how to do this?
TL;DR How do you save the current webpage to a webpage.html or webpage.txt file using java?
EDIT: I used Base64 from the Apache commons codec, which solved my 401 authentication issue. However, I am still getting a 400 error when I attempt to connect my InputStream (see below). Does this mean a connection isn't being established in the first place?
URL url = new URL ("http://"+ipAddress+"/axis-cgi/record/record.cgi?diskid=SD_DISK");
byte[] encodedBytes = Base64.encodeBase64("root:pass".getBytes());
String encoding = new String (encodedBytes);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput (true);
connection.setRequestProperty ("Authorization", "Basic " + encoding);
connection.connect();
InputStream content = (InputStream)connection.getInputStream();
BufferedReader in = new BufferedReader (new InputStreamReader (content));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
EDIT 2: Changing the request to a GET resolved the issue.
So while scrutinizing my code above, I decided to change
connection.setRequestMethod("POST");
to
connection.setRequestMethod("GET");
This solved my problem. In hindsight, I think the server was not recognizing the HTTP because it is not set up to handle the various trappings that come along with post.
I am trying to send a request to a server using GET that will respond with XML. I am told that I need to set the "Accept" property, code follows:
StringBuffer url = new StringBuffer(BASE_URL);
url.append(DRS_SERVICE_RELATIVE_URL);
url.append("?").append(DOC_PARAM_NAME).append("=").append(docId);
url.append("&").append(DOB_PARAM_NAME).append("=").append(dob);
try
{
this.server = new URL(url.toString());
URLConnection urlCon = this.server.openConnection();
HttpURLConnection con = (HttpURLConnection)urlCon;
con.addRequestProperty("Accept", "text/xml, application/*+xml, application/xml, text/xml, application/*+xml");
con.connect();
input = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line = null;
while((line = input.readLine()) != null)
System.out.println(line);
I get response code 500. When I talk to the developers of the URL I am trying to access they say I am not setting the "Accept" property to XML? What am I doing wrong? How are you supposed to set that property?
EDIT:
OK this is embarassing. The problem had to do with my development enviroment, specifically the way I set up a TCP/IP monitoring tool. When I stopped monitoring the network messages it worked as expected.
The problem had to do with my development enviroment, specifically the way I set up a TCP/IP monitoring tool. When I stopped monitoring the network messages it worked as expected.
I am working on creating a Video sitemap for a site that has hosted videos on Brightcove video cloud. In order to get all the video information from the site, Brightcove suggests to read the response from their url of following form
http://api.brightcove.com/services/library?token="+accountToken+"&page_size=1&command=find_all_videos&output=JSON&get_item_count=true
the output of the url is in JSON, where accountToken is just an identifier of the account.
When I hit the above url with Token in the browser, it gives me the correct response.
I wrote below program snippet to read from that url
URL jsonURL = new URL("http://api.brightcove.com/services/library?token="+accountToken+"&page_size=1&command=find_all_videos&output=JSON&get_item_count=true");
HttpURLConnection connection = (HttpURLConnection) jsonURL.openConnection();
connection.setRequestMethod("GET");
connection.connect();
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String lineRead = "";
while (reader.ready()) {
lineRead = lineRead + reader.readLine();
}
As my browser uses proxy, I added below code to include proxy settings
System.setProperty("http.proxyHost", "my.proxyurl.com");
System.setProperty("http.proxyPort", "80");
Without using proxy settings, it returns java.net.ConnectException: Connection refused: connect and with proxy it gives me java.io.IOException: Server returned HTTP response code: 503
So my question is , why is it giving me a 503(Service Unavailable) error ? From the browser its working fine.
Update 1:
It seems like an issue with the Network. I pinged the domain and it said "Request Timed out". Working via HTTP though. Looks like an issue with the Firewall.
I think, it may due to your internet connection, I have tried your code I didn't get any 503(Service Unavailable). Check out with different connection connection(without proxy) and it should work. Or you can try it with slightly different approach:
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("host", "port));
conn = new URL(jsonURL).openConnection(proxy);
If you have SOCKS type proxy, change Proxy's constructor parameter to Proxy.Type.SOCKS.
Minor correction to Jamas code
String host="myproxy.com";
int port=8080;
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port));
I want to call a secure webservice, using a cert that I have... the server takes a long time to authenticate with the cert, and, while this is ok the first time, the user will call it over and over again (in the same "session") and I feel I ought to be able to reuse the connection.
I have the following code.
System.setProperty("javax.net.ssl.trustStorePassword", "");
System.setProperty("javax.net.ssl.trustStore", "trusted.cacerts");
System.setProperty("javax.net.ssl.keyStorePassword", "mypassword");
System.setProperty("javax.net.ssl.keyStore", "trusted.clientcerts");
URL url = new URL("https://remoteserver:8443/testservice");
HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "text/xml");
connection.setDoOutput(true);
OutputStream os = connection.getOutputStream();
os.write(bytes);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
connection.disconnect();
This works great... but is slow. Just the authentication takes about 10 seconds. This internal authentication is typical here and that cannot be sped up. But can't I reuse it somehow?
I tried put a loop around this code, between the url.connection and the disconnect, thinking I could just recall it again and again, but that fails (500). I have tried moving things around a bit, in order to do only some of the commands the first time, but it still fails.
I read about keep-alive, but have not found any good examples of what this is, and how to use it (if that is even a valid way). If I do all of this via HTML, via Firefox or IE, the browser is able to cache the cert, I guess, so every time after the first is blazing fast. Can I emulate that some how?
better alternative is to use HttpClient and its connection pooling mechanism. also see if https keep-alive is going to help you
Try just not calling connection.disconnect()... I don't think there should be any need for you to do that. You should, however, ensure that you close your reader when you're finished with it.
If I create an HTTP java.net.URL and then call openConnection() on it, does it necessarily imply that an HTTP post is going to happen? I know that openStream() implies a GET. If so, how do you perform one of the other HTTP verbs without having to work with the raw socket layer?
If you retrieve the URLConnection object using openConnection() it doesn't actually start communicating with the server. That doesn't happen until you get the stream from the URLConnection(). When you first get the connection you can add/change headers and other connection properties before actually opening it.
URLConnection's life cycle is a bit odd. It doesn't send the headers to the server until you've gotten one of the streams. If you just get the input stream then I believe it does a GET, sends the headers, then lets you read the output. If you get the output stream then I believe it sends it as a POST, as it assumes you'll be writing data to it (You may need to call setDoOutput(true) for the output stream to work). As soon as you get the input stream the output stream is closed and it waits for the response from the server.
For example, this should do a POST:
URL myURL = new URL("http://example.com/my/path");
URLConnection conn = myURL.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
OutputStream os = conn.getOutputStream();
os.write("Hi there!");
os.close();
InputStream is = conn.getInputStream();
// read stuff here
While this would do a GET:
URL myURL = new URL("http://example.com/my/path");
URLConnection conn = myURL.openConnection();
conn.setDoOutput(false);
conn.setDoInput(true);
InputStream is = conn.getInputStream();
// read stuff here
URLConnection will also do other weird things. If the server specifies a content length then URLConnection will keep the underlying input stream open until it receives that much data, even if you explicitly close it. This caused a lot of problems for us as it made shutting our client down cleanly a bit hard, as the URLConnection would keep the network connection open. This probably probably exists even if you just use getStream() though.
No it does not. But if the protocol of the URL is HTTP, you'll get a HttpURLConnection as a return object. This class has a setRequestMethod method to specify which HTTP method you want to use.
If you want to do more sophisticated stuff you're probably better off using a library like Jakarta HttpClient.