Remove RSocket metadata MimeType constants

For public use, these constants aren't ideally exposed through an SPI
like MetadataExtractor, and there isn't any other obvious place either.
In practice the only public API where these can be passed in is
RSocketRequester and RSocketMessageHandler both of which already
default to composite metadata anyway, leaving only the routing MimeType
to be used potentially but much less likely.
Due to existence of similar constants in the RSocket itself, i.e.
WellKnownMimeType, we can get by internally too without declaring
MimeType constants from a central place.
This commit is contained in:
Rossen Stoyanchev
2019-08-27 12:27:20 +03:00
parent 45d0405624
commit 29a58ab045
8 changed files with 66 additions and 60 deletions

View File

@@ -28,6 +28,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.rsocket.Payload;
import io.rsocket.metadata.CompositeMetadata;
import io.rsocket.metadata.WellKnownMimeType;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.ResolvableType;
@@ -153,7 +154,7 @@ public class DefaultMetadataExtractor implements MetadataExtractor {
@Override
public Map<String, Object> extract(Payload payload, MimeType metadataMimeType) {
Map<String, Object> result = new HashMap<>();
if (metadataMimeType.equals(COMPOSITE_METADATA)) {
if (metadataMimeType.toString().equals(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.toString())) {
for (CompositeMetadata.Entry entry : new CompositeMetadata(payload.metadata(), false)) {
extractEntry(entry.getContent(), entry.getMimeType(), result);
}
@@ -170,7 +171,7 @@ public class DefaultMetadataExtractor implements MetadataExtractor {
extractor.extract(content, result);
return;
}
if (MetadataExtractor.ROUTING.toString().equals(mimeType)) {
if (mimeType != null && mimeType.equals(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString())) {
// TODO: use rsocket-core API when available
result.put(MetadataExtractor.ROUTE_KEY, content.toString(StandardCharsets.UTF_8));
}

View File

@@ -27,6 +27,7 @@ import java.util.function.Consumer;
import io.rsocket.Payload;
import io.rsocket.RSocketFactory;
import io.rsocket.frame.decoder.PayloadDecoder;
import io.rsocket.metadata.WellKnownMimeType;
import io.rsocket.transport.ClientTransport;
import io.rsocket.transport.netty.client.TcpClientTransport;
import io.rsocket.transport.netty.client.WebsocketClientTransport;
@@ -43,6 +44,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
/**
* Default implementation of {@link RSocketRequester.Builder}.
@@ -59,7 +61,8 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
@Nullable
private MimeType dataMimeType;
private MimeType metadataMimeType = MetadataExtractor.COMPOSITE_METADATA;
@Nullable
private MimeType metadataMimeType;
@Nullable
private Object setupData;
@@ -159,11 +162,14 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
factory.frameDecoder(PayloadDecoder.ZERO_COPY);
}
MimeType metaMimeType = this.metadataMimeType != null ? this.metadataMimeType :
MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
MimeType dataMimeType = getDataMimeType(rsocketStrategies);
factory.dataMimeType(dataMimeType.toString());
factory.metadataMimeType(this.metadataMimeType.toString());
factory.metadataMimeType(metaMimeType.toString());
Payload setupPayload = getSetupPayload(dataMimeType, rsocketStrategies);
Payload setupPayload = getSetupPayload(dataMimeType, metaMimeType, rsocketStrategies);
if (setupPayload != null) {
factory.setupPayload(setupPayload);
}
@@ -171,14 +177,14 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
return factory.transport(transport)
.start()
.map(rsocket -> new DefaultRSocketRequester(
rsocket, dataMimeType, this.metadataMimeType, rsocketStrategies));
rsocket, dataMimeType, metaMimeType, rsocketStrategies));
}
@Nullable
private Payload getSetupPayload(MimeType dataMimeType, RSocketStrategies strategies) {
private Payload getSetupPayload(MimeType dataMimeType, MimeType metaMimeType, RSocketStrategies strategies) {
DataBuffer metadata = null;
if (this.setupRoute != null || !CollectionUtils.isEmpty(this.setupMetadata)) {
metadata = new MetadataEncoder(this.metadataMimeType, strategies)
metadata = new MetadataEncoder(metaMimeType, strategies)
.metadataAndOrRoute(this.setupMetadata, this.setupRoute, this.setupRouteVars)
.encode();
}
@@ -246,7 +252,7 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
private static MimeType getMimeType(Decoder<?> decoder) {
MimeType mimeType = decoder.getDecodableMimeTypes().get(0);
return new MimeType(mimeType, Collections.emptyMap());
return mimeType.getParameters().isEmpty() ? mimeType : new MimeType(mimeType, Collections.emptyMap());
}
}

View File

@@ -25,6 +25,7 @@ import java.util.regex.Pattern;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.CompositeByteBuf;
import io.rsocket.metadata.CompositeMetadataFlyweight;
import io.rsocket.metadata.WellKnownMimeType;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.Encoder;
@@ -46,7 +47,7 @@ import org.springframework.util.ObjectUtils;
final class MetadataEncoder {
/** For route variable replacement. */
private static final Pattern VARS_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
private static final Pattern VARS_PATTERN = Pattern.compile("\\{([^/]+?)}");
private final MimeType metadataMimeType;
@@ -68,7 +69,8 @@ final class MetadataEncoder {
Assert.notNull(strategies, "RSocketStrategies is required");
this.metadataMimeType = metadataMimeType;
this.strategies = strategies;
this.isComposite = metadataMimeType.equals(MetadataExtractor.COMPOSITE_METADATA);
this.isComposite = this.metadataMimeType.toString().equals(
WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
this.allocator = bufferFactory() instanceof NettyDataBufferFactory ?
((NettyDataBufferFactory) bufferFactory()).getByteBufAllocator() : ByteBufAllocator.DEFAULT;
}
@@ -157,11 +159,15 @@ final class MetadataEncoder {
* @see PayloadUtils#createPayload(DataBuffer, DataBuffer)
*/
public DataBuffer encode() {
Map<Object, MimeType> mergedMetadata = mergeRouteAndMetadata();
if (this.isComposite) {
CompositeByteBuf composite = this.allocator.compositeBuffer();
if (this.route != null) {
CompositeMetadataFlyweight.encodeAndAddMetadata(composite, this.allocator,
WellKnownMimeType.MESSAGE_RSOCKET_ROUTING,
PayloadUtils.asByteBuf(bufferFactory().wrap(this.route.getBytes(StandardCharsets.UTF_8))));
}
try {
mergedMetadata.forEach((value, mimeType) -> {
this.metadata.forEach((value, mimeType) -> {
DataBuffer buffer = encodeEntry(value, mimeType);
CompositeMetadataFlyweight.encodeAndAddMetadata(
composite, this.allocator, mimeType.toString(), PayloadUtils.asByteBuf(buffer));
@@ -180,38 +186,24 @@ final class MetadataEncoder {
throw ex;
}
}
else if (this.route != null) {
Assert.isTrue(this.metadata.isEmpty(), "Composite metadata required for route and other entries");
return this.metadataMimeType.toString().equals(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString()) ?
bufferFactory().wrap(this.route.getBytes(StandardCharsets.UTF_8)) :
encodeEntry(this.route, this.metadataMimeType);
}
else {
Assert.isTrue(mergedMetadata.size() == 1, "Composite metadata required for multiple entries");
Map.Entry<Object, MimeType> entry = mergedMetadata.entrySet().iterator().next();
Assert.isTrue(this.metadata.size() == 1, "Composite metadata required for multiple entries");
Map.Entry<Object, MimeType> entry = this.metadata.entrySet().iterator().next();
if (!this.metadataMimeType.equals(entry.getValue())) {
throw new IllegalArgumentException(
"Connection configured for metadata mime type " +
"'" + this.metadataMimeType + "', but actual is `" + mergedMetadata + "`");
"'" + this.metadataMimeType + "', but actual is `" + this.metadata + "`");
}
return encodeEntry(entry.getKey(), entry.getValue());
}
}
private Map<Object, MimeType> mergeRouteAndMetadata() {
if (this.route == null) {
return this.metadata;
}
MimeType routeMimeType = this.metadataMimeType.equals(MetadataExtractor.COMPOSITE_METADATA) ?
MetadataExtractor.ROUTING : this.metadataMimeType;
Object routeValue = this.route;
if (routeMimeType.equals(MetadataExtractor.ROUTING)) {
// TODO: use rsocket-core API when available
routeValue = bufferFactory().wrap(this.route.getBytes(StandardCharsets.UTF_8));
}
Map<Object, MimeType> result = new LinkedHashMap<>();
result.put(routeValue, routeMimeType);
result.putAll(this.metadata);
return result;
}
@SuppressWarnings("unchecked")
private <T> DataBuffer encodeEntry(Object metadata, MimeType mimeType) {
if (metadata instanceof DataBuffer) {

View File

@@ -38,16 +38,6 @@ public interface MetadataExtractor {
*/
String ROUTE_KEY = "route";
/**
* Constant MimeType {@code "message/x.rsocket.composite-metadata.v0"}.
*/
MimeType COMPOSITE_METADATA = new MimeType("message", "x.rsocket.composite-metadata.v0");
/**
* Constant for MimeType {@code "message/x.rsocket.routing.v0"}.
*/
MimeType ROUTING = new MimeType("message", "x.rsocket.routing.v0");
/**
* Extract a map of values from the given {@link Payload} metadata.

View File

@@ -24,6 +24,7 @@ import io.rsocket.ConnectionSetupPayload;
import io.rsocket.RSocket;
import io.rsocket.SocketAcceptor;
import io.rsocket.frame.FrameType;
import io.rsocket.metadata.WellKnownMimeType;
import reactor.core.publisher.Mono;
import org.springframework.beans.BeanUtils;
@@ -73,7 +74,8 @@ public class RSocketMessageHandler extends MessageMappingMessageHandler {
@Nullable
private MimeType defaultDataMimeType;
private MimeType defaultMetadataMimeType = MetadataExtractor.COMPOSITE_METADATA;
private MimeType defaultMetadataMimeType = MimeTypeUtils.parseMimeType(
WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
public RSocketMessageHandler() {