BasicHttpResult.java
package org.wikimedia.eventutilities.core.http;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.IOException;
import java.util.function.IntPredicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.ThreadSafe;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
/**
* Class representing an HTTP request result from HttpRequest
* This is not called 'response' as it also
* can represent a failed result caused
* by a local Exception rather than an HTTP response error status code.
*/
@ParametersAreNonnullByDefault @ThreadSafe
public class BasicHttpResult {
/**
* If the HTTP request that caused this result was successful.
* If a local exception is encountered or a provided the isSuccess function
* is false, this will be false.
*/
protected final boolean success;
/**
* The HTTP response status code, or -1 if a local exception was encountered.
*/
protected final int status;
/**
* The HTTP response message, or the Exception message if a local exception was encountered.
*/
@Nullable
protected final String message;
/**
* THe HTTP response body, if there was one.
*/
@Nullable
protected final byte[] body;
/**
* If a local IOException was encountered, this will be set to it.
*/
@Nullable
protected final IOException exception;
BasicHttpResult(boolean success, int status, @Nullable String message, @Nullable byte[] body) {
this.success = success;
this.status = status;
this.message = message;
this.body = body;
this.exception = null;
}
/**
* Constructs a failure BasicHttpResult representing a failure due to
* a local IOException rather than an HTTP response error status code.
*/
BasicHttpResult(IOException e) {
this.success = false;
this.status = -1;
this.message = e.getMessage();
this.body = null;
this.exception = e;
}
/**
* Creates an BasicHttpResult from an httpcomponents HttpResponse and a lambda
* isSuccess that determines what http response status codes constitute a successful
* response.
*/
@Nullable
public static BasicHttpResult create(HttpResponse response, IntPredicate isSuccess) throws IOException {
int status = response.getStatusLine().getStatusCode();
boolean success = isSuccess.test(status);
String message = response.getStatusLine().getReasonPhrase();
HttpEntity responseEntity = response.getEntity();
byte[] body = responseEntity != null ? EntityUtils.toByteArray(responseEntity) : null;
return new BasicHttpResult(success, status, message, body);
}
public boolean getSuccess() {
return success;
}
public int getStatus() {
return status;
}
@Nullable
public String getMessage() {
return message;
}
/**
* Returns a copy of the byte[] response body.
*/
@Nullable
public byte[] getBody() {
if (body == null) {
return null;
}
final byte[] bodyCopy = new byte[body.length];
System.arraycopy(body, 0, bodyCopy, 0, body.length);
return bodyCopy;
}
@Nonnull
public String getBodyAsString() {
if (body == null) {
return "";
} else {
return new String(body, UTF_8);
}
}
@Nullable
public IOException getException() {
return exception;
}
/**
* Returns true if this result represents a failure due to a local IOException.
*/
public boolean causedByException() {
return exception != null;
}
@Nonnull
public String toString() {
StringBuilder repr = new StringBuilder("BasicHttpResult");
if (success) {
repr.append("(success) ");
} else {
repr.append("(failure) ");
}
if (causedByException()) {
repr.append(" encountered local exception: ").append(message);
} else {
repr.append(" status: ").append(status).append(" message: ").append(message);
}
return repr.toString();
}
}