HTTP Post in C2DM giving SocketTimeoutException - java

I made an app. for Android which uses the C2DM service from Google. I
made a server simulator from some tutorials and it works fine. My
problem is, I tried to build a Java Servlet. From the Android device
it receives fine the message and saves the Registration ID, but when I
try to send a https POST request to the Google C2DM Server it always
gets a SocketTimeoutException : Timeout while fetching:
https://android.clients.google.com/c2dm/send.
I don't get why this is happening when the same works on the Android
device. Here is the code:
//The AuthToken from Google Client Login
String auth_key = TOKEN;
StringBuilder postDataBuilder = new StringBuilder();
//some parameters to pass, I've checked and it's correct, it's working
//with Fiddler
postDataBuilder.append(PARAM_REGISTRATION_ID).append("=").append(REGISTRATION_ID);
postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=").append("0");
postDataBuilder.append("&").append("data.payload").append("=").append(URLEncoder.encode(message, UTF8));
byte[] postData = postDataBuilder.toString().getBytes(UTF8);
URL url = new URL("https://android.clients.google.com/c2dm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
conn.setRequestProperty("Content-Length",Integer.toString(postData.length));
conn.setRequestProperty("Authorization", "GoogleLogin auth="+auth_key);
OutputStream out = conn.getOutputStream();
out.write(postData);
out.close();
int responseCode = conn.getResponseCode();
//here comes the error processing, but I can't reach it, because of
//the exception.
if (responseCode == 401 || responseCode == 403) {
//....
}
Thanks for your help :).

The first obvious thing to check is - if you have thought of this I apologise - are you behind a proxy server e.g. a company firewall? If so a timeout is exactly the symptom I'd expect with the above code. (This catches me out all the time!)
With the latter half of your code (from the HttpURLConnection declaration on), unmodified, I see a timeout; on my system (behind a company firewall), with two changes I get a 200 OK back:
addition of a proxy object passed to the HttpUrlConnection factory as follows:
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("...", 8080));
HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
accepting the C2DM server's certificate that wasn't trusted by my JVM. For test purposes I overrode the default hostname verifier and TrustManager as described in Trusting all certificates using HttpClient over HTTPS . For production you should look at a more secure solution.
Another thing I spotted; it doesn't seem to matter but http://code.google.com/android/c2dm/index.html#push says to post to https://android.apis.google.com/c2dm/send, not android.clients.google.com - just something to be aware of that might break in future.

I faced same problem and
I had tried :
URL url = new URL("http://android.apis.google.com/c2dm/send");
instead of :
URL url = new URL("https://android.apis.google.com/c2dm/send");
it worked for me.

Related

JAVA POST request and then redirect to it?

What I need to do is send POST request to specific URL with two parameters and when the request is sent, I need to redirect user to that link so that he would be able to access functionality.
So far, what I have managed to do from various examples is this:
private void postRemoteAdvisoryLink() throws IOException {
URL obj = new URL(KdrmApplicationContext.getRemoteAdvisoryUrlPath());
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setConnectTimeout(60000);
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
// For post only - start
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write(("?auth=ssor&TransportKey=" + ssorTransportKey).getBytes());
os.flush();
os.close();
int responseCode = con.getResponseCode();
}
The problem is that now I get connection time out when trying to execute OutputStream os = con.getOutputStream(); line. Also, I still have no idea how to redirect user when request is completed.
Any ideas?
Using the basic Java URL classes would require you to manually handle the details of HTTP protocol - it's better to use libraries like Apache Http Components, as they deal with the underlying protocols for you. Some examples including POST requests can be found on their website.
Given the original question, the Timeout is likely related to host not responding or your Java application being unable to connect to given URL (due to no proxy configuration for example).
If you want to redirect a request based on the answer, you need to check the response headers and http status - if the status is 302, then there should be a header called Location, which will contain the URL you should make another request to.
Before getting an OutputStream, also make sure to set the Content-Length header (and ideally the Content-Type header as well).

Build and use Cookie for token based authentication to gain access to api through openAM

Please excuse me if any of this sounds very stupid or inexperienced, however I have looked everywhere else and haven't been able to find a simple explanation as to how to properly implement this.
So far I have made a restful call to a server running on openAm; the call sends my user name and password credentials and returns to me a secure token. I then need to make another restful call to request certain json files in their api.
I understand that in my second restful call I need to somehow embed the token with it so the server knows that I am allowed to access the requested data. My question is what is the proper way to go about this. I have found/heard of multiple possibilities such as passing it in the header, parameters, or as a cookie, but each time my request is redirected to the log in url instead of returning my request.
From my understanding it appears the cookie method works best (if I'm wrong then please post a different method). So for openAm authentication, how do I properly build a cookie with my token. Once the cookie is built how do I embed that into the connection. Do I need to make a whole new connection or can I redirect my original connection with the cookie? Any help or advice is greatly appreciated.
Some of my code, using HttpURLConnection:
//takes url and builds our connection
String url = "http://some.url.net/openam/json/authenticate";
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("X-OpenAM-Username", name);
connection.setRequestProperty("X-OpenAM-Password", pass);
connection.setRequestProperty("Content-Type", "application/json");
//takes in the connections response
BufferedReader in = new BufferedReader(new InputStreamReader(response, "UTF-8"));
String output = in.readLine();
//this is to cut the token out of the response
int i = 14;
while(true){
if (output.charAt(i)=='"'){
break;
}
i++;
}
String token = output.substring(14,i);
//build our new connection and second call
url = "https://other.url.net/api/v1/resource/attributes";
HttpURLConnection request_conn = (HttpURLConnection) new URL(url).openConnection();
/*
request_conn.setRequestProperty("iPlanetDirectoryPro", token);
request_conn.setRequestMethod("POST");
request_conn.connect();
*/ //Tried to put the token through the header, doesnt work
/*
Cookie cookie;
cookie = new Cookie("iPlanetDirectoryPro", token);
cookie.setDomain(".di2e.net");
cookie.setPath("/");
cookie.setSecure(true);
request_conn.addCookie(cookie);//addCookie() doesnt work for a urlConection?
*/ //Tried building the cookie and adding it to the new conection

send http request from IIS to GCM using java

I am trying to send Json message from my [java application server] to [GCM]:
the java server app located on IIS server (Windows server 2008 R2).
here is my function:
public static String post(String apiKey, String json){
try{
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type:", "application/json");
conn.setRequestProperty("Authorization:", "key="+apiKey); // apiKey is valid browser apiKey.
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeUTF(json);
wr.flush();
wr.close();
/*I've deleted the respond check from the question*/
}
but I fail to send!, and does not get any message or exception.
I think that the server itself doesnt let me send http requests!
is this true? how to solve?
I recommend using the Sender and Message objects instead. The sample GCM server code uses those. Sample server code can be seen here.
If you really insist on handling the connection yourself, you can look at the underlying HttpURLConnection implementation of the Sender object here.
It does appear that there are certain differences between the Sender code and your request properties. Hope this helps.

Read session variable using HttpURLConnection

I am trying to log in to a website using an HttpURLConnection.
If the login is successful, the server sets user_id variable in the current session.
Using SO and the Google developer docs on the matter I have been able to POST my credentials to the server, but how do I get the user_id from the session now?
For reference here is my code:
String body = "user=chris&password=geheim";
HttpURLConnection conn = (HttpURLConnection) new URL(LOGIN_URL).openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setInstanceFollowRedirects(false);
conn.connect();
OutputStream out = conn.getOutputStream();
BufferedInputStream in = new BufferedInputStream(conn.getInputStream());
out.write(body.getBytes());
int response = conn.getResponseCode();
String s = "";
for (int c = in.read(); c != -1; c = in.read()) {
s += (char) c;
}
System.out.println(response);
System.out.println(s);
System.out.println(conn.getHeaderFields());
Note: to make it easier to read I've left out all exception handling and resource management. Also this is just trial code connecting to my localhost, so no worries about the hardcoded credentials and other insecurities.
Update
Okay, apparently my body is not getting submitted after all. When I do a console.log(util.inspect(req.body)) in my server code, it prints {}. I double-checked the request method and that is POST. What am I doing wrong?
Rewrote the code, and even though I think I did the exact same thing as before it's working now. Weird, but whatever.
The session where the user_id is stored, is kept on the server. All the client usually gets is a session-id in a session cookie (e.g. JSESSIONID) that is passed back to the server so the server can find the correct session and data again.
That's why you also can put large amounts of data into a user's session ... imagine all of that was actually passed to the client!
You can't, unless there is a co-operative active page in the server that will give it to you.

Java native browser login prompt

I am trying to make a HTTPS call using Java to a browser that uses the native login prompt.
http://blog.stevensanderson.com/2008/08/25/using-the-browsers-native-login-prompt/
Currently I'm using the below for HTTP and it works fine for other websites since I know the parameters to put in...however it fails for the above type of login (I am not sure how to capture the parameters...it's a login pop up..or if this is even the correct approach)....any ideas??..thanks
HttpUtility.sendPostRequest(requestURL, params);
String[] response = HttpUtility.readMultipleLinesRespone();
The server should respond to your first request with a WWW-Authenticate header and a status of 401. The header will contain details of the kind of authentication it's expecting.
Then you can try again after adding an Authorization header to your request in the correct format.
#alex: OK...I managed to make the HTTPS connection following your suggestion with this:
URL url = new URL("https://www.example.com/Login");
URLConnection urlConnection = url.openConnection();
urlConnection.setRequestProperty("Authorization", "Basic " + authString);
InputStream is = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
//then I read the input stream..
But when I tried to make another connection (say go to a different page after login) with this code in another method...taking URLConnection as the parameter:
//Below is in a method called account(URLConnection urlConnection)
URL url = new URL("https://www.example.com/account.aspx");
urlConnection = url.openConnection();
InputStream is = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
//again I read the input stream..
...it throws the below exception...same exception before logging in..how can I rectify?
Server returned HTTP response code: 401 for URL: https://www.example.com/account.aspx
You have probably moved on from this problem, but I recently had an issue that involved achieving functionality similar to the browser's native login prompt. I have solved it and written a post about it. Steven Sanderson's post was helpful for me too, in helping me understand certain concepts.
http://captaindanko.blogspot.com.au/2015/04/how-does-browsers-native-login-prompt.html

Categories

Resources