Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flip the default should throw behavior for HttpJsonMessageWithFaultingPayload #1176

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class PayloadAccessFaultingMap extends AbstractMap<String, Object> {
private boolean disableThrowingPayloadNotLoaded;

public PayloadAccessFaultingMap(StrictCaseInsensitiveHttpHeadersMap headers) {
disableThrowingPayloadNotLoaded = true;
underlyingMap = new TreeMap<>();
isJson = Optional.ofNullable(headers.get("content-type"))
.map(list -> list.stream().anyMatch(s -> s.startsWith("application/json")))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ public void channelRead(@NonNull ChannelHandlerContext ctx, @NonNull Object msg)
IAuthTransformer authTransformer = requestPipelineOrchestrator.authTransfomerFactory.getAuthTransformer(
httpJsonMessage
);
final var payloadMap = (PayloadAccessFaultingMap) httpJsonMessage.payload();
try {
payloadMap.setDisableThrowingPayloadNotLoaded(false);
handlePayloadNeutralTransformationOrThrow(
ctx,
originalHttpJsonMessage,
Expand All @@ -86,6 +88,8 @@ public void channelRead(@NonNull ChannelHandlerContext ctx, @NonNull Object msg)
getAuthTransformerAsStreamingTransformer(authTransformer)
);
ctx.fireChannelRead(handleAuthHeaders(httpJsonMessage, authTransformer));
} finally {
payloadMap.setDisableThrowingPayloadNotLoaded(true);
}
} else if (msg instanceof HttpContent) {
ctx.fireChannelRead(msg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;

import org.opensearch.migrations.replay.datahandlers.JsonAccumulator;
import org.opensearch.migrations.replay.tracing.IReplayContexts;
Expand All @@ -24,6 +25,7 @@
import io.netty.util.ReferenceCountUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.event.Level;

/**
* This accumulates HttpContent messages through a JsonAccumulator and eventually fires off a
Expand Down Expand Up @@ -93,7 +95,10 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
}
}
} catch (JacksonException e) {
log.atInfo().setCause(e).setMessage("Error parsing json body. " +
log.atLevel(hasRequestContentTypeMatching(capturedHttpJsonMessage,
// a JacksonException for non-json data doesn't need to be surfaced to a user
v -> v.startsWith("application/json")) ? Level.INFO : Level.TRACE)
.setCause(e).setMessage("Error parsing json body. " +
"Will pass all payload bytes directly as a ByteBuf within the payload map").log();
jsonWasInvalid = true;
parsedJsonObjects.clear();
Expand Down Expand Up @@ -123,7 +128,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception

var leftoverBody = accumulatedBody.slice(jsonBodyByteLength,
accumulatedBody.readableBytes() - jsonBodyByteLength);
if (jsonBodyByteLength == 0 && isRequestContentTypeNotText(capturedHttpJsonMessage)) {
if (jsonBodyByteLength == 0 &&
hasRequestContentTypeMatching(capturedHttpJsonMessage, v -> !v.startsWith("text/")))
{
context.onPayloadSetBinary();
capturedHttpJsonMessage.payload()
.put(JsonKeysForHttpMessage.INLINED_BINARY_BODY_DOCUMENT_KEY,
Expand Down Expand Up @@ -157,12 +164,13 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
}
}

private boolean isRequestContentTypeNotText(HttpJsonMessageWithFaultingPayload message) {
private boolean hasRequestContentTypeMatching(HttpJsonMessageWithFaultingPayload message,
Predicate<String> contentTypeFilter) {
// ContentType not text if specified and has a value with / and that value does not start with text/
return Optional.ofNullable(capturedHttpJsonMessage.headers().insensitiveGet(HttpHeaderNames.CONTENT_TYPE.toString()))
.map(s -> s.stream()
.filter(v -> v.contains("/"))
.filter(v -> !v.startsWith("text/"))
.filter(contentTypeFilter)
.count() > 1
)
.orElse(false);
Expand Down
Loading