All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ably.lib.network.DefaultHttpCall Maven / Gradle / Ivy

There is a newer version: 1.2.47
Show newest version
package io.ably.lib.network;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.NoRouteToHostException;
import java.net.Proxy;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

class DefaultHttpCall implements HttpCall {
    private final Proxy proxy;
    private final HttpRequest request;
    private HttpURLConnection connection;

    DefaultHttpCall(HttpRequest request, Proxy proxy) {
        this.request = request;
        this.proxy = proxy;
    }

    @Override
    public HttpResponse execute() {
        URL url = request.getUrl();
        try {
            connection = (HttpURLConnection) url.openConnection(proxy);
            /* prepare connection */
            connection.setRequestMethod(request.getMethod());
            connection.setConnectTimeout(request.getHttpOpenTimeout());
            connection.setReadTimeout(request.getHttpReadTimeout());
            connection.setDoInput(true);

            for (Map.Entry> entry : request.getHeaders().entrySet()) {
                String headerName = entry.getKey();
                List values = entry.getValue();
                for (String headerValue : values) {
                    connection.setRequestProperty(headerName, headerValue);
                }
            }

            /* prepare request body */
            if (request.getBody() != null) {
                byte[] body = prepareRequestBody(request.getBody());
                writeRequestBody(body);
            }

            return readResponse();
        } catch (ConnectException | SocketTimeoutException | UnknownHostException | NoRouteToHostException fce) {
            throw new FailedConnectionException(fce);
        } catch (IOException ioe) {
            throw new RuntimeException(ioe);
        } finally {
            cancel();
        }
    }

    @Override
    public void cancel() {
        if (connection != null) {
            connection.disconnect();
        }
    }

    /**
     * Emit the request body for an HTTP request
     */
    private byte[] prepareRequestBody(HttpBody requestBody) throws IOException {
        connection.setDoOutput(true);
        byte[] body = requestBody.getContent();
        int length = body.length;
        connection.setFixedLengthStreamingMode(length);
        return body;
    }


    private void writeRequestBody(byte[] body) throws IOException {
        OutputStream os = connection.getOutputStream();
        os.write(body);
    }

    private HttpResponse readResponse() throws IOException {
        HttpResponse.HttpResponseBuilder builder = HttpResponse.builder();
        int statusCode = connection.getResponseCode();

        builder
            .code(statusCode)
            .message(connection.getResponseMessage());

        /* Store all header field names in lower-case to eliminate case insensitivity */
        Map> caseSensitiveHeaders = connection.getHeaderFields();
        Map> headers = new HashMap<>(caseSensitiveHeaders.size(), 1f);

        for (Map.Entry> entry : caseSensitiveHeaders.entrySet()) {
            if (entry.getKey() != null) {
                headers.put(entry.getKey().toLowerCase(Locale.ROOT), entry.getValue());
            }
        }

        builder.headers(headers);

        if (statusCode == HttpURLConnection.HTTP_NO_CONTENT) {
            return builder.build();
        }

        String contentType = connection.getContentType();
        int contentLength = connection.getContentLength();

        InputStream is = null;
        try {
            is = connection.getInputStream();
        } catch (Throwable ignored) {}

        if (is == null) is = connection.getErrorStream();

        try {
            byte[] body = readInputStream(is, contentLength);
            builder.body(new HttpBody(contentType, body));
        } catch (NullPointerException e) {
            /* nothing to read */
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
        }

        return builder.build();
    }

    private byte[] readInputStream(InputStream inputStream, int bytes) throws IOException {
        /* If there is nothing to read */
        if (inputStream == null) {
            throw new NullPointerException("inputStream == null");
        }

        int bytesRead = 0;

        if (bytes == -1) {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4 * 1024];
            while ((bytesRead = inputStream.read(buffer)) > -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            return outputStream.toByteArray();
        } else {
            int idx = 0;
            byte[] output = new byte[bytes];
            while ((bytesRead = inputStream.read(output, idx, bytes - idx)) > -1) {
                idx += bytesRead;
            }

            return output;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy