优化
This commit is contained in:
@@ -3,6 +3,13 @@ package com.baiyue.common.web;
|
||||
import feign.Request;
|
||||
import feign.Capability;
|
||||
import feign.Retryer;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.DecodeException;
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -22,6 +29,9 @@ public class EventDeliveryFeignConfiguration {
|
||||
}
|
||||
/** Applied at Feign build time after global/client properties, without changing other clients. */
|
||||
public static final class DeliveryTransportCapability implements Capability {
|
||||
private static final ObjectMapper RESPONSE_JSON = new ObjectMapper()
|
||||
.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION)
|
||||
.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
|
||||
private final Request.Options options;
|
||||
public DeliveryTransportCapability(Request.Options options) { this.options = options; }
|
||||
@Override public Request.Options enrich(Request.Options ignored) { return options; }
|
||||
@@ -29,5 +39,26 @@ public class EventDeliveryFeignConfiguration {
|
||||
// The persisted Outbox owns the retry budget.
|
||||
return Retryer.NEVER_RETRY;
|
||||
}
|
||||
@Override public Decoder enrich(Decoder decoder) {
|
||||
return (response, type) -> {
|
||||
if (type instanceof ParameterizedType parameterized && parameterized.getRawType() == ApiResponse.class) {
|
||||
// Jackson normally coerces a numeric 200 into String. Inspect the wire value first.
|
||||
if (response.body() == null) throw new DecodeException(response.status(), "Missing event response", response.request());
|
||||
byte[] bytes;
|
||||
try (var stream = response.body().asInputStream()) { bytes = stream.readNBytes(65537); }
|
||||
if (bytes.length > 65536) throw new DecodeException(response.status(), "Event response exceeds limit", response.request());
|
||||
try {
|
||||
var root = RESPONSE_JSON.readTree(bytes);
|
||||
if (root == null || !root.isObject() || !root.path("code").isTextual()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
} catch (Exception invalid) {
|
||||
throw new DecodeException(response.status(), "Invalid event response contract", response.request());
|
||||
}
|
||||
return decoder.decode(response.toBuilder().body(bytes).build(), type);
|
||||
}
|
||||
return decoder.decode(response, type);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user