5

POST request gives FileNotFoundException for the URL

I am making an Http POST request to a Url https://nitos.gr in android.

The url has not domain name. Stackoverflow does not allow me to include URL with numbers in my text, so i just write a random url https://nitos.gr for having an example.

I get a 400 response code, and print the getErrorStream() giving libcore.net.http.UnknownLengthHttpInputStream@41eba330

However, i perform succesfully HTTP GET request. The url is https, thus i have a fake trust manager allowing all SSL connections.

In summary:

Protocol: HTTPS

GET Request: successful

POST Request: Fails

Request code: 400

Error message: java.io.FileNotFoundException: https://nitos.gr

ErrorStream: java.io.FileNotFoundException: https://nitos.gr

The method performing the POST Request follows:

public void setTestbedData(String path, String data) {
        HttpURLConnection con = null;

        try {
            con = (HttpURLConnection) ( new URL(Constants.BASE_URL + path)).openConnection();
             // If you invoke the method setDoOutput(true) on the URLConnection, it will always use the POST method.
            con.setRequestMethod("POST");
            con.setDoInput(true);
            con.setDoOutput(true);

            con.setRequestProperty("Accept", "application/json");
            con.setRequestProperty("Content-Type", "application/json");

            Log.i("data", data);    

            OutputStream outputStream = con.getOutputStream();
            outputStream.write(data.getBytes());
            outputStream.flush();

            Log.w("RESPONSE CODE", "code " + con.getResponseCode());

            Log.w("this is connection ",""+con); 
            InputStream errorstream = con.getErrorStream();             
            Log.w("GetErrorStream  ", ""+errorstream);

            InputStream _is;
            if (con.getResponseCode() >= 400) {  
                _is = con.getInputStream();  
            } else {  

                _is = con.getErrorStream();  

                String result = getStringFromInputStream(_is);
                Log.i("Error != 400", result);
            }


            if (con.getResponseCode() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                    + con.getResponseCode());
            }



            BufferedReader responseBuffer = new BufferedReader(new InputStreamReader((con.getInputStream())));

            String output;
            Log.i("TestbedHttpClient","Output from Server:");
            while ((output = responseBuffer.readLine()) != null) {
                Log.i("Output",output);
            }

            con.disconnect();

            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

    }

The error messages:

RESPONSE CODE(18936): code 400 libcore.net.http.HttpsURLConnectionImpl$HttpUrlConnectionDelegate:https://nitos.gr GetErrorStream(18936): libcore.net.http.UnknownLengthHttpInputStream@41eba330 System.err(18936): java.io.FileNotFoundException: https://nitos.gr System.err(18936): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:186)

zoe vas
  • 281
  • 9
  • 25
  • Don't print the error-stream, but read it and print the characters from error-stream. This would be great to help you. BTW you could put some effort to format your post so we can read it easily. – hgoebl Aug 23 '14 at 18:27
  • 1
    Sorry, what do you mean by printing only characters? InputStream errorstream = con.getErrorStream(); Log.w("GetErrorStream ", ""+errorstream); This is not right? – zoe vas Aug 23 '14 at 18:57
  • To get the error-stream visible, you have to deal with it the same way you later read the content of the input-stream (via `BufferedReader`). Then you will see what the server says. This will be only a tiny step further to know what you've made wrong... – hgoebl Aug 24 '14 at 07:47

2 Answers2

5

Replace following code

        Log.w("this is connection ",""+con); 
        InputStream errorstream = con.getErrorStream();             
        Log.w("GetErrorStream  ", ""+errorstream);

        InputStream _is;
        if (con.getResponseCode() >= 400) {  
            _is = con.getInputStream();  
        } else {  

            _is = con.getErrorStream();  

            String result = getStringFromInputStream(_is);
            Log.i("Error != 400", result);
        }

with

        InputStream _is;
        if (con.getResponseCode() / 100 == 2) { // 2xx code means success
            _is = con.getInputStream();  
        } else {  

            _is = con.getErrorStream();  

            String result = getStringFromInputStream(_is);
            Log.i("Error != 2xx", result);
        }

Or in other words: It doesn't make sense to read from getInputStream() when HTTP status code is greater than or equal to 400. It's not that simple, maybe you have to deal with some 3xx codes as well. Have a look at List of HTTP status codes.

A last word: if you find HttpURLConnection cumbersome to use, you could use one of the abstraction libraries listed here.

hgoebl
  • 12,637
  • 9
  • 49
  • 72
  • you can simplify the if (con.getResponseCode() / 100 == 2) to if *(con.getResponseCode() == 200)* – Ranjithkumar Feb 14 '17 at 14:21
  • No, this is not what I want. It should be true for 204 (as an example), too. – hgoebl Feb 14 '17 at 14:23
  • It _does_ make sense to read from `getInputStream()` if the status code isn't successful. What if the server sends back more information with the response? Even just for debugging it would be great to see what the response body was. – Jans Rautenbach Jul 19 '18 at 10:37
  • 1
    @GeorgeRautenbach you're basically right. But you have to read from `con.getErrorStream()` instead of `con.getInputStream()`. – hgoebl Jul 23 '18 at 08:19
1

Finally, I could not perform POST Request due to the fact that the server has authentication. So, there is no problem with the configuration of the POST Request. Thus, now i should find a way to attach a certificate to the REST Call to the server.

zoe vas
  • 281
  • 9
  • 25