Question

While working on an application for android that uses web services I encounterd a bad request (response code 400) message when trying to retrieve some data in android versions 4.0.3 and 4.3. The perculiar thing however is that when sending the same request using the same code but on a device using android version 2.3.3 it works without any problems. I have also tried using httpGet instead of HttpsURLConnection, while this work for all versions it does not provide a solution as I need the added security.

My code is as follows:

private String executeRequest(String urlAddress)
{
    String responce = null;
    String msg = null;
    int error = 0;
    try {
        URL url = new URL(urlAddress);
        HttpsURLConnection  connection = (HttpsURLConnection)url.openConnection();
        SSLSocketFactory factory =  SecureSocketFactory.getSSLSocketFactory();
        connection.setSSLSocketFactory(factory);

        connection.setHostnameVerifier(new Verifier());
        connection.setDoOutput(true);
        connection.setDoInput(true);

        if (method == RequestMethod.POST)
        {
            connection.setRequestMethod("POST");
        }
        msg = connection.getResponseMessage();
        error = connection.getResponseCode();
        if ("OK".equals(msg))
        {
            InputStream content = (InputStream) connection.getContent();
            responce = convertStreamToString(content);
        }
        else
        {
            responce = "Error " + error;
        }
        connection.disconnect();

    } catch (Exception e) {
        responce = e.toString();
    }

    return responce;
}

And the code of SecureSocketFactory.getSSLSocketFactory():

public static SSLSocketFactory getSSLSocketFactory()
    throws IOException
{
    if(ssf_ == null)
    {
        javax.net.ssl.KeyManager kms[] = null;
        javax.net.ssl.TrustManager tms[] = null;
        SSLContext context = null;
        try
        {
            tms = CustomTrustManager.getTrustManagers();
            context = SSLContext.getInstance("TLS");
            context.init(kms, tms, null);
        }
        catch(GeneralSecurityException e)
        {
            IOException io = new IOException(e.getLocalizedMessage());
            io.setStackTrace(e.getStackTrace());
            throw io;
        }
        ssf_ = context.getSocketFactory();
    }
    return ssf_;
}

and the code of CustomTrustManager.getTrustManagers()

static TrustManager[] getTrustManagers(String trustStoreFile, String trustStorePW)
    throws NoSuchAlgorithmException, KeyStoreException
{
    String alg = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmFact = TrustManagerFactory.getInstance(alg);
    tmFact.init((KeyStore)null);
    TrustManager tms[] = tmFact.getTrustManagers();
    for(int i = 0; i < tms.length; i++)
        if(tms[i] instanceof X509TrustManager)
            tms[i] = new CustomTrustManager((X509TrustManager)tms[i]);

    return tms;
}

static TrustManager[] getTrustManagers()
    throws NoSuchAlgorithmException, KeyStoreException
{
    return getTrustManagers(null, null);
}

I have looked everywhere, but can't seem to find a solution please help.

Was it helpful?

Solution

I found my error, because do connection.setDoInput(true) it silencly sets my Requestmethod to post in version 4 which gives an error on the server causing it to return bad request.

apparently it does not set this in version 2, which explains why it does work there.

The following execute request method change fixed my code:

private String executeRequest(String urlAddress)
{
    String responce = null;
    String msg = null;
    int error = 0;
    try {
        URL url = new URL(urlAddress);
        HttpsURLConnection  connection = (HttpsURLConnection)url.openConnection();
        SSLSocketFactory factory =  SecureSocketFactory.getSSLSocketFactory();
        connection.setSSLSocketFactory(factory);

        connection.setHostnameVerifier(new Verifier());

        if (method == RequestMethod.POST)
        {
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");
        }
        else
        {
            connection.setDoInput(true);
            connection.setRequestMethod("GET");
        }
        msg = connection.getResponseMessage();
        error = connection.getResponseCode();
        if ("OK".equals(msg))
        {
            InputStream content = (InputStream) connection.getContent();
            responce = convertStreamToString(content);
        }
        else
        {
            responce = "Error " + error;
        }
        connection.disconnect();

    } catch (Exception e) {
        responce = e.toString();
    }

    return responce;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top