package com.instructure.canvasapi.utilities;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.ResponseBody;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okio.BufferedSink;
import retrofit.client.Header;
import retrofit.client.OkClient;
import retrofit.client.Request;
import retrofit.client.Response;
import retrofit.mime.TypedInput;
import retrofit.mime.TypedOutput;
/**
* Wrapper class to help determine whether a response is from the network or the cache
* Copy of OkClient because static methods aren't modifiable
*/
public class CanvasOkClient extends OkClient {
static final int CONNECT_TIMEOUT_MILLIS = 15 * 1000; // 15s
static final int READ_TIMEOUT_MILLIS = 20 * 1000; // 20s
public static final String CANVAS_API_CACHE_HEADER = "Canvas-api-cache";
public static final String CANVAS_API_CACHE_HEADER_VALUE = "is-cache";
private static OkHttpClient generateDefaultOkHttp() {
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setReadTimeout(READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
return client;
}
private final OkHttpClient client;
public CanvasOkClient() {
this(generateDefaultOkHttp());
}
public CanvasOkClient(OkHttpClient client) {
if (client == null) throw new NullPointerException("client == null");
this.client = client;
}
public OkHttpClient getClient() {
return client;
}
@Override public Response execute(Request request) throws IOException {
return parseResponse(client.newCall(createRequest(request)).execute());
}
static com.squareup.okhttp.Request createRequest(Request request) {
com.squareup.okhttp.Request.Builder builder = new com.squareup.okhttp.Request.Builder()
.url(request.getUrl())
.method(request.getMethod(), createRequestBody(request.getBody()));
List<Header> headers = request.getHeaders();
for (int i = 0, size = headers.size(); i < size; i++) {
Header header = headers.get(i);
String value = header.getValue();
if (value == null) value = "";
builder.addHeader(header.getName(), value);
}
return builder.build();
}
static Response parseResponse(com.squareup.okhttp.Response response) throws IOException {
// If the networkResponse is null, then the response is from cache.
// A header is added to the response, so it can be determined in the callback that it was from cache.
boolean isCache = response.networkResponse() == null;
return new Response(response.request().urlString(), response.code(), response.message(),
createHeaders(response.headers(), isCache), createResponseBody(response.body()));
}
private static RequestBody createRequestBody(final TypedOutput body) {
if (body == null) {
return null;
}
final MediaType mediaType = MediaType.parse(body.mimeType());
return new RequestBody() {
@Override public MediaType contentType() {
return mediaType;
}
@Override public void writeTo(BufferedSink sink) throws IOException {
body.writeTo(sink.outputStream());
}
@Override public long contentLength() {
return body.length();
}
};
}
private static TypedInput createResponseBody(final ResponseBody body) throws IOException{
if (body.contentLength() == 0) {
return null;
}
return new TypedInput() {
@Override public String mimeType() {
MediaType mediaType = body.contentType();
return mediaType == null ? null : mediaType.toString();
}
@Override public long length() {
try {
return body.contentLength();
} catch (IOException e) {
e.printStackTrace();
return 0; //FIXME try catch
}
}
@Override public InputStream in() throws IOException {
return body.byteStream();
}
};
}
private static List<Header> createHeaders(Headers headers, boolean isCached) {
int size = headers.size();
List<Header> headerList = new ArrayList<Header>(size);
for (int i = 0; i < size; i++) {
headerList.add(new Header(headers.name(i), headers.value(i)));
}
if (isCached) {
headerList.add(new Header(CANVAS_API_CACHE_HEADER, CANVAS_API_CACHE_HEADER_VALUE));
}
return headerList;
}
}