WpErrorInterceptor.java
package io.github.evisentin.wordpress.rest.client.adapter.apache.interceptors;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.evisentin.wordpress.rest.client.domain.exception.WpBadRequestException;
import io.github.evisentin.wordpress.rest.client.domain.exception.WpForbiddenException;
import io.github.evisentin.wordpress.rest.client.domain.exception.WpNotFoundException;
import io.github.evisentin.wordpress.rest.client.domain.exception.WpUnauthorizedException;
import io.github.evisentin.wordpress.rest.client.domain.model.WpError;
import org.apache.hc.core5.http.*;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.protocol.HttpContext;
import java.io.IOException;
import static org.apache.commons.lang3.StringUtils.isBlank;
public final class WpErrorInterceptor implements HttpResponseInterceptor {
private static final ObjectMapper MAPPER = new ObjectMapper();
@Override
public void process(final HttpResponse response,
final EntityDetails entityDetails,
final HttpContext context)
throws HttpException, IOException {
int statusCode = response.getCode();
// success → do nothing
if (statusCode >= 200 && statusCode < 300) {
return;
}
HttpEntity entity = null;
if (response instanceof ClassicHttpResponse classicResponse) {
entity = classicResponse.getEntity();
}
String rawBody = entity != null ? EntityUtils.toString(entity) : null;
WpError wpError = parseWpError(rawBody);
// ⚠️ IMPORTANT: entity is consumed → rebuild it
if (response instanceof ClassicHttpResponse classicResponse) {
classicResponse.setEntity(
new org.apache.hc.core5.http.io.entity.StringEntity(rawBody == null ? "" : rawBody)
);
}
throw mapException(statusCode, wpError, rawBody);
}
private static String buildBodySuffix(final String rawBody) {
return isBlank(rawBody) ? "" : ", body=" + rawBody;
}
private static RuntimeException mapException(final int statusCode,
final WpError wpError,
final String rawBody) {
return switch (statusCode) {
case 400 -> new WpBadRequestException(wpError);
case 401 -> new WpUnauthorizedException(wpError);
case 403 -> new WpForbiddenException(wpError);
case 404 -> new WpNotFoundException(wpError);
default -> new RuntimeException(
"Unexpected HTTP status " + statusCode + buildBodySuffix(rawBody)
);
};
}
private static WpError parseWpError(final String rawBody) {
if (isBlank(rawBody)) return null;
try {
return MAPPER.readValue(rawBody, WpError.class);
} catch (Exception ignored) {
return null;
}
}
}