package io.nextop.httpclient;
import io.nextop.Message;
import io.nextop.Nextop;
import io.nextop.NextopAndroid;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import rx.functions.Func1;
import javax.annotation.Nullable;
import java.io.IOException;
// FIXME(compat)
public class NextopHttpClient implements HttpClient {
private final Nextop nextop;
private final HttpParams params;
private final ClientConnectionManager connectionManager;
public NextopHttpClient(@Nullable ClientConnectionManager connectionManager,
@Nullable HttpParams params) {
this(connectionManager, params, NextopAndroid.getActive());
}
public NextopHttpClient(@Nullable ClientConnectionManager connectionManager,
@Nullable HttpParams params,
Nextop nextop) {
this.params = params;
this.connectionManager = connectionManager;
this.nextop = nextop;
}
@Override
public HttpParams getParams() {
// important: this object is currently benign
// TODO attempt to map values set here into the Nextop messages
return params;
}
@Override
public ClientConnectionManager getConnectionManager() {
// important: this object is currently benign
// TODO attempt to map values set here into the Nextop messages
return connectionManager;
}
@Override
public HttpResponse execute(@Nullable HttpHost httpHost, HttpRequest httpRequest, @Nullable HttpContext httpContext) throws IOException, ClientProtocolException {
// TODO httpContext? currently ignored
Message message = fromHttpRequest(httpHost, httpRequest);
// FIXME attach cancel policy on request to nextop.cancelSend(id)
return execute(nextop, message);
}
@Override
public <T> T execute(@Nullable HttpHost httpHost, HttpRequest httpRequest, ResponseHandler<? extends T> responseHandler, @Nullable HttpContext httpContext) throws IOException, ClientProtocolException {
HttpResponse response = execute(httpHost, httpRequest, httpContext);
return responseHandler.handleResponse(response);
}
@Override
public HttpResponse execute(HttpUriRequest httpUriRequest) throws IOException, ClientProtocolException {
return execute((HttpHost) null, httpUriRequest, (HttpContext) null);
}
@Override
public HttpResponse execute(HttpUriRequest httpUriRequest, HttpContext httpContext) throws IOException, ClientProtocolException {
return execute((HttpHost) null, httpUriRequest, httpContext);
}
@Override
public HttpResponse execute(HttpHost httpHost, HttpRequest httpRequest) throws IOException, ClientProtocolException {
return execute(httpHost, httpRequest, (HttpContext) null);
}
@Override
public <T> T execute(HttpUriRequest httpUriRequest, ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {
return execute((HttpHost) null, httpUriRequest, responseHandler, (HttpContext) null);
}
@Override
public <T> T execute(HttpUriRequest httpUriRequest, ResponseHandler<? extends T> responseHandler, HttpContext httpContext) throws IOException, ClientProtocolException {
return execute((HttpHost) null, httpUriRequest, responseHandler, httpContext);
}
@Override
public <T> T execute(HttpHost httpHost, HttpRequest httpRequest, ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {
return execute(httpHost, httpRequest, responseHandler, (HttpContext) null);
}
public static HttpResponse execute(Nextop nextop, Message message) throws IOException {
Nextop.Receiver<Message> receiver = nextop.send(message);
Message responseMessage = receiver.onErrorReturn(new Func1<Throwable, Message>() {
@Override
public Message call(Throwable throwable) {
// TODO handle the error more precisely
return Message.newBuilder().setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR).build();
}
}).defaultIfEmpty(
// if using the nextop protocol, some successful messages don't have a response code,
// just an ack which closes the channel
Message.newBuilder().setCode(HttpStatus.SC_OK).build()
).toBlocking().single();
return toHttpResponse(responseMessage);
}
public static Message fromHttpRequest(HttpHost httpHost, HttpRequest httpRequest) {
return fromHttpRequestBuilder(httpHost, httpRequest).build();
}
public static Message.Builder fromHttpRequestBuilder(HttpHost httpHost, HttpRequest httpRequest) {
// FIXME support request.abort
// FIXME adapt org.apache.* to io.nextop.org.apache.* then use Message.fromHttpRequest,
// FIXME and adapt back with abort behavior mixed in
return null;
}
public static HttpResponse toHttpResponse(Message message) {
// FIXME use Message.toHttpResponse and adapt back with abort behavior mixed in
return null;
}
}