2

Trying to post to a restAPI using JAVA OKHttp.

My code looks as follows:

try {
            loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            client = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .addInterceptor(loggingInterceptor)
                .build();
            MediaType mediaType = MediaType.parse("app.lication/json");
            RequestBody body = RequestBody.create(mediaType, FileUtils.readFileToString(file));    
            Request request = new Request.Builder()
                    .url(restAPIUrl)
                    .post(body)
                    .addHeader("content-type", "application/json")
                    .addHeader("cache-control", "no-cache")
                    .build();

            Call call = client.newCall(request);
            call.execute();

            handleResponse(file, response.code());

        } catch (Exception e) {

            logger.severe("Http Request failed: " + e.getMessage());

        }

On my local development box (centos) that doesn't have firewall open to the restAPI, every thing behaves as expected. call.execute() throws an exception: Could not resolve host: Name or service not available.

On the production box (rhel), where firewall is open. The method call to client.newCall(request); just hangs indefinitely. (Before calling execute()) strace just shows the thread waiting.

I've verified i can reach the restAPI from command line with:

curl -X get https://restAPIUrl/index.html

The same jar is behaving differently on the two servers. I can't figure out why differences in server configuration would affect the newCall() (I would more expect it on execute) What could be the cause for newCall() hanging due to environment? Any help would be much appreciated.

thank you!


Update:

I found that it gets past the newCall() method if I override the defaultSocketFactory.

client = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .addInterceptor(loggingInterceptor)
                .setSocketFactory(new SocketFactory () {
                       @Override
                        public Socket createSocket(String s int i) thorws IOException, UnknownHostException {
                              return null;
                         }
                         .
                         .
                 })
                .build();

Why wouldn't the system properly allocate the socket for the client using defaultSocketFactory on the rhel env? (SELINUX disabled.)


Update 2: Resolution

In the end this issue was caused by no read permissions on 'local_policy.jar' in $JAVA_HOME/lib/security. (File didn't exist in my dev environment)

The nasty part was the permissions exception was being swallowed by the OKHttp API.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
brercia
  • 171
  • 1
  • 6
  • This is the same issue as: https://stackoverflow.com/questions/46321268/android-https-connection-to-aws-alive-json-hangs/55691675 – grebulon Apr 15 '19 at 14:52
  • Sorry should have updated this earlier. Not the same issue as above. See resolution in the question. – brercia Apr 16 '19 at 20:01

1 Answers1

1

Try to patch the security provider as described in "Update your security provider to protect against SSL exploits".

Just implement ProviderInstaller.installIfNeeded (or installIfNeededAsync)

grebulon
  • 7,697
  • 5
  • 42
  • 66