parent
358a6d6f10
commit
56c2987273
|
@ -19,6 +19,8 @@ package org.springframework.messaging.rsocket;
|
|||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
|
@ -44,6 +46,7 @@ import org.springframework.core.io.buffer.NettyDataBufferFactory;
|
|||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Default, package-private {@link RSocketRequester} implementation.
|
||||
|
@ -58,6 +61,9 @@ final class DefaultRSocketRequester implements RSocketRequester {
|
|||
static final MimeType ROUTING = new MimeType("message", "x.rsocket.routing.v0");
|
||||
|
||||
|
||||
/** For route variable replacement. */
|
||||
private static final Pattern VARS_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
|
||||
|
||||
private static final Map<String, Object> EMPTY_HINTS = Collections.emptyMap();
|
||||
|
||||
|
||||
|
@ -105,11 +111,29 @@ final class DefaultRSocketRequester implements RSocketRequester {
|
|||
}
|
||||
|
||||
@Override
|
||||
public RequestSpec route(String route) {
|
||||
public RequestSpec route(String route, Object... vars) {
|
||||
Assert.notNull(route, "'route' is required");
|
||||
route = expand(route, vars);
|
||||
return new DefaultRequestSpec(route, metadataMimeType().equals(COMPOSITE_METADATA) ? ROUTING : null);
|
||||
}
|
||||
|
||||
private static String expand(String route, Object... vars) {
|
||||
if (ObjectUtils.isEmpty(vars)) {
|
||||
return route;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int index = 0;
|
||||
Matcher matcher = VARS_PATTERN.matcher(route);
|
||||
while (matcher.find()) {
|
||||
Assert.isTrue(index < vars.length, () -> "No value for variable '" + matcher.group(1) + "'");
|
||||
String value = vars[index].toString();
|
||||
value = value.contains(".") ? value.replaceAll("\\.", "%2E") : value;
|
||||
matcher.appendReplacement(sb, value);
|
||||
index++;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestSpec metadata(Object metadata, @Nullable MimeType mimeType) {
|
||||
return new DefaultRequestSpec(metadata, mimeType);
|
||||
|
|
|
@ -66,13 +66,19 @@ public interface RSocketRequester {
|
|||
|
||||
/**
|
||||
* Begin to specify a new request with the given route to a remote handler.
|
||||
* <p>The route can be a template with placeholders, e.g.
|
||||
* {@code "flight.{code}"} in which case the supplied route variables are
|
||||
* expanded into the template after being formatted via {@code toString()}.
|
||||
* If a formatted variable contains a "." it is replaced with the escape
|
||||
* sequence "%2E" to avoid treating it as separator by the responder .
|
||||
* <p>If the connection is set to use composite metadata, the route is
|
||||
* encoded as {@code "message/x.rsocket.routing.v0"}. Otherwise the route
|
||||
* is encoded according to the mime type for the connection.
|
||||
* @param route the route to a handler
|
||||
* @param routeVars variables to be expanded into the route template
|
||||
* @return a spec for further defining and executing the request
|
||||
*/
|
||||
RequestSpec route(String route);
|
||||
RequestSpec route(String route, Object... routeVars);
|
||||
|
||||
/**
|
||||
* Begin to specify a new request with the given metadata.
|
||||
|
|
|
@ -210,14 +210,17 @@ public class DefaultRSocketRequesterTests {
|
|||
.hasMessageStartingWith("Connection configured for metadata mime type");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeWithVars() {
|
||||
RSocketRequester requester = RSocketRequester.wrap(this.rsocket, TEXT_PLAIN, TEXT_PLAIN, this.strategies);
|
||||
requester.route("a.{b}.{c}", "BBB", "C.C.C").data("body").send().block();
|
||||
assertThat(this.rsocket.getSavedPayload().getMetadataUtf8()).isEqualTo("a.BBB.C%2EC%2EC");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportedMetadataMimeTypes() {
|
||||
|
||||
RSocketRequester.wrap(this.rsocket, TEXT_PLAIN,
|
||||
COMPOSITE_METADATA, this.strategies);
|
||||
|
||||
RSocketRequester.wrap(this.rsocket, TEXT_PLAIN,
|
||||
ROUTING, this.strategies);
|
||||
RSocketRequester.wrap(this.rsocket, TEXT_PLAIN, COMPOSITE_METADATA, this.strategies);
|
||||
RSocketRequester.wrap(this.rsocket, TEXT_PLAIN, ROUTING, this.strategies);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue