com.outbrain.ob1k.http.ning.NingRequestBuilder Maven / Gradle / Ivy
The newest version!
package com.outbrain.ob1k.http.ning;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.outbrain.ob1k.http.utils.ComposableFutureAdapter.fromListenableFuture;
import com.ning.http.client.AsyncCompletionHandler;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.HttpResponseBodyPart;
import com.ning.http.client.ListenableFuture;
import com.ning.http.client.Request;
import com.outbrain.ob1k.concurrent.ComposableFuture;
import com.outbrain.ob1k.concurrent.ComposableFutures;
import com.outbrain.ob1k.concurrent.handlers.FutureSuccessHandler;
import com.outbrain.ob1k.http.RequestBuilder;
import com.outbrain.ob1k.http.Response;
import com.outbrain.ob1k.http.common.ContentType;
import com.outbrain.ob1k.http.TypedResponse;
import com.outbrain.ob1k.http.common.Cookie;
import com.outbrain.ob1k.http.common.Header;
import com.outbrain.ob1k.http.common.Param;
import com.outbrain.ob1k.http.marshalling.MarshallingStrategy;
import com.outbrain.ob1k.http.utils.ComposableFutureAdapter.Provider;
import com.outbrain.ob1k.http.utils.UrlUtils;
import com.outbrain.swinfra.metrics.api.MetricFactory;
import org.apache.commons.codec.EncoderException;
import rx.Observable;
import rx.functions.Func1;
import rx.subjects.PublishSubject;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
/**
* @author marenzon
*/
public class NingRequestBuilder implements RequestBuilder {
private final AsyncHttpClient asyncHttpClient;
private final AsyncHttpClient.BoundRequestBuilder ningRequestBuilder;
private final MetricFactory metricFactory;
private MarshallingStrategy marshallingStrategy;
private String requestUrl;
private long responseMaxSize;
private String charset = DEFAULT_CHARSET;
private String bodyString;
private byte[] bodyByteArray;
private Object bodyObject;
public NingRequestBuilder(final AsyncHttpClient asyncHttpClient, final AsyncHttpClient.BoundRequestBuilder ningRequestBuilder,
final String requestUrl, final MetricFactory metricFactory, final long responseMaxSize,
final MarshallingStrategy marshallingStrategy) {
this.asyncHttpClient = checkNotNull(asyncHttpClient, "asyncHttpClient may not be null");
this.ningRequestBuilder = checkNotNull(ningRequestBuilder, "ningRequestBuilder may not be null");
this.requestUrl = checkNotNull(requestUrl, "requestUrl may not be null");
this.metricFactory = metricFactory;
this.responseMaxSize = responseMaxSize;
this.marshallingStrategy = marshallingStrategy;
}
@Override
public RequestBuilder setContentType(final ContentType contentType) {
return setContentType(contentType.requestEncoding());
}
@Override
public RequestBuilder setContentType(final String contentType) {
ningRequestBuilder.setHeader(CONTENT_TYPE_HEADER, contentType);
return this;
}
@Override
public RequestBuilder setPathParam(final String param, final String value) throws EncoderException {
requestUrl = UrlUtils.replacePathParam(requestUrl, param, value);
ningRequestBuilder.setUrl(requestUrl);
return this;
}
@Override
public RequestBuilder setPathParam(final Param param) throws EncoderException {
return setPathParam(param.getName(), param.getValue());
}
@Override
public RequestBuilder setPathParams(final List params) throws EncoderException {
for (final Param param : params) {
setPathParam(param);
}
return this;
}
@Override
public RequestBuilder setUserAgent(final String userAgent) {
return addHeader(USER_AGENT_HEADER, userAgent);
}
@Override
public RequestBuilder addHeader(final String name, final String value) {
ningRequestBuilder.addHeader(name, value);
return this;
}
@Override
public RequestBuilder addHeader(final Header header) {
return addHeader(header.getName(), header.getValue());
}
@Override
public RequestBuilder addHeaders(final List headers) {
for (final Header header : headers) {
addHeader(header);
}
return this;
}
@Override
public RequestBuilder setBody(final String body) {
this.bodyString = body;
return this;
}
@Override
public RequestBuilder setBody(final byte[] body) {
this.bodyByteArray = body;
return this;
}
@Override
public RequestBuilder setBody(final Object body) {
this.bodyObject = body;
return this;
}
@Override
public RequestBuilder setBodyEncoding(final String charset) {
this.charset = charset;
return this;
}
@Override
public RequestBuilder addQueryParam(final String name, final String value) {
ningRequestBuilder.addQueryParam(name, value);
return this;
}
@Override
public RequestBuilder addQueryParams(final Map params) {
for (final Map.Entry param : params.entrySet()) {
addQueryParam(param.getKey(), param.getValue());
}
return this;
}
@Override
public RequestBuilder addQueryParam(final Param param) {
return addQueryParam(param.getName(), param.getValue());
}
@Override
public RequestBuilder addQueryParams(final List params) {
for (final Param param : params) {
addQueryParam(param);
}
return this;
}
@Override
public RequestBuilder setResponseMaxSize(final long responseMaxSize) {
this.responseMaxSize = responseMaxSize;
return this;
}
@Override
public RequestBuilder addCookie(final Cookie cookie) {
final com.ning.http.client.cookie.Cookie ningCookie = transformToNingCookie(cookie);
ningRequestBuilder.addCookie(ningCookie);
return this;
}
@Override
public RequestBuilder setRequestTimeout(final int requestTimeout) {
ningRequestBuilder.setRequestTimeout(requestTimeout);
return this;
}
@Override
public RequestBuilder setMarshallingStrategy(final MarshallingStrategy marshallingStrategy) {
this.marshallingStrategy = checkNotNull(marshallingStrategy, "unmarshallingStrategy may not be null");
return this;
}
@Override
public ComposableFuture asResponse() {
try {
prepareRequestBody();
} catch (final IOException e) {
return ComposableFutures.fromError(e);
}
final ComposableFuture responseFuture = executeAndTransformRequest();
return responseFuture.continueOnSuccess(new FutureSuccessHandler() {
@Override
public ComposableFuture handle(final com.ning.http.client.Response ningResponse) {
try {
final Response response = new NingResponse<>(ningResponse, null, null);
return ComposableFutures.fromValue(response);
} catch (final IOException e) {
return ComposableFutures.fromError(e);
}
}
});
}
@Override
public Observable asStream() {
try {
prepareRequestBody();
} catch (final IOException e) {
return Observable.error(e);
}
setRequestTimeout(-1);
final PublishSubject result = PublishSubject.create();
final NingHttpStreamHandler handler = new NingHttpStreamHandler(responseMaxSize, result);
ningRequestBuilder.execute(handler);
return result;
}
@Override
public ComposableFuture> asTypedResponse(final Class type) {
return asTypedResponse((Type) type);
}
@Override
public Observable> asTypedStream(final Class type) {
return asTypedStream((Type) type);
}
@Override
public ComposableFuture> asTypedResponse(final Type type) {
final ComposableFuture responseFuture = executeAndTransformRequest();
return responseFuture.continueOnSuccess(new FutureSuccessHandler>() {
@Override
public ComposableFuture> handle(final com.ning.http.client.Response ningResponse) {
try {
final TypedResponse response = new NingResponse<>(ningResponse, type, marshallingStrategy);
return ComposableFutures.fromValue(response);
} catch (final IOException e) {
return ComposableFutures.fromError(e);
}
}
});
}
@Override
public Observable> asTypedStream(final Type type) {
try {
prepareRequestBody();
} catch (final IOException e) {
return Observable.error(e);
}
setRequestTimeout(-1);
final PublishSubject> result = PublishSubject.create();
final NingHttpTypedStreamHandler handler = new NingHttpTypedStreamHandler<>(responseMaxSize, result,
marshallingStrategy, type);
ningRequestBuilder.execute(handler);
return result;
}
@Override
public ComposableFuture asValue(final Class type) {
return asValue((Type) type);
}
@Override
public ComposableFuture asValue(final Type type) {
final ComposableFuture> responseFuture = asTypedResponse(type);
return responseFuture.continueOnSuccess(new FutureSuccessHandler, T>() {
@Override
public ComposableFuture handle(final TypedResponse typedResponse) {
try {
return ComposableFutures.fromValue(typedResponse.getTypedBody());
} catch (final IOException e) {
return ComposableFutures.fromError(e);
}
}
});
}
@Override
public Observable asStreamValue(final Class type) {
return asStreamValue((Type) type);
}
@Override
public Observable asStreamValue(final Type type) {
final Observable> responseObservable = asTypedStream(type);
return responseObservable.flatMap(new Func1, Observable>() {
@Override
public Observable call(final TypedResponse typedResponse) {
try {
return Observable.from(typedResponse.getTypedBody());
} catch (final IOException e) {
return Observable.error(e);
}
}
});
}
private ComposableFuture executeAndTransformRequest() {
try {
prepareRequestBody();
} catch (final IOException e) {
return ComposableFutures.fromError(e);
}
final Request ningRequest = ningRequestBuilder.build();
return fromListenableFuture(
new Provider() {
private boolean aborted = false;
private long size;
@Override
public ListenableFuture provide() {
return asyncHttpClient.executeRequest(ningRequest, new AsyncCompletionHandler() {
@Override
public com.ning.http.client.Response onCompleted(final com.ning.http.client.Response response) throws Exception {
if (aborted) {
throw new RuntimeException("Response size is bigger than the limit: " + responseMaxSize);
}
return response;
}
@Override
public STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception {
if (responseMaxSize > 0) {
size += content.length();
if (size > responseMaxSize) {
aborted = true;
return STATE.ABORT;
}
}
return super.onBodyPartReceived(content);
}
});
}
}, metricFactory, ningRequest.getUri().getHost()
);
}
private com.ning.http.client.cookie.Cookie transformToNingCookie(final Cookie cookie) {
return com.ning.http.client.cookie.Cookie.newValidCookie(cookie.getName(), cookie.getValue(), false,
cookie.getDomain(), cookie.getPath(), 0, (int) cookie.getMaxAge(),
cookie.isSecure(), cookie.isHttpOnly());
}
/**
* Prepares the request body - setting the body, charset and
* content length by body type
*
* @throws IOException
*/
private void prepareRequestBody() throws IOException {
if (bodyByteArray != null) {
setByteArrayBody();
} else if (bodyString != null) {
setStringBody();
} else if (bodyObject != null) {
setTypedBody();
}
}
private void setTypedBody() throws IOException {
final byte[] body = marshallingStrategy.marshall(bodyObject);
ningRequestBuilder.setBody(body);
ningRequestBuilder.setContentLength(body.length);
ningRequestBuilder.setBodyEncoding(charset);
}
private void setStringBody() throws UnsupportedEncodingException {
ningRequestBuilder.setBody(bodyString);
ningRequestBuilder.setContentLength(bodyString.getBytes(charset).length);
ningRequestBuilder.setBodyEncoding(charset);
}
private void setByteArrayBody() {
ningRequestBuilder.setBody(bodyByteArray);
ningRequestBuilder.setContentLength(bodyByteArray.length);
ningRequestBuilder.setBodyEncoding(charset);
}
} © 2015 - 2025 Weber Informatics LLC | Privacy Policy