I've came up with the following problem. In my application I need to post an XML file to a server and wait for it's reply. I've achieved the above by using Apache HttpClient:
create the xml
using HttpClient and Post to post it to the server
The server initially responded with a 302 (Object moved), so I used LaxRedirectStrategy to be able to follow the redirect. I wrap the response in a StringBuffer and then push it into a new tab of the browser. Everything works fine, the tab shows the complete response from that server but every action in that page is not associated to the URL of the server response but to my main application. So, for example, if my application is on https://myapplication.com and the server is on https://theotherserver.com (+ /redirect for the redirect), each action on the page (i.e. /action) leads to https://myapplication.com/action and not to https://theotherserver.com/action.
In my page I have a button where this process starts. When you click it, it executes:
jQuery('input#button').on
(
'click',
function ()
{
jQuery.ajax
(
{
url: 'myURL.do',
data: {data: mydata},
method: 'POST',
success: function(data)
{
if (data.success == 'true')
{
var w = window.open('tab', windowname');
w.document.write(data.result);
w.document.close();
w.focus();
}
else
{
alert(data.error);
}
}
});
});
the .do executes the following:
public ResponseEntity<Map<String, String>> myMethod(HttpServletRequest request, HttpServletResponse response) throws ParserConfigurationException
{
Map<String, String> respData = new HashMap<String, String>();
try
{
String myXML = prepareMyXMLFile();
String result = sendMyXMLFile(myXML);
respData.put("success", String.valueOf(true));
respData.put("result", result);
return new ResponseEntity<Map<String, String>>(respData, HttpStatus.OK);
}
catch (Exception e)
{
respData.put("success", String.valueOf(false));
respData.put("error", String.valueOf(e));
return new ResponseEntity<Map<String, String>>(respData, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
and finally sendMyXMLFile():
private String sendMyXML(String myXML)
{
try
{
HttpClient client = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
HttpPost post = new HttpPost("myURL");
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("xml", myXML));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new
InputStreamReader(response.getEntity().getContent()));
StringBuffer responseResult = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null)
{
responseResult.append(line);
}
return responseResult.toString();
}
catch (IOException | TransformerException e)
{
//log error
}
return null;
}
What do I need to do to use the response URL as the base URL in the other tab?
Any help is appreciated. Thanks
Related
I use a simple WebServer from http://www.java2s.com/Code/Java/Network-Protocol/AverysimpleWebserverWhenitreceivesaHTTPrequestitsendstherequestbackasthereply.htm
and Android code from Sending json object via http post method in android
In my main Activity:
AsyncT asyncT = new AsyncT();
asyncT.execute();
Class:
class AsyncT extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... params) {
try {
URL url = new URL(""); //Enter URL here
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST"); // here you are telling that it is a POST request, which can be changed into "PUT", "GET", "DELETE" etc.
httpURLConnection.setRequestProperty("Content-Type", "application/json"); // here you are setting the `Content-Type` for the data you are sending which is `application/json`
httpURLConnection.connect();
JSONObject jsonObject = new JSONObject();
jsonObject.put("para_1", "arg_1");
DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
wr.writeBytes(jsonObject.toString());
wr.flush();
wr.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
The connection is established without any errors ("HostConnection::get() New Host Connection established"). However, I am not able to get in my Java server any information from the request. When I read from input stream
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println(in);
I get java.io.BufferedReader#4d7hge12
And this outputs nothing:
String line;
while ((line = in.readLine()) != null) {
if (line.length() == 0)
break;
System.out.println(line);
}
Don't re-invent the wheel and use a library for this.
For example okhttp:
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
If you want to call a REST-API you can use retrofit (which is build ontop of okhttp)
Assuming you're doing this as a learning exercise, so using another library isn't what you're looking for, I would suggest a couple of things:
(1) install Wireshark and see what the actual response coming back the server is, does it look sensible?
(2) break that line of code out into separate lines, is the InputStream / InputStreamReader null?
I can't seem to get my PHP page to display the data I have sent using a http client in Android. All I need now is displaying it in PHP which seems to be a challenge, I know I have done something wrong.
Any guidance would be much appreciated. I have tried everything from var_dump($_SERVER) to json_decode to display it in PHP. Is it even possible to display it on a PHP page?
private class Connection extends AsyncTask{
#Override
protected Object doInBackground(Object[] objects){
try{
PostData(R.id.fullscreen_content, 3);
}
catch(IOException exception){
exception.printStackTrace();
}
return null;
}
}
protected void PostData(Integer Question_ID,Integer ResponseChosen_ID) {
URL url = new URL("http://10.0.2.2:443/SwlLogin.php");
HttpURLConnection conn =(HttpURLConnection)url.openConnection();
conn.setDoOutput(true);
HttpClient httpClient = new DefaultHttpClient();
HttpGet post = new HttpGet(conn.getURL().toString());
post.setHeader("Content-type","application/json");
conn.connect();
Date date = new Date();
SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd", Locale.UK);
SimpleDateFormat time = new SimpleDateFormat("HH:mm:ss",Locale.UK);
String nowDate = dt.format(date);
String nowTime = time.format(date);
String phpDate = nowDate;
String phpTime = nowTime;
ArrayList<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("Question ID", Question_ID.toString()));
params.add(new BasicNameValuePair("Response_Chosen_ID", ResponseChosen_ID.toString()));
params.add(new BasicNameValuePair("TimestampDate", phpDate));
params.add(new BasicNameValuePair("time", phpTime));
JSONArray array = new JSONArray();
array.put(params);
post.setHeader("postData", params.toString());
post.getParams().setParameter("JSON", params);
HttpParams var = httpClient.getParams();
var.setParameter("GET",params);
HttpResponse response = httpClient.execute(post);
OutputStreamWriter write = new OutputStreamWriter(conn.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuilder builder = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null){
builder.append(line);
}
Log.d("Response:", builder.toString());
builder.toString();
reader.close();
public void happy_click(View view) throws IOException {
try{
new Connection().execute();
report_success();
}
catch(Exception exception){
messageBox("Response was not successful","Failed to process response" + exception.getMessage());
}
}
you can not run this code on the UI thread or you will get a NetworkRequestOnUIThread exception. you have to do this on a different thread.
try using AsyncTask via
private class Uploader extends AsyncTask<Void,Void,Void>{
protected void doInBackground(){
// do network request here
}
private void onPostExecute(){
// handle UI updates here as is on ui Thread
}
}
or you could look at using OkHTTP library which I recommend highly. to do this download the jar from okHttp. add it to you libs folder then you can do network call like this
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
JSONObject parcel = new JSONObject();
try{
parcel.put("email", emailEdit.getText().toString());
parcel.put("password", passwordEdit.getText().toString());
parcel.put("device", "Android");
parcel.put("hash", "1234");;
}catch (JSONException e ){
e.printStackTrace();
}
RequestBody body = RequestBody.create(JSON, parcel.toString());
Request request = new Request.Builder()
.header("Content-Type", "application/json")
.url("YOURURL")
.post(body)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
if (null != e) {e.printStackTrace();}
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (null != response && response.message().equals(Constants.KEY_OK)) {
JSONObject serverResponse;
try{
serverResponse = new JSONObject(response.body().string());
if(serverResponse.getBoolean(Constants.KEY_SUCCESS)){
Constants.getInstance().setToken(serverResponse.getString(Constants.KEY_TOKEN));
moveToHomePage();
}else{
showLoginFail();
}
}catch (JSONException e ){
e.printStackTrace();
}
response.body().close();
} else {
showLoginFail();
}
}
});
also make sure you have
<uses-permission android:name="...permision.INTERNET">
in your manifest file
In my app, I need to send all sorts of POST requests to a server. some of those requests have responses and others don't.
this is the code I'm using to send the requests:
private static final String TAG = "Server";
private static final String PATH = "http://10.0.0.2:8001/data_connection";
private static HttpResponse response = null;
private static StringEntity se = null;
private static HttpClient client;
private static HttpPost post = null;
public static String actionKey = null;
public static JSONObject sendRequest(JSONObject req) {
try {
client = new DefaultHttpClient();
actionKey = req.getString("actionKey");
se = new StringEntity(req.toString());
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_ENCODING, "application/json"));
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post = new HttpPost(PATH);
post.setEntity(se);
Log.d(TAG, "http request is being sent");
response = client.execute(post);
Log.d(TAG, "http request was sent");
if (response != null) {
InputStream in = response.getEntity().getContent();
String a = convertFromInputStream(in);
in.close();
return new JSONObject(a);
}
} catch (UnsupportedEncodingException e) {
Log.d(TAG, "encoding request to String entity faild!");
e.printStackTrace();
} catch (ClientProtocolException e) {
Log.d(TAG, "executing the http POST didn't work");
e.printStackTrace();
} catch (IOException e) {
Log.d(TAG, "executing the http POST didn't work");
e.printStackTrace();
} catch (JSONException e) {
Log.d(TAG, "no ActionKey");
e.printStackTrace();
}
return null;
}
private static String convertFromInputStream(InputStream in)
throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
return (sb.toString());
}
This is the code for the AsyncTask class that sends the request:
class ServerRequest extends AsyncTask<JSONObject, Void, JSONObject> {
#Override
protected JSONObject doInBackground(JSONObject... params) {
JSONObject req = params[0];
JSONObject response = Server.sendRequest(req);
return response;
}
#Override
protected void onPostExecute(JSONObject result) {
// HANDLE RESULT
super.onPostExecute(result);
}
}
my problem starts when the server doesn't return a response. the AsyncTask thread stays open even after the work is done because the HTTPClient never closes the connection.
Is there a way to not wait for a response? this is something that will definitely add a lot of overhead to the server since all the Android apps trying to connect to it will keep the connection alive, and will probably cause many problems on the app itself.
Basically, what I'm looking for is a method that will allow me to send to POST message and kill the connection right after the sending of the request since there is no response coming my way.
Just, Set ConnectionTimeOut with HttpClient Object, (Code is for your understanding in your case it may be different)
int TIMEOUT_MILLISEC = 30000;
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);
HttpClient httpclient = new DefaultHttpClient(httpParams);
HttpPost httppost = new HttpPost(url);
httppost.addHeader("Content-Type", "application/json");
Now, It will terminate the Connection after TimeoOut you defined. But be sure this will throw TimeOutException so You have to handle this exception in your HttpRequest.. (Use Try -catch)
EDIT: Or you can use HttpRequestExecutor class.
From class HttpRequestExecutor of package org.apache.http.protocol
protected boolean canResponseHaveBody (HttpRequest request, HttpResponse response)
Decide whether a response comes with an entity. The implementation in this class is based on RFC 2616. Unknown methods and response codes are supposed to indicate responses with an entity.
Derived executors can override this method to handle methods and response codes not specified in RFC 2616.
I'm trying to write a POST call to Google Translate with Jersey 1.5. This is my code:
package main;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import javax.ws.rs.core.MultivaluedMap;
public class Main {
private static String GOOGLE_TRANSLATE_URL = "https://www.googleapis.com/language/translate/v2";
private static String translateString(String sourceString, String sourceLanguage, String targetLanguage) {
String response;
Client c = Client.create();
WebResource wr = c.resource(GOOGLE_TRANSLATE_URL);
MultivaluedMap<String, String> params = new MultivaluedMapImpl();
params.add("q", sourceString);
params.add("source", sourceLanguage);
params.add("target", targetLanguage);
params.add("key", "xxxx");
wr.header("X-HTTP-Method-Override", "GET");
response = wr.post(String.class, params);
return response;
}
public static void main(String[] args) {
System.out.println(translateString("Hello", "en", "sv"));
}
}
When I run this, all I get back is this: com.sun.jersey.api.client.UniformInterfaceException: POST https://www.googleapis.com/language/translate/v2 returned a response status of 404.
I've managed to accomplish this with a simple cURL command like so:
curl --header "X-HTTP-Method-Override: GET" -d key=xxxx -d q=Hello -d source=en -d target=sv https://www.googleapis.com/language/translate/v2
Thanks in advance!
I suspect that POST with zero Content-Length is not something a normal HTTP server will accept. The RFC does not define this case, but the main assumption of POST is that you're sending a message body.
Looking at the Google API, they mention the following
You can also use POST to invoke the API if you want to send more data in a single request. The q parameter in the POST body must be less than 5K characters. To use POST, you must use the X-HTTP-Method-Override header to tell the Translate API to treat the request as a GET (use X-HTTP-Method-Override: GET).
This means that instead of adding q, source and target parameters in the URL, you need to do so in the POST body. I'm not familiar with the Jersey API, from a brief look you just need to add params as an explicit second parameter to the .post call, remove the queryParams() call, and set the Content-Length properly.
I think the best and correct way is this
private static final String gurl = "www.googleapis.com";
private static final String gpath = "/language/translate/v2/detect";
public String detectLangGooglePost(String text) throws SystemException {
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("key", key));
URI uri;
try {
uri = URIUtils.createURI("https", gurl, -1, gpath, URLEncodedUtils.format(qparams, "UTF-8"), null);
} catch (URISyntaxException e) {
throw new SystemException("Possibly invalid URI parameters", e);
}
HttpResponse response = getPostResponse(uri, text);
StringBuilder builder = getBuilder(response);
String language = getLanguage(builder);
return language;
}
private HttpResponse getPostResponse(URI uri, String text) throws SystemException {
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("q", text));
HttpResponse response;
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(uri);
httpPost.addHeader("X-HTTP-Method-Override", "GET");
try {
httpPost.setEntity(new UrlEncodedFormEntity(qparams));
response = httpclient.execute(httpPost);
} catch (Exception e) {
throw new SystemException("Problem when executing Google get request", e);
}
int sc = response.getStatusLine().getStatusCode();
if (sc != HttpStatus.SC_OK)
throw new SystemException("google status code : " + sc);
return response;
}
private StringBuilder getBuilder(HttpResponse response) throws SystemException {
HttpEntity entity = response.getEntity();
if (entity == null)
throw new SystemException("response entity null");
StringBuilder builder = new StringBuilder();
BufferedReader in = null;
String str;
try {
in = new BufferedReader(new InputStreamReader(entity.getContent()));
while ((str = in.readLine()) != null)
builder.append(str);
} catch (IOException e) {
throw new SystemException("Reading input stream of http google response entity problem", e);
} finally {
IOUtils.closeQuietly(in);
}
if (builder.length() == 0)
throw new SystemException("content stream of response entity empty has zero length");
return builder;
}
private String getLanguage(StringBuilder builder) throws SystemException {
JSONObject data = null;
JSONArray detections = null;
String language = null;
JSONObject object = (JSONObject) JSONValue.parse(builder.toString());
if (object == null)
throw new SystemException("JSON parsing builder object returned null");
if (object.containsKey("data") == false)
throw new SystemException("JSONObject doesn't contain data key");
data = (JSONObject) object.get("data");
detections = (JSONArray) data.get("detections");
if (detections == null)
throw new SystemException("JSON detections is null");
JSONObject body = (JSONObject) ((JSONArray) detections.get(0)).get(0);
if (body == null)
throw new SystemException("detections body is null");
if (body.containsKey("language") == false)
throw new SystemException("language key is null");
language = (String) body.get("language");
if (language == null || language.equals(unknown))
throw new SystemException("Google lang detection - resulting language : " + language);
return language;
}
I was able to send very long text like this!
Client:
MultivaluedMap<String,String> formData = new MultivaluedMapImpl();
formData.add("text", text);
WebResource resource = Client.create().resource(getBaseURI()).path("text2rdf");
return resource.type("application/x-www-form-urlencoded").post(String.class, formData);
Server:
#POST
#Produces("text/whatever")
public String textToRdf (
#FormParam("text") String text) {...
I switched to Apache HttpClient 4.x and solved it like this instead:
public class Main {
private static String GOOGLE_TRANSLATE_URL = "https://www.googleapis.com/language/translate/v2";
private static String GOOGLE_API_KEY = "xxxx";
private static String translateString(String sourceString, String sourceLanguage, String targetLanguage) {
String response = null;
// prepare call
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(GOOGLE_TRANSLATE_URL+"?q="+sourceString+"&source="+sourceLanguage+"&target="+targetLanguage+"&key="+GOOGLE_API_KEY);
post.setHeader("X-HTTP-Method-Override", "GET");
try {
// make the call
ResponseHandler<String> responseHandler = new BasicResponseHandler();
response = client.execute(post, responseHandler);
} catch (IOException e) {
// todo: proper error handling
}
return response;
}
public static void main(String[] args) {
System.out.println(translateString("hello", "en", "sv"));
}
}
Don't really know why this works better than Jersey, but it works. Thanks for trying to help!
I've written some code for my Android device to login to a web site over HTTPS and parse some data out of the resulting pages. An HttpGet happens first to get some info needed for login, then an HttpPost to do the actual login process.
The code below works great in a Java project within Eclipse which has the following JAR files on the build path: httpcore-4.1-beta2.jar, httpclient-4.1-alpha2.jar, httpmime-4.1-alpha2.jar, and commons-logging-1.1.1.jar.
public static MyBean gatherData(String username, String password) {
MyBean myBean = new MyBean();
try {
HttpResponse response = doHttpGet(URL_PAGE_LOGIN, null, null);
System.out.println("Got login page");
String content = EntityUtils.toString(response.getEntity());
String token = ContentParser.getToken(content);
String cookie = getCookie(response);
System.out.println("Performing login");
System.out.println("token = "+token +" || cookie = "+cookie);
response = doLoginPost(username,password,cookie, token);
int respCode = response.getStatusLine().getStatusCode();
if (respCode != 302) {
System.out.println("ERROR: not a 302 redirect!: code is \""+ respCode+"\"");
if (respCode == 200) {
System.out.println(getHeaders(response));
System.out.println(EntityUtils.toString(response.getEntity()).substring(0, 500));
}
} else {
System.out.println("Logged in OK, loading account home");
// redirect handler and rest of parse removed
}
}catch (Exception e) {
System.out.println("ERROR in gatherdata: "+e.toString());
e.printStackTrace();
}
return myBean;
}
private static HttpResponse doHttpGet(String url, String cookie, String referrer) {
try {
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
client.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
HttpGet httpGet = new HttpGet(url);
httpGet.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
httpGet.setHeader(HEADER_USER_AGENT,HEADER_USER_AGENT_VALUE);
if (referrer != null && !referrer.equals("")) httpGet.setHeader(HEADER_REFERER,referrer);
if (cookie != null && !cookie.equals("")) httpGet.setHeader(HEADER_COOKIE,cookie);
return client.execute(httpGet);
} catch (Exception e) {
e.printStackTrace();
throw new ConnectException("Failed to read content from response");
}
}
private static HttpResponse doLoginPost(String username, String password, String cookie, String token) throws ClientProtocolException, IOException {
try {
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
client.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
HttpPost post = new HttpPost(URL_LOGIN_SUBMIT);
post.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
post.setHeader(HEADER_USER_AGENT,HEADER_USER_AGENT_VALUE);
post.setHeader(HEADER_REFERER, URL_PAGE_LOGIN);
post.setHeader(HEADER_COOKIE, cookie);
post.setHeader("Content-Type","application/x-www-form-urlencoded");
List<NameValuePair> formParams = new ArrayList<NameValuePair>();
formParams.add(new BasicNameValuePair("org.apache.struts.taglib.html.TOKEN", token));
formParams.add(new BasicNameValuePair("showLogin", "true"));
formParams.add(new BasicNameValuePair("upgrade", ""));
formParams.add(new BasicNameValuePair("username", username));
formParams.add(new BasicNameValuePair("password", password));
formParams.add(new BasicNameValuePair("submit", "Secure+Log+in"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams,HTTP.UTF_8);
post.setEntity(entity);
return client.execute(post);
} catch (Exception e) {
e.printStackTrace();
throw new ConnectException("ERROR in doLoginPost(): "+e.getMessage());
}
}
The server (which is not under my control) returns a 302 redirect when the login was successful, and 200 if it fails and re-loads the login page. When run with the above JAR files I get the 302 redirect, however if I run the exact same code from an Android project with the 1.6 Android JAR file on the build path I get the 200 response from the server. I get the same 200 response when running the code on my 2.2 device.
My android application has internet permissions, and the HttpGet works fine. I'm assuming that the problem lies in the fact that HttpPost (or some other class) is different in some significant way between the Android JAR version and the newer Apache versions.
I've tried adding the Apache libraries to the build path of the Android project, but due to the duplicate classes I get messages like: INFO/dalvikvm(390): DexOpt: not resolving ambiguous class 'Lorg/apache/http/impl/client/DefaultHttpClient;' in the log. I've also tried using a MultipartEntity instead of the UrlEncodedFormEntity but I get the same 200 result.
So, I have a few questions:
Can I force the code running under Android to use the newer Apache libraries in preference to the Android versions?
If not, does anyone have any ideas how can I alter my code so that it works with the Android JAR file?
Are there any other, totally different approaches to doing an HttpPost in Android?
Any other ideas?
I've read a lot of posts and code, but I'm not getting anywhere.
I have now given up on getting the HttpClient route to give the expected response from the server when run on Android. Instead I rewrote the doPost method above to use an HttpsURLConnection instead. Here's the new (working) version in the hope that it's useful to someone.
private static LoginBean altPost(String username, String password, String cookie, String token){
LoginBean loginBean = new LoginBean();
HttpsURLConnection urlc = null;
OutputStreamWriter out = null;
DataOutputStream dataout = null;
BufferedReader in = null;
try {
URL url = new URL(URL_LOGIN_SUBMIT);
urlc = (HttpsURLConnection) url.openConnection();
urlc.setRequestMethod("POST");
urlc.setDoOutput(true);
urlc.setDoInput(true);
urlc.setUseCaches(false);
urlc.setAllowUserInteraction(false);
urlc.setRequestProperty(HEADER_USER_AGENT, HEADER_USER_AGENT_VALUE_FF);
urlc.setRequestProperty("Cookie", cookie);
urlc.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
String output = "org.apache.struts.taglib.html.TOKEN="+ URLEncoder.encode(token, HTTP.UTF_8)
+"&showLogin=true&upgrade=&username="+ URLEncoder.encode(username, HTTP.UTF_8)
+"&password="+ URLEncoder.encode(password, HTTP.UTF_8)+"&submit="
+URLEncoder.encode("Secure+Log+in", HTTP.UTF_8);
dataout = new DataOutputStream(urlc.getOutputStream());
// perform POST operation
dataout.writeBytes(output);
// get response info
loginBean.setResponseCode(urlc.getResponseCode());
// get required headers
String headerName = null;
StringBuffer newCookie = new StringBuffer(100);
String redirectLocation = "";
for (int i=1; (headerName = urlc.getHeaderField(i)) != null;i++) {
if (headerName.indexOf(COOKIE_VALUE_SESSION) > -1) {
if (newCookie.length() > 0) {newCookie.append("; ");}
newCookie.append(headerName);
}
if (headerName.indexOf(COOKIE_VALUE_AUTH) > -1) {
if (newCookie.length() > 0) {newCookie.append("; ");}
newCookie.append(headerName);
}
if (headerName.indexOf("https://") > -1) {
redirectLocation = headerName;
}
}
loginBean.setCookie(newCookie.toString());
loginBean.setRedirectUrl(redirectLocation);
in = new BufferedReader(new InputStreamReader(urlc.getInputStream()),8096);
String response;
// write html to System.out for debug
while ((response = in.readLine()) != null) {
System.out.println(response);
}
in.close();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return loginBean;
}
I still have no idea why the HttpClient way didn't work properly.
To avoid the collisions, use this JAR file for httpclient:
httplib
And this post would also be very useful:
An answer to Stack Overflow question Apache HTTP client or URLConnection
Is it possible that this website does user-agent detection and actually returns different results because it's Android? Given that 200 implies success, why must it give a 302 instead of a 200? Have you printed out the result that you get when it returns a 200, and does it give any additional information?
Check the RedirectHandler, override the default one and do some logging in it, I had problems with that when going to Android...