com.urbanairship.api.client.ResponseAsyncHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-client Show documentation
Show all versions of java-client Show documentation
The Urban Airship Java client library
/*
* Copyright (c) 2013-2016. Urban Airship and Contributors
*/
package com.urbanairship.api.client;
import com.fasterxml.jackson.core.JsonParseException;
import io.netty.handler.codec.http.HttpHeaders;
import org.apache.commons.lang.StringUtils;
import org.asynchttpclient.AsyncHandler;
import org.asynchttpclient.HttpResponseBodyPart;
import org.asynchttpclient.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Asynchronous API response handler.
* @param The response type.
*/
class ResponseAsyncHandler implements AsyncHandler {
private static final Logger log = LoggerFactory.getLogger(ResponseAsyncHandler.class);
private static final String CONTENT_TYPE_KEY = "Content-type";
private final Response.Builder responseBuilder = new Response.Builder<>();
private final ClientException.Builder exceptionBuilder = ClientException.newBuilder();
private final ServerException.Builder serverExceptionBuilder = ServerException.newBuilder();
private final Optional clientCallback;
private final ResponseParser parser;
private final StringBuilder bodyBuilder = new StringBuilder();
private AtomicInteger retryCount = new AtomicInteger(0);
private String exceptionContentType;
private boolean isSuccessful;
private boolean clientError;
private boolean serverError;
private Integer statusCode;
/**
* ResponseAsyncHandler constructor.
*
* @param clientCallback An optional ResponseCallback for handling the response on completion or error.
* @param parser The response parser.
*/
public ResponseAsyncHandler(Optional clientCallback, ResponseParser parser) {
this.clientCallback = clientCallback;
this.parser = parser;
}
@Override
public State onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
statusCode = responseStatus.getStatusCode();
if (statusCode == 401 || statusCode == 403) {
exceptionBuilder.setStatusCode(statusCode);
exceptionBuilder.setStatusText(responseStatus.getStatusText());
clientError = true;
} else if (statusCode >= 500) {
serverExceptionBuilder.setStatusCode(statusCode);
serverExceptionBuilder.setStatusText(responseStatus.getStatusText());
serverError = true;
}
else {
responseBuilder.setStatus(responseStatus.getStatusCode());
isSuccessful = true;
}
return State.CONTINUE;
}
@Override
public State onHeadersReceived(HttpHeaders httpHeaders) throws Exception {
if (isSuccessful) {
responseBuilder.setHeaders(getHeaders(httpHeaders));
} else {
exceptionContentType = httpHeaders.get(CONTENT_TYPE_KEY);
}
return State.CONTINUE;
}
@Override
public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
String body = new String(bodyPart.getBodyPartBytes(), StandardCharsets.UTF_8);
if (clientError) {
// The response body for an error won't be very big, so we can throw here without needing to aggregate.
RequestError error = RequestError.errorFromResponse(body, exceptionContentType);
exceptionBuilder.setRequestError(error);
throw exceptionBuilder.build();
}
else if (serverError) {
RequestError error = RequestError.errorFromResponse(body, exceptionContentType);
serverExceptionBuilder.setRequestError(error);
throw serverExceptionBuilder.build();
}
bodyBuilder.append(body);
return State.CONTINUE;
}
@Override
public Response onCompleted() throws Exception {
if (StringUtils.isNotBlank(bodyBuilder.toString())) {
try {
responseBuilder.setBody(parser.parse(bodyBuilder.toString()));
} catch (JsonParseException e) {
log.debug(String.format("Could not parse the response: %s", bodyBuilder.toString()), e);
onThrowable(e);
return responseBuilder.build();
}
}
Response response = responseBuilder.build();
if (clientCallback.isPresent()) {
clientCallback.get().completed(response);
}
log.debug("Response processing completed for " + response.getBody());
return response;
}
@Override
public void onThrowable(Throwable t) {
log.error("Exception thrown during response processing", t);
if (clientCallback.isPresent()) {
clientCallback.get().error(t);
}
}
/**
* Retrieves the response headers.
* @param httpResponse The HttpResponse.
* @return An immutable map of response headers.
*/
private Map getHeaders(HttpHeaders httpResponse) {
Map headers = new HashMap<>();
for (Map.Entry entry : httpResponse.entries()) {
headers.put(entry.getKey(), entry.getValue());
}
return headers;
}
/**
* Retrieves the request retry count.
*
* @return The retry count.
*/
public int getRetryCount() {
return retryCount.get();
}
/**
* Increment the request retry count.
*/
public void incrementRetryCount() {
retryCount.incrementAndGet();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy