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

io.github.saoxuequ.http.request.light.UrlConnectionHttpExecutor Maven / Gradle / Ivy

package io.github.saoxuequ.http.request.light;

import io.github.saoxuequ.http.request.core.EntityRequest;
import io.github.saoxuequ.http.request.core.Request;
import io.github.saoxuequ.http.request.utils.HeaderUtils;
import io.github.saoxuequ.http.request.utils.NamedThreadFactory;
import io.github.saoxuequ.http.request.utils.Preconditions;
import io.github.saoxuequ.http.request.core.HttpExecutor;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

public class UrlConnectionHttpExecutor implements HttpExecutor {

    private final ExecutorService asyncPool;

    public UrlConnectionHttpExecutor(ExecutorService asyncPool) {
        this.asyncPool = asyncPool;
    }

    public UrlConnectionHttpExecutor() {
        this(new ThreadPoolExecutor(
                2, 2, 2, TimeUnit.SECONDS,
                new ArrayBlockingQueue(100),
                new NamedThreadFactory("http-async-pool"),
                new ThreadPoolExecutor.AbortPolicy()));
    }

    @Override
    public  R execute(EntityRequest request, int connectTimeout, int readTimeout) {
        try {
            URI uri = request.getUri();
            HttpURLConnection connection = openHttpConnection(uri.toURL());

            connection.setConnectTimeout(connectTimeout);
            connection.setReadTimeout(readTimeout);
            connection.setDoInput(true);

            connection.setDoOutput(true);
            connection.setChunkedStreamingMode(4096);

            try {
                connection.setRequestMethod(request.getMethod());
            } catch (ProtocolException e) {
                throw new RuntimeException(e);
            }

            setHeaders(uri, request.getHeaders(), connection);
            connection.connect();

            if (connection.getDoOutput()) {
                try (OutputStream os = connection.getOutputStream()) {
                    request.getEntity().write(os);
                }
            }

            int code = connection.getResponseCode();
            String reason = connection.getRequestMethod();
            if (code != 200) {
                throwException(connection, code, reason);
            }
            try (InputStream is = connection.getInputStream()) {
                Preconditions.checkState(is != null, "response stream is null.");
                return request.getResponseReader().read(is);
            }
        } catch (Exception e) {
            throw new RuntimeException(request.getUri().toString(), e);
        }
    }

    private String throwException(HttpURLConnection connection, int code, String reason) {
        String errorResponse = "";
        try (InputStream is = connection.getInputStream() == null ? connection.getErrorStream() :
                connection.getInputStream()) {
            if (is != null) {
                errorResponse = IOUtils.toString(is);
            }
            throw new IllegalStateException(String.format("error code:%s, reason:%s, response: %s", code, reason,
                    errorResponse));
        } catch (Exception e) {
            throw new IllegalStateException(String.format("error code:%s, reason:%s, response: %s", code, reason,
                    errorResponse), e);
        }
    }

    private HttpURLConnection openHttpConnection(URL url) throws IOException {
        URLConnection urlConnection = url.openConnection();
        if (!HttpURLConnection.class.isInstance(urlConnection)) {
            throw new RuntimeException("Expected type for [" + url + "] is [HttpURLConnection] but got: " + urlConnection);
        }
        return (HttpURLConnection) urlConnection;
    }

    private void setHeaders(URI uri, Map> headers, HttpURLConnection conn) {
        headers.forEach((k, vs) -> {
            conn.setRequestProperty(k, HeaderUtils.assembleHeaderValue(vs));
        });
    }

    @Override
    public  Future executeAsync(EntityRequest request, int connectTimeout, int readTimeout) {
        return asyncPool.submit(() -> execute(request, connectTimeout, readTimeout));
    }

    @Override
    public  R execute(Request request, int connectTimeout, int readTimeout) {
        try {
            URI uri = request.getUri();
            HttpURLConnection connection = openHttpConnection(uri.toURL());

            connection.setConnectTimeout(connectTimeout);
            connection.setReadTimeout(readTimeout);

            connection.setDoInput(true);

            connection.setDoOutput(false);

            try {
                connection.setRequestMethod(request.getMethod());
            } catch (ProtocolException e) {
                throw new RuntimeException(e);
            }

            setHeaders(uri, request.getHeaders(), connection);
            connection.connect();

            int code = connection.getResponseCode();
            String reason = connection.getRequestMethod();
            if (code != 200) {
                throwException(connection, code, reason);
            }
            try (InputStream is = connection.getInputStream()) {
                Preconditions.checkState(is != null, "response stream is null.");
                return request.getResponseReader().read(is);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public  Future executeAsync(Request request, int connectTimeout, int readTimeout) {
        return asyncPool.submit(() -> execute(request, connectTimeout, readTimeout));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy