org.codehaus.httpcache4j.resolver.OKHttpResponseResolver Maven / Gradle / Ivy
package org.codehaus.httpcache4j.resolver;
import okhttp3.*;
import okio.BufferedSink;
import org.codehaus.httpcache4j.*;
import org.codehaus.httpcache4j.Headers;
import org.codehaus.httpcache4j.payload.Payload;
import org.codehaus.httpcache4j.util.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class OKHttpResponseResolver extends AbstractResponseResolver {
private final OkHttpClient client;
public OKHttpResponseResolver(ResolverConfiguration config) {
this(config, builder -> {});
}
public OKHttpResponseResolver(ResolverConfiguration configuration, Consumer configF) {
super(configuration);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.authenticator(new NullAuthenticator());
builder.followRedirects(false);
builder.followSslRedirects(false);
builder.cache(null);
ConnectionConfiguration connConfig = configuration.getConnectionConfiguration();
builder.connectionPool(new ConnectionPool(
connConfig.getMaxConnections().orElse(new ConnectionPool().connectionCount()),
(5 * 60 * 1000), // 5 minutes,
TimeUnit.MILLISECONDS
));
connConfig.getConnectionRequestTimeout().ifPresent(i -> builder.readTimeout(i, TimeUnit.MILLISECONDS));
connConfig.getSocketTimeout().ifPresent(i -> builder.connectTimeout(i, TimeUnit.MILLISECONDS));
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(connConfig.getMaxConnections().orElse(dispatcher.getMaxRequests()));
dispatcher.setMaxRequestsPerHost(connConfig.getDefaultConnectionsPerHost().orElse(dispatcher.getMaxRequestsPerHost()));
builder.dispatcher(dispatcher);
if (connConfig.getTimeout().isPresent()) {
builder.connectTimeout(connConfig.getTimeout().get(), TimeUnit.MILLISECONDS);
}
HTTPHost proxyHost = configuration.getProxyAuthenticator().getConfiguration().getHost();
if (proxyHost != null) {
builder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost.getHost(), proxyHost.getPort())));
}
configF.accept(builder);
this.client = builder.build();
}
@Override
protected HTTPResponse resolveImpl(HTTPRequest request) throws IOException {
final Request req = transformRequest(request);
Response response = client.newCall(req).execute();
return transformResponse(response);
}
private Request transformRequest(HTTPRequest request) {
Request.Builder builder = new Request.Builder();
builder.addHeader(HeaderConstants.USER_AGENT, getConfiguration().getUserAgent());
Headers requestHeaders = request.getHeaders();
for (Header header : requestHeaders) {
builder.addHeader(header.getName(), header.getValue());
}
Optional payload = request.getPayload().map(PayloadRequestBody::new);
builder.method(request.getMethod().getMethod(), payload.orElse(null));
builder.url(HttpUrl.get(request.getNormalizedURI()));
return builder.build();
}
private HTTPResponse transformResponse(Response response) throws IOException {
Status status = Status.valueOf(response.code());
StatusLine line = new StatusLine(status, response.message());
return new HTTPResponse(
Optional.ofNullable(response.body()).map(PayloadResponseBody::new),
line,
new Headers(response.headers().toMultimap())
);
}
@Override
public void shutdown() {
client.dispatcher().executorService().shutdown();
}
public OkHttpClient getClient() {
return client;
}
private static class PayloadRequestBody extends RequestBody {
private final Payload payload;
public PayloadRequestBody(Payload payload) {
this.payload = payload;
}
@Override
public MediaType contentType() {
return MediaType.parse(payload.getMimeType().toString());
}
@Override
public void writeTo(BufferedSink bufferedSink) throws IOException {
IOUtils.copy(payload.getInputStream(), bufferedSink.outputStream());
}
}
private static class PayloadResponseBody implements Payload {
private final ResponseBody delegate;
private boolean available;
public PayloadResponseBody(ResponseBody payload) {
this.delegate = payload;
}
@Override
public MIMEType getMimeType() {
return MIMEType.valueOf(delegate.contentType().toString());
}
@Override
public InputStream getInputStream() {
available = false;
return delegate.byteStream();
}
@Override
public long length() {
return delegate.contentLength();
}
@Override
public boolean isAvailable() {
return available;
}
}
private static class NullAuthenticator implements Authenticator {
@Override
public Request authenticate(Route route, Response response) throws IOException {
return null;
}
}
}