package com.jdroid.java.http.okhttp; import com.jdroid.java.http.AbstractHttpService; import com.jdroid.java.http.HttpResponseWrapper; import com.jdroid.java.http.HttpService; import com.jdroid.java.http.HttpServiceProcessor; import com.jdroid.java.http.Server; import com.jdroid.java.http.parser.Parser; import com.jdroid.java.utils.LoggerUtils; import com.jdroid.java.utils.StringUtils; import java.io.InputStream; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.ResponseBody; public abstract class OkHttpService extends AbstractHttpService { static { // This is to avoid exceptions like "java.net.ProtocolException: Unexpected status line:..." that occurs in some // cases when HTTP connections are reused. This issue, according to the tests carried out, seems to happen in the app // only in some cases when a connection is reused after a response code 204. System.setProperty("http.keepAlive", "false"); } private static OkHttpClient OK_HTTP_CLIENT_PROTOTYPE; protected OkHttpClient client; protected Request request; private List<Interceptor> networkInterceptors; public OkHttpService(Server server, List<Object> urlSegments, List<HttpServiceProcessor> httpServiceProcessors) { super(server, urlSegments, httpServiceProcessors); } @Override protected HttpResponseWrapper doExecute(String urlString) { if (OK_HTTP_CLIENT_PROTOTYPE == null) { synchronized (OkHttpService.class) { if (OK_HTTP_CLIENT_PROTOTYPE == null) { OK_HTTP_CLIENT_PROTOTYPE = new OkHttpClient(); } } } OkHttpClient.Builder clientBuilder = OK_HTTP_CLIENT_PROTOTYPE.newBuilder(); clientBuilder.connectTimeout(getConnectionTimeout(), TimeUnit.MILLISECONDS); clientBuilder.writeTimeout(getWriteTimeout(), TimeUnit.MILLISECONDS); clientBuilder.readTimeout(getReadTimeout(), TimeUnit.MILLISECONDS); if (networkInterceptors != null) { for (Interceptor each : networkInterceptors) { clientBuilder.addNetworkInterceptor(each); } } client = clientBuilder.build(); Request.Builder builder = new Request.Builder(); builder.url(urlString); addUserAgent(builder); addHeaders(builder); onConfigureRequestBuilder(builder); request = builder.build(); return new ExecuteRequestCommand().execute(this); } @SuppressWarnings("unchecked") @Override protected <T> T parse(Parser parser, InputStream inputStream) { return (T)new ParseCommand(parser).execute(inputStream); } protected void addUserAgent(Request.Builder builder) { String userAgent = getUserAgent(); if (StringUtils.isNotBlank(userAgent)) { builder.addHeader(HttpService.USER_AGENT_HEADER, userAgent); LOGGER.debug("User Agent: " + userAgent); } } private void addHeaders(Request.Builder builder) { for (Map.Entry<String, String> entry : getHeaders().entrySet()) { builder.addHeader(entry.getKey(), entry.getValue()); } } protected void onConfigureRequestBuilder(Request.Builder builder) { // Do nothing } @Override protected void doFinally() { try { OkHttpResponseWrapper okHttpResponseWrapper = (OkHttpResponseWrapper)getHttpResponseWrapper(); if (okHttpResponseWrapper != null) { ResponseBody body = okHttpResponseWrapper.getResponse().body(); if (body != null) { body.close(); } } } catch (Exception e) { LoggerUtils.logHandledException(LOGGER, e); } } public void setNetworkInterceptors(List<Interceptor> networkInterceptors) { this.networkInterceptors = networkInterceptors; } public void addNetworkInterceptor(Interceptor networkInterceptor) { this.networkInterceptors.add(networkInterceptor); } }