mirror of https://github.com/dapr/java-sdk.git
Support many query strings in HTTP and binary data in Cloud Event for PubSub. (#485)
* Handles base64 data from CloudEvent. * Support for multiple query strings. * Addressing comments.
This commit is contained in:
parent
1b3077071f
commit
e46ef319cd
|
@ -26,7 +26,7 @@ jobs:
|
||||||
DAPR_RUNTIME_VER: 1.0.0-rc.3
|
DAPR_RUNTIME_VER: 1.0.0-rc.3
|
||||||
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/3dacfb672d55f1436c249057aaebbe597e1066f3/install/install.sh
|
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/3dacfb672d55f1436c249057aaebbe597e1066f3/install/install.sh
|
||||||
DAPR_CLI_REF:
|
DAPR_CLI_REF:
|
||||||
DAPR_REF:
|
DAPR_REF: 4899aa8fb8f7537fb10432e6cc0cfc09c572cb54
|
||||||
OSSRH_USER_TOKEN: ${{ secrets.OSSRH_USER_TOKEN }}
|
OSSRH_USER_TOKEN: ${{ secrets.OSSRH_USER_TOKEN }}
|
||||||
OSSRH_PWD_TOKEN: ${{ secrets.OSSRH_PWD_TOKEN }}
|
OSSRH_PWD_TOKEN: ${{ secrets.OSSRH_PWD_TOKEN }}
|
||||||
GPG_KEY: ${{ secrets.GPG_KEY }}
|
GPG_KEY: ${{ secrets.GPG_KEY }}
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -16,7 +16,7 @@
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<grpc.version>1.33.1</grpc.version>
|
<grpc.version>1.33.1</grpc.version>
|
||||||
<protobuf.version>3.13.0</protobuf.version>
|
<protobuf.version>3.13.0</protobuf.version>
|
||||||
<dapr.proto.baseurl>https://raw.githubusercontent.com/dapr/dapr/4a6369caaba9cf46eae9bfa4fa6e76b474854c89/dapr/proto</dapr.proto.baseurl>
|
<dapr.proto.baseurl>https://raw.githubusercontent.com/dapr/dapr/4899aa8fb8f7537fb10432e6cc0cfc09c572cb54/dapr/proto</dapr.proto.baseurl>
|
||||||
<os-maven-plugin.version>1.6.2</os-maven-plugin.version>
|
<os-maven-plugin.version>1.6.2</os-maven-plugin.version>
|
||||||
<maven-dependency-plugin.version>3.1.1</maven-dependency-plugin.version>
|
<maven-dependency-plugin.version>3.1.1</maven-dependency-plugin.version>
|
||||||
<maven-antrun-plugin.version>1.8</maven-antrun-plugin.version>
|
<maven-antrun-plugin.version>1.8</maven-antrun-plugin.version>
|
||||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
||||||
name: sample123
|
name: sample123
|
||||||
spec:
|
spec:
|
||||||
type: bindings.kafka
|
type: bindings.kafka
|
||||||
version: 1
|
version: v1
|
||||||
metadata:
|
metadata:
|
||||||
# Kafka broker connection setting
|
# Kafka broker connection setting
|
||||||
- name: brokers
|
- name: brokers
|
||||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
||||||
name: messagebus
|
name: messagebus
|
||||||
spec:
|
spec:
|
||||||
type: pubsub.redis
|
type: pubsub.redis
|
||||||
version: 1
|
version: v1
|
||||||
metadata:
|
metadata:
|
||||||
- name: redisHost
|
- name: redisHost
|
||||||
value: localhost:6379
|
value: localhost:6379
|
||||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
||||||
name: statestore
|
name: statestore
|
||||||
spec:
|
spec:
|
||||||
type: state.redis
|
type: state.redis
|
||||||
version: 1
|
version: v1
|
||||||
metadata:
|
metadata:
|
||||||
- name: redisHost
|
- name: redisHost
|
||||||
value: localhost:6379
|
value: localhost:6379
|
||||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
||||||
name: vault
|
name: vault
|
||||||
spec:
|
spec:
|
||||||
type: secretstores.hashicorp.vault
|
type: secretstores.hashicorp.vault
|
||||||
version: 1
|
version: v1
|
||||||
metadata:
|
metadata:
|
||||||
- name: vaultAddr
|
- name: vaultAddr
|
||||||
value: "http://127.0.0.1:8200"
|
value: "http://127.0.0.1:8200"
|
||||||
|
|
|
@ -5,17 +5,23 @@
|
||||||
|
|
||||||
package io.dapr.it.pubsub.http;
|
package io.dapr.it.pubsub.http;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.dapr.client.DaprClient;
|
import io.dapr.client.DaprClient;
|
||||||
import io.dapr.client.DaprClientBuilder;
|
import io.dapr.client.DaprClientBuilder;
|
||||||
|
import io.dapr.client.domain.CloudEvent;
|
||||||
import io.dapr.client.domain.HttpExtension;
|
import io.dapr.client.domain.HttpExtension;
|
||||||
import io.dapr.client.domain.Metadata;
|
import io.dapr.client.domain.Metadata;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
|
import io.dapr.serializer.DaprObjectSerializer;
|
||||||
|
import io.dapr.utils.TypeRef;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.Parameterized;
|
import org.junit.runners.Parameterized;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -24,12 +30,18 @@ import java.util.List;
|
||||||
|
|
||||||
import static io.dapr.it.Retry.callWithRetry;
|
import static io.dapr.it.Retry.callWithRetry;
|
||||||
import static io.dapr.it.TestUtils.assertThrowsDaprException;
|
import static io.dapr.it.TestUtils.assertThrowsDaprException;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class PubSubIT extends BaseIT {
|
public class PubSubIT extends BaseIT {
|
||||||
|
|
||||||
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
|
private static final TypeRef<List<CloudEvent>> CLOUD_EVENT_LIST_TYPE_REF = new TypeRef<>() {};
|
||||||
|
|
||||||
//Number of messages to be sent: 10
|
//Number of messages to be sent: 10
|
||||||
private static final int NUM_MESSAGES = 10;
|
private static final int NUM_MESSAGES = 10;
|
||||||
|
|
||||||
|
@ -39,6 +51,8 @@ public class PubSubIT extends BaseIT {
|
||||||
private static final String ANOTHER_TOPIC_NAME = "anothertopic";
|
private static final String ANOTHER_TOPIC_NAME = "anothertopic";
|
||||||
// Topic used for TTL test
|
// Topic used for TTL test
|
||||||
private static final String TTL_TOPIC_NAME = "ttltopic";
|
private static final String TTL_TOPIC_NAME = "ttltopic";
|
||||||
|
// Topic to test binary data
|
||||||
|
private static final String BINARY_TOPIC_NAME = "binarytopic";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters for this test.
|
* Parameters for this test.
|
||||||
|
@ -97,8 +111,6 @@ public class PubSubIT extends BaseIT {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPubSub() throws Exception {
|
public void testPubSub() throws Exception {
|
||||||
System.out.println("Working Directory = " + System.getProperty("user.dir"));
|
|
||||||
|
|
||||||
final DaprRun daprRun = closeLater(startDaprApp(
|
final DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
SubscriberService.SUCCESS_MESSAGE,
|
SubscriberService.SUCCESS_MESSAGE,
|
||||||
|
@ -112,8 +124,25 @@ public class PubSubIT extends BaseIT {
|
||||||
daprRun.switchToHTTP();
|
daprRun.switchToHTTP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DaprObjectSerializer serializer = new DaprObjectSerializer() {
|
||||||
|
@Override
|
||||||
|
public byte[] serialize(Object o) throws JsonProcessingException {
|
||||||
|
return OBJECT_MAPPER.writeValueAsBytes(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T deserialize(byte[] data, TypeRef<T> type) throws IOException {
|
||||||
|
return (T) OBJECT_MAPPER.readValue(data, OBJECT_MAPPER.constructType(type.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getContentType() {
|
||||||
|
return "application/json";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Send a batch of messages on one topic
|
// Send a batch of messages on one topic
|
||||||
try (DaprClient client = new DaprClientBuilder().build()) {
|
try (DaprClient client = new DaprClientBuilder().withObjectSerializer(serializer).build()) {
|
||||||
for (int i = 0; i < NUM_MESSAGES; i++) {
|
for (int i = 0; i < NUM_MESSAGES; i++) {
|
||||||
String message = String.format("This is message #%d on topic %s", i, TOPIC_NAME);
|
String message = String.format("This is message #%d on topic %s", i, TOPIC_NAME);
|
||||||
//Publishing messages
|
//Publishing messages
|
||||||
|
@ -140,38 +169,113 @@ public class PubSubIT extends BaseIT {
|
||||||
|
|
||||||
callWithRetry(() -> {
|
callWithRetry(() -> {
|
||||||
System.out.println("Checking results for topic " + TOPIC_NAME);
|
System.out.println("Checking results for topic " + TOPIC_NAME);
|
||||||
final List<String> messages = client.invokeMethod(daprRun.getAppName(), "messages/testingtopic", null, HttpExtension.GET, List.class).block();
|
final List<CloudEvent> messages = client.invokeMethod(
|
||||||
|
daprRun.getAppName(),
|
||||||
|
"messages/testingtopic",
|
||||||
|
null,
|
||||||
|
HttpExtension.GET,
|
||||||
|
CLOUD_EVENT_LIST_TYPE_REF).block();
|
||||||
assertEquals(11, messages.size());
|
assertEquals(11, messages.size());
|
||||||
for (int i = 0; i < NUM_MESSAGES; i++) {
|
for (int i = 0; i < NUM_MESSAGES; i++) {
|
||||||
assertTrue(messages.toString(), messages.contains(String.format("This is message #%d on topic %s", i, TOPIC_NAME)));
|
final int messageId = i;
|
||||||
|
assertTrue(messages
|
||||||
|
.stream()
|
||||||
|
.filter(m -> m.getData() != null)
|
||||||
|
.map(m -> m.getData())
|
||||||
|
.filter(m -> m.equals(String.format("This is message #%d on topic %s", messageId, TOPIC_NAME)))
|
||||||
|
.count() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean foundByte = false;
|
assertTrue(messages
|
||||||
for (String message : messages) {
|
.stream()
|
||||||
if ((message.getBytes().length == 1) && (message.getBytes()[0] == 1)) {
|
.filter(m -> m.getData() != null)
|
||||||
foundByte = true;
|
.map(m -> m.getData())
|
||||||
}
|
.filter(m -> "AQ==".equals(m))
|
||||||
}
|
.count() == 1);
|
||||||
assertTrue(foundByte);
|
|
||||||
|
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
callWithRetry(() -> {
|
callWithRetry(() -> {
|
||||||
System.out.println("Checking results for topic " + ANOTHER_TOPIC_NAME);
|
System.out.println("Checking results for topic " + ANOTHER_TOPIC_NAME);
|
||||||
final List<String> messages = client.invokeMethod(daprRun.getAppName(), "messages/anothertopic", null, HttpExtension.GET, List.class).block();
|
final List<CloudEvent> messages = client.invokeMethod(
|
||||||
|
daprRun.getAppName(),
|
||||||
|
"messages/anothertopic",
|
||||||
|
null,
|
||||||
|
HttpExtension.GET,
|
||||||
|
CLOUD_EVENT_LIST_TYPE_REF).block();
|
||||||
assertEquals(10, messages.size());
|
assertEquals(10, messages.size());
|
||||||
|
|
||||||
for (int i = 0; i < NUM_MESSAGES; i++) {
|
for (int i = 0; i < NUM_MESSAGES; i++) {
|
||||||
assertTrue(messages.contains(String.format("This is message #%d on topic %s", i, ANOTHER_TOPIC_NAME)));
|
final int messageId = i;
|
||||||
|
assertTrue(messages
|
||||||
|
.stream()
|
||||||
|
.filter(m -> m.getData() != null)
|
||||||
|
.map(m -> m.getData())
|
||||||
|
.filter(m -> m.equals(String.format("This is message #%d on topic %s", messageId, ANOTHER_TOPIC_NAME)))
|
||||||
|
.count() == 1);
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPubSubTTLMetadata() throws Exception {
|
public void testPubSubBinary() throws Exception {
|
||||||
System.out.println("Working Directory = " + System.getProperty("user.dir"));
|
final DaprRun daprRun = closeLater(startDaprApp(
|
||||||
|
this.getClass().getSimpleName(),
|
||||||
|
SubscriberService.SUCCESS_MESSAGE,
|
||||||
|
SubscriberService.class,
|
||||||
|
true,
|
||||||
|
60000));
|
||||||
|
// At this point, it is guaranteed that the service above is running and all ports being listened to.
|
||||||
|
if (this.useGrpc) {
|
||||||
|
daprRun.switchToGRPC();
|
||||||
|
} else {
|
||||||
|
daprRun.switchToHTTP();
|
||||||
|
}
|
||||||
|
|
||||||
|
DaprObjectSerializer serializer = new DaprObjectSerializer() {
|
||||||
|
@Override
|
||||||
|
public byte[] serialize(Object o) {
|
||||||
|
return (byte[])o;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T deserialize(byte[] data, TypeRef<T> type) {
|
||||||
|
return (T) data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getContentType() {
|
||||||
|
return "application/octet-stream";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try (DaprClient client = new DaprClientBuilder().withObjectSerializer(serializer).build()) {
|
||||||
|
client.publishEvent(
|
||||||
|
PUBSUB_NAME,
|
||||||
|
BINARY_TOPIC_NAME,
|
||||||
|
new byte[]{1}).block();
|
||||||
|
System.out.println("Published one byte.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.sleep(3000);
|
||||||
|
|
||||||
|
try (DaprClient client = new DaprClientBuilder().build()) {
|
||||||
|
callWithRetry(() -> {
|
||||||
|
System.out.println("Checking results for topic " + BINARY_TOPIC_NAME);
|
||||||
|
final List<CloudEvent> messages = client.invokeMethod(
|
||||||
|
daprRun.getAppName(),
|
||||||
|
"messages/binarytopic",
|
||||||
|
null,
|
||||||
|
HttpExtension.GET, CLOUD_EVENT_LIST_TYPE_REF).block();
|
||||||
|
assertEquals(1, messages.size());
|
||||||
|
assertNull(messages.get(0).getData());
|
||||||
|
assertArrayEquals(new byte[]{1}, messages.get(0).getBinaryData());
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPubSubTTLMetadata() throws Exception {
|
||||||
DaprRun daprRun = closeLater(startDaprApp(
|
DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
60000));
|
60000));
|
||||||
|
|
|
@ -22,22 +22,28 @@ import java.util.List;
|
||||||
@RestController
|
@RestController
|
||||||
public class SubscriberController {
|
public class SubscriberController {
|
||||||
|
|
||||||
private static final List<Object> messagesReceivedTestingTopic = new ArrayList();
|
private static final List<CloudEvent> messagesReceivedTestingTopic = new ArrayList();
|
||||||
private static final List<Object> messagesReceivedAnotherTopic = new ArrayList();
|
private static final List<CloudEvent> messagesReceivedBinaryTopic = new ArrayList();
|
||||||
private static final List<Object> messagesReceivedTTLTopic = new ArrayList();
|
private static final List<CloudEvent> messagesReceivedAnotherTopic = new ArrayList();
|
||||||
|
private static final List<CloudEvent> messagesReceivedTTLTopic = new ArrayList();
|
||||||
|
|
||||||
@GetMapping(path = "/messages/testingtopic")
|
@GetMapping(path = "/messages/testingtopic")
|
||||||
public List<Object> getMessagesReceivedTestingTopic() {
|
public List<CloudEvent> getMessagesReceivedTestingTopic() {
|
||||||
return messagesReceivedTestingTopic;
|
return messagesReceivedTestingTopic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping(path = "/messages/binarytopic")
|
||||||
|
public List<CloudEvent> getMessagesReceivedBinaryTopic() {
|
||||||
|
return messagesReceivedBinaryTopic;
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping(path = "/messages/anothertopic")
|
@GetMapping(path = "/messages/anothertopic")
|
||||||
public List<Object> getMessagesReceivedAnotherTopic() {
|
public List<CloudEvent> getMessagesReceivedAnotherTopic() {
|
||||||
return messagesReceivedAnotherTopic;
|
return messagesReceivedAnotherTopic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(path = "/messages/ttltopic")
|
@GetMapping(path = "/messages/ttltopic")
|
||||||
public List<Object> getMessagesReceivedTTLTopic() {
|
public List<CloudEvent> getMessagesReceivedTTLTopic() {
|
||||||
return messagesReceivedTTLTopic;
|
return messagesReceivedTTLTopic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +55,22 @@ public class SubscriberController {
|
||||||
String message = envelope.getData() == null ? "" : envelope.getData().toString();
|
String message = envelope.getData() == null ? "" : envelope.getData().toString();
|
||||||
String contentType = envelope.getDatacontenttype() == null ? "" : envelope.getDatacontenttype();
|
String contentType = envelope.getDatacontenttype() == null ? "" : envelope.getDatacontenttype();
|
||||||
System.out.println("Testing topic Subscriber got message: " + message + "; Content-type: " + contentType);
|
System.out.println("Testing topic Subscriber got message: " + message + "; Content-type: " + contentType);
|
||||||
messagesReceivedTestingTopic.add(envelope.getData());
|
messagesReceivedTestingTopic.add(envelope);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Topic(name = "binarytopic", pubsubName = "messagebus")
|
||||||
|
@PostMapping(path = "/route2")
|
||||||
|
public Mono<Void> handleBinaryMessage(@RequestBody(required = false) CloudEvent envelope) {
|
||||||
|
return Mono.fromRunnable(() -> {
|
||||||
|
try {
|
||||||
|
String message = envelope.getData() == null ? "" : envelope.getData().toString();
|
||||||
|
String contentType = envelope.getDatacontenttype() == null ? "" : envelope.getDatacontenttype();
|
||||||
|
System.out.println("Binary topic Subscriber got message: " + message + "; Content-type: " + contentType);
|
||||||
|
messagesReceivedBinaryTopic.add(envelope);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -57,13 +78,13 @@ public class SubscriberController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Topic(name = "anothertopic", pubsubName = "messagebus")
|
@Topic(name = "anothertopic", pubsubName = "messagebus")
|
||||||
@PostMapping(path = "/route2")
|
@PostMapping(path = "/route3")
|
||||||
public Mono<Void> handleMessageAnotherTopic(@RequestBody(required = false) CloudEvent envelope) {
|
public Mono<Void> handleMessageAnotherTopic(@RequestBody(required = false) CloudEvent envelope) {
|
||||||
return Mono.fromRunnable(() -> {
|
return Mono.fromRunnable(() -> {
|
||||||
try {
|
try {
|
||||||
String message = envelope.getData() == null ? "" : envelope.getData().toString();
|
String message = envelope.getData() == null ? "" : envelope.getData().toString();
|
||||||
System.out.println("Another topic Subscriber got message: " + message);
|
System.out.println("Another topic Subscriber got message: " + message);
|
||||||
messagesReceivedAnotherTopic.add(envelope.getData());
|
messagesReceivedAnotherTopic.add(envelope);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -71,13 +92,13 @@ public class SubscriberController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Topic(name = "ttltopic", pubsubName = "messagebus")
|
@Topic(name = "ttltopic", pubsubName = "messagebus")
|
||||||
@PostMapping(path = "/route3")
|
@PostMapping(path = "/route4")
|
||||||
public Mono<Void> handleMessageTTLTopic(@RequestBody(required = false) CloudEvent envelope) {
|
public Mono<Void> handleMessageTTLTopic(@RequestBody(required = false) CloudEvent envelope) {
|
||||||
return Mono.fromRunnable(() -> {
|
return Mono.fromRunnable(() -> {
|
||||||
try {
|
try {
|
||||||
String message = envelope.getData() == null ? "" : envelope.getData().toString();
|
String message = envelope.getData() == null ? "" : envelope.getData().toString();
|
||||||
System.out.println("TTL topic Subscriber got message: " + message);
|
System.out.println("TTL topic Subscriber got message: " + message);
|
||||||
messagesReceivedTTLTopic.add(envelope.getData());
|
messagesReceivedTTLTopic.add(envelope);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import io.grpc.ForwardingClientCall;
|
||||||
import io.grpc.Metadata;
|
import io.grpc.Metadata;
|
||||||
import io.grpc.MethodDescriptor;
|
import io.grpc.MethodDescriptor;
|
||||||
import io.grpc.stub.StreamObserver;
|
import io.grpc.stub.StreamObserver;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.core.publisher.MonoSink;
|
import reactor.core.publisher.MonoSink;
|
||||||
import reactor.util.context.Context;
|
import reactor.util.context.Context;
|
||||||
|
@ -47,8 +48,10 @@ import reactor.util.context.Context;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -550,8 +553,9 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
requestBuilder.setData(Any.newBuilder().build());
|
requestBuilder.setData(Any.newBuilder().build());
|
||||||
}
|
}
|
||||||
CommonProtos.HTTPExtension.Builder httpExtensionBuilder = CommonProtos.HTTPExtension.newBuilder();
|
CommonProtos.HTTPExtension.Builder httpExtensionBuilder = CommonProtos.HTTPExtension.newBuilder();
|
||||||
|
|
||||||
httpExtensionBuilder.setVerb(CommonProtos.HTTPExtension.Verb.valueOf(httpExtension.getMethod().toString()))
|
httpExtensionBuilder.setVerb(CommonProtos.HTTPExtension.Verb.valueOf(httpExtension.getMethod().toString()))
|
||||||
.putAllQuerystring(httpExtension.getQueryString());
|
.setQuerystring(httpExtension.encodeQueryString());
|
||||||
requestBuilder.setHttpExtension(httpExtensionBuilder.build());
|
requestBuilder.setHttpExtension(httpExtensionBuilder.build());
|
||||||
|
|
||||||
requestBuilder.setContentType(objectSerializer.getContentType());
|
requestBuilder.setContentType(objectSerializer.getContentType());
|
||||||
|
|
|
@ -29,7 +29,6 @@ import io.dapr.serializer.DefaultObjectSerializer;
|
||||||
import io.dapr.utils.NetworkUtils;
|
import io.dapr.utils.NetworkUtils;
|
||||||
import io.dapr.utils.TypeRef;
|
import io.dapr.utils.TypeRef;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.util.context.Context;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -142,7 +141,7 @@ public class DaprClientHttp extends AbstractDaprClient {
|
||||||
|
|
||||||
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "publish", pubsubName, topic };
|
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "publish", pubsubName, topic };
|
||||||
|
|
||||||
Map<String, String> queryArgs = metadataToQueryArgs(metadata);
|
Map<String, List<String>> queryArgs = metadataToQueryArgs(metadata);
|
||||||
return Mono.subscriberContext().flatMap(
|
return Mono.subscriberContext().flatMap(
|
||||||
context -> this.client.invokeApi(
|
context -> this.client.invokeApi(
|
||||||
DaprHttp.HttpMethods.POST.name(), pathSegments, queryArgs, serializedEvent, headers, context
|
DaprHttp.HttpMethods.POST.name(), pathSegments, queryArgs, serializedEvent, headers, context
|
||||||
|
@ -185,7 +184,7 @@ public class DaprClientHttp extends AbstractDaprClient {
|
||||||
headers.putAll(httpExtension.getHeaders());
|
headers.putAll(httpExtension.getHeaders());
|
||||||
Mono<DaprHttp.Response> response = Mono.subscriberContext().flatMap(
|
Mono<DaprHttp.Response> response = Mono.subscriberContext().flatMap(
|
||||||
context -> this.client.invokeApi(httpMethod, pathSegments,
|
context -> this.client.invokeApi(httpMethod, pathSegments,
|
||||||
httpExtension.getQueryString(), serializedRequestBody, headers, context)
|
httpExtension.getQueryParams(), serializedRequestBody, headers, context)
|
||||||
);
|
);
|
||||||
return response.flatMap(r -> getMono(type, r));
|
return response.flatMap(r -> getMono(type, r));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -294,7 +293,7 @@ public class DaprClientHttp extends AbstractDaprClient {
|
||||||
|
|
||||||
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "state", stateStoreName, "bulk"};
|
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "state", stateStoreName, "bulk"};
|
||||||
|
|
||||||
Map<String, String> queryArgs = metadataToQueryArgs(metadata);
|
Map<String, List<String>> queryArgs = metadataToQueryArgs(metadata);
|
||||||
return Mono.subscriberContext().flatMap(
|
return Mono.subscriberContext().flatMap(
|
||||||
context -> this.client
|
context -> this.client
|
||||||
.invokeApi(DaprHttp.HttpMethods.POST.name(), pathSegments, queryArgs, requestBody, null, context)
|
.invokeApi(DaprHttp.HttpMethods.POST.name(), pathSegments, queryArgs, requestBody, null, context)
|
||||||
|
@ -333,9 +332,10 @@ public class DaprClientHttp extends AbstractDaprClient {
|
||||||
.map(o -> o.getStateOptionsAsMap())
|
.map(o -> o.getStateOptionsAsMap())
|
||||||
.orElse(Collections.emptyMap());
|
.orElse(Collections.emptyMap());
|
||||||
|
|
||||||
final Map<String, String> queryParams = new HashMap<>();
|
final Map<String, List<String>> queryParams = new HashMap<>();
|
||||||
queryParams.putAll(metadataToQueryArgs(metadata));
|
queryParams.putAll(metadataToQueryArgs(metadata));
|
||||||
queryParams.putAll(optionsMap);
|
queryParams.putAll(optionsMap.entrySet().stream().collect(
|
||||||
|
Collectors.toMap(kv -> kv.getKey(), kv -> Collections.singletonList(kv.getValue()))));
|
||||||
|
|
||||||
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "state", stateStoreName, key};
|
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "state", stateStoreName, key};
|
||||||
|
|
||||||
|
@ -478,12 +478,13 @@ public class DaprClientHttp extends AbstractDaprClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> optionsMap = Optional.ofNullable(options)
|
Map<String, String> optionsMap = Optional.ofNullable(options)
|
||||||
.map(stateOptions -> stateOptions.getStateOptionsAsMap())
|
.map(o -> o.getStateOptionsAsMap())
|
||||||
.orElse(Collections.emptyMap());
|
.orElse(Collections.emptyMap());
|
||||||
|
|
||||||
final Map<String, String> queryParams = new HashMap<>();
|
final Map<String, List<String>> queryParams = new HashMap<>();
|
||||||
queryParams.putAll(metadataToQueryArgs(metadata));
|
queryParams.putAll(metadataToQueryArgs(metadata));
|
||||||
queryParams.putAll(optionsMap);
|
queryParams.putAll(optionsMap.entrySet().stream().collect(
|
||||||
|
Collectors.toMap(kv -> kv.getKey(), kv -> Collections.singletonList(kv.getValue()))));
|
||||||
|
|
||||||
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "state", stateStoreName, key};
|
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "state", stateStoreName, key};
|
||||||
|
|
||||||
|
@ -572,7 +573,7 @@ public class DaprClientHttp extends AbstractDaprClient {
|
||||||
return DaprException.wrapMono(e);
|
return DaprException.wrapMono(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> queryArgs = metadataToQueryArgs(metadata);
|
Map<String, List<String>> queryArgs = metadataToQueryArgs(metadata);
|
||||||
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "secrets", secretStoreName, key};
|
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "secrets", secretStoreName, key};
|
||||||
|
|
||||||
return Mono.subscriberContext().flatMap(
|
return Mono.subscriberContext().flatMap(
|
||||||
|
@ -608,7 +609,7 @@ public class DaprClientHttp extends AbstractDaprClient {
|
||||||
return DaprException.wrapMono(e);
|
return DaprException.wrapMono(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> queryArgs = metadataToQueryArgs(metadata);
|
Map<String, List<String>> queryArgs = metadataToQueryArgs(metadata);
|
||||||
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "secrets", secretStoreName, "bulk"};
|
String[] pathSegments = new String[]{ DaprHttp.API_VERSION, "secrets", secretStoreName, "bulk"};
|
||||||
|
|
||||||
return Mono.subscriberContext().flatMap(
|
return Mono.subscriberContext().flatMap(
|
||||||
|
@ -638,19 +639,19 @@ public class DaprClientHttp extends AbstractDaprClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts metadata map into HTTP headers.
|
* Converts metadata map into Query params.
|
||||||
* @param metadata metadata map
|
* @param metadata metadata map
|
||||||
* @return HTTP headers
|
* @return Query params
|
||||||
*/
|
*/
|
||||||
private static Map<String, String> metadataToQueryArgs(Map<String, String> metadata) {
|
private static Map<String, List<String>> metadataToQueryArgs(Map<String, String> metadata) {
|
||||||
if (metadata == null) {
|
if (metadata == null) {
|
||||||
return Collections.EMPTY_MAP;
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(e -> e.getKey() != null)
|
.filter(e -> e.getKey() != null)
|
||||||
.collect(Collectors.toMap(e -> METADATA_PREFIX + e.getKey(), e -> e.getValue()));
|
.collect(Collectors.toMap(e -> METADATA_PREFIX + e.getKey(), e -> Collections.singletonList(e.getValue())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -158,7 +159,7 @@ public class DaprHttp implements AutoCloseable {
|
||||||
public Mono<Response> invokeApi(
|
public Mono<Response> invokeApi(
|
||||||
String method,
|
String method,
|
||||||
String[] pathSegments,
|
String[] pathSegments,
|
||||||
Map<String, String> urlParameters,
|
Map<String, List<String>> urlParameters,
|
||||||
Map<String, String> headers,
|
Map<String, String> headers,
|
||||||
Context context) {
|
Context context) {
|
||||||
return this.invokeApi(method, pathSegments, urlParameters, (byte[]) null, headers, context);
|
return this.invokeApi(method, pathSegments, urlParameters, (byte[]) null, headers, context);
|
||||||
|
@ -178,7 +179,7 @@ public class DaprHttp implements AutoCloseable {
|
||||||
public Mono<Response> invokeApi(
|
public Mono<Response> invokeApi(
|
||||||
String method,
|
String method,
|
||||||
String[] pathSegments,
|
String[] pathSegments,
|
||||||
Map<String, String> urlParameters,
|
Map<String, List<String>> urlParameters,
|
||||||
String content,
|
String content,
|
||||||
Map<String, String> headers,
|
Map<String, String> headers,
|
||||||
Context context) {
|
Context context) {
|
||||||
|
@ -203,7 +204,7 @@ public class DaprHttp implements AutoCloseable {
|
||||||
public Mono<Response> invokeApi(
|
public Mono<Response> invokeApi(
|
||||||
String method,
|
String method,
|
||||||
String[] pathSegments,
|
String[] pathSegments,
|
||||||
Map<String, String> urlParameters,
|
Map<String, List<String>> urlParameters,
|
||||||
byte[] content,
|
byte[] content,
|
||||||
Map<String, String> headers,
|
Map<String, String> headers,
|
||||||
Context context) {
|
Context context) {
|
||||||
|
@ -234,7 +235,7 @@ public class DaprHttp implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
private CompletableFuture<Response> doInvokeApi(String method,
|
private CompletableFuture<Response> doInvokeApi(String method,
|
||||||
String[] pathSegments,
|
String[] pathSegments,
|
||||||
Map<String, String> urlParameters,
|
Map<String, List<String>> urlParameters,
|
||||||
byte[] content, Map<String, String> headers,
|
byte[] content, Map<String, String> headers,
|
||||||
Context context) {
|
Context context) {
|
||||||
final String requestId = UUID.randomUUID().toString();
|
final String requestId = UUID.randomUUID().toString();
|
||||||
|
@ -257,7 +258,10 @@ public class DaprHttp implements AutoCloseable {
|
||||||
urlBuilder.addPathSegment(pathSegment);
|
urlBuilder.addPathSegment(pathSegment);
|
||||||
}
|
}
|
||||||
Optional.ofNullable(urlParameters).orElse(Collections.emptyMap()).entrySet().stream()
|
Optional.ofNullable(urlParameters).orElse(Collections.emptyMap()).entrySet().stream()
|
||||||
.forEach(urlParameter -> urlBuilder.addQueryParameter(urlParameter.getKey(), urlParameter.getValue()));
|
.forEach(urlParameter ->
|
||||||
|
Optional.ofNullable(urlParameter.getValue()).orElse(Collections.emptyList()).stream()
|
||||||
|
.forEach(urlParameterValue ->
|
||||||
|
urlBuilder.addQueryParameter(urlParameter.getKey(), urlParameterValue)));
|
||||||
|
|
||||||
Request.Builder requestBuilder = new Request.Builder()
|
Request.Builder requestBuilder = new Request.Builder()
|
||||||
.url(urlBuilder.build())
|
.url(urlBuilder.build())
|
||||||
|
|
|
@ -6,10 +6,13 @@
|
||||||
package io.dapr.client.domain;
|
package io.dapr.client.domain;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import javax.annotation.PropertyKey;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,6 +57,12 @@ public final class CloudEvent {
|
||||||
*/
|
*/
|
||||||
private Object data;
|
private Object data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cloud event specs says binary data should be in data_base64.
|
||||||
|
*/
|
||||||
|
@JsonProperty("data_base64")
|
||||||
|
private byte[] binaryData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a CloudEvent.
|
* Instantiates a CloudEvent.
|
||||||
*/
|
*/
|
||||||
|
@ -84,6 +93,28 @@ public final class CloudEvent {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a CloudEvent.
|
||||||
|
* @param id Identifier of the message being processed.
|
||||||
|
* @param source Source for this event.
|
||||||
|
* @param type Type of event.
|
||||||
|
* @param specversion Version of the event spec.
|
||||||
|
* @param binaryData Payload.
|
||||||
|
*/
|
||||||
|
public CloudEvent(
|
||||||
|
String id,
|
||||||
|
String source,
|
||||||
|
String type,
|
||||||
|
String specversion,
|
||||||
|
byte[] binaryData) {
|
||||||
|
this.id = id;
|
||||||
|
this.source = source;
|
||||||
|
this.type = type;
|
||||||
|
this.specversion = specversion;
|
||||||
|
this.datacontenttype = "application/octet-stream";
|
||||||
|
this.binaryData = binaryData == null ? null : Arrays.copyOf(binaryData, binaryData.length);;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialize a message topic from Dapr.
|
* Deserialize a message topic from Dapr.
|
||||||
|
@ -196,6 +227,22 @@ public final class CloudEvent {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cloud event's binary data.
|
||||||
|
* @return Cloud event's binary data.
|
||||||
|
*/
|
||||||
|
public byte[] getBinaryData() {
|
||||||
|
return this.binaryData == null ? null : Arrays.copyOf(this.binaryData, this.binaryData.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cloud event's binary data.
|
||||||
|
* @param binaryData Cloud event's binary data.
|
||||||
|
*/
|
||||||
|
public void setBinaryData(byte[] binaryData) {
|
||||||
|
this.binaryData = binaryData == null ? null : Arrays.copyOf(binaryData, binaryData.length);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@ -213,7 +260,8 @@ public final class CloudEvent {
|
||||||
&& Objects.equals(type, that.type)
|
&& Objects.equals(type, that.type)
|
||||||
&& Objects.equals(specversion, that.specversion)
|
&& Objects.equals(specversion, that.specversion)
|
||||||
&& Objects.equals(datacontenttype, that.datacontenttype)
|
&& Objects.equals(datacontenttype, that.datacontenttype)
|
||||||
&& Objects.equals(data, that.data);
|
&& Objects.equals(data, that.data)
|
||||||
|
&& Arrays.equals(binaryData, that.binaryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,6 +269,6 @@ public final class CloudEvent {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(id, source, type, specversion, datacontenttype, data);
|
return Objects.hash(id, source, type, specversion, datacontenttype, data, binaryData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,12 @@
|
||||||
package io.dapr.client.domain;
|
package io.dapr.client.domain;
|
||||||
|
|
||||||
import io.dapr.client.DaprHttp;
|
import io.dapr.client.DaprHttp;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP Extension class.
|
* HTTP Extension class.
|
||||||
|
@ -60,9 +63,9 @@ public final class HttpExtension {
|
||||||
private DaprHttp.HttpMethods method;
|
private DaprHttp.HttpMethods method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP querystring.
|
* HTTP query params.
|
||||||
*/
|
*/
|
||||||
private Map<String, String> queryString;
|
private Map<String, List<String>> queryParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP headers.
|
* HTTP headers.
|
||||||
|
@ -72,19 +75,21 @@ public final class HttpExtension {
|
||||||
/**
|
/**
|
||||||
* Construct a HttpExtension object.
|
* Construct a HttpExtension object.
|
||||||
* @param method Required value denoting the HttpMethod.
|
* @param method Required value denoting the HttpMethod.
|
||||||
* @param queryString map for the queryString the HTTP call.
|
* @param queryParams map for the query parameters the HTTP call.
|
||||||
* @param headers map to set HTTP headers.
|
* @param headers map to set HTTP headers.
|
||||||
* @see io.dapr.client.DaprHttp.HttpMethods for supported methods.
|
* @see io.dapr.client.DaprHttp.HttpMethods for supported methods.
|
||||||
* @throws IllegalArgumentException on null method or queryString.
|
* @throws IllegalArgumentException on null method or queryString.
|
||||||
*/
|
*/
|
||||||
public HttpExtension(DaprHttp.HttpMethods method, Map<String, String> queryString, Map<String, String> headers) {
|
public HttpExtension(DaprHttp.HttpMethods method,
|
||||||
|
Map<String, List<String>> queryParams,
|
||||||
|
Map<String, String> headers) {
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
throw new IllegalArgumentException("HttpExtension method cannot be null");
|
throw new IllegalArgumentException("HttpExtension method cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.queryString = Collections.unmodifiableMap(queryString == null ? Collections.EMPTY_MAP : queryString);
|
this.queryParams = Collections.unmodifiableMap(queryParams == null ? Collections.emptyMap() : queryParams);
|
||||||
this.headers = Collections.unmodifiableMap(headers == null ? Collections.EMPTY_MAP : headers);
|
this.headers = Collections.unmodifiableMap(headers == null ? Collections.emptyMap() : headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,11 +106,31 @@ public final class HttpExtension {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getQueryString() {
|
public Map<String, List<String>> getQueryParams() {
|
||||||
return queryString;
|
return queryParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getHeaders() {
|
public Map<String, String> getHeaders() {
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the query string for the HTTP request.
|
||||||
|
* @return Encoded HTTP query string.
|
||||||
|
*/
|
||||||
|
public String encodeQueryString() {
|
||||||
|
if ((this.queryParams == null) || (this.queryParams.isEmpty())) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpUrl.Builder urlBuilder = new HttpUrl.Builder();
|
||||||
|
// Setting required values but we only need query params in the end.
|
||||||
|
urlBuilder.scheme("http").host("localhost");
|
||||||
|
Optional.ofNullable(this.queryParams).orElse(Collections.emptyMap()).entrySet().stream()
|
||||||
|
.forEach(urlParameter ->
|
||||||
|
Optional.ofNullable(urlParameter.getValue()).orElse(Collections.emptyList()).stream()
|
||||||
|
.forEach(urlParameterValue ->
|
||||||
|
urlBuilder.addQueryParameter(urlParameter.getKey(), urlParameterValue)));
|
||||||
|
return urlBuilder.build().encodedQuery();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,4 +149,26 @@ public class CloudEventTest {
|
||||||
assertEquals("AQI=", cloudEvent.getData());
|
assertEquals("AQI=", cloudEvent.getData());
|
||||||
assertArrayEquals(expected, OBJECT_MAPPER.convertValue(cloudEvent.getData(), byte[].class));
|
assertArrayEquals(expected, OBJECT_MAPPER.convertValue(cloudEvent.getData(), byte[].class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deserializeBinaryData() throws Exception {
|
||||||
|
String content = "{\n" +
|
||||||
|
" \"specversion\" : \"1.0\",\n" +
|
||||||
|
" \"type\" : \"com.github.pull_request.opened\",\n" +
|
||||||
|
" \"source\" : \"https://github.com/cloudevents/spec/pull\",\n" +
|
||||||
|
" \"subject\" : \"123\",\n" +
|
||||||
|
" \"id\" : \"A234-1234-1234\",\n" +
|
||||||
|
" \"time\" : \"2018-04-05T17:31:00Z\",\n" +
|
||||||
|
" \"comexampleextension1\" : \"value\",\n" +
|
||||||
|
" \"comexampleothervalue\" : 5,\n" +
|
||||||
|
" \"datacontenttype\" : \"application/octet-stream\",\n" +
|
||||||
|
" \"data_base64\" : \"AQI=\"\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
byte[] expected = new byte[]{ 0x1, 0x2 };
|
||||||
|
CloudEvent cloudEvent = CloudEvent.deserialize(content.getBytes());
|
||||||
|
assertEquals("application/octet-stream", cloudEvent.getDatacontenttype());
|
||||||
|
assertNull(cloudEvent.getData());
|
||||||
|
assertArrayEquals(expected, cloudEvent.getBinaryData());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,14 +549,14 @@ public class DaprClientGrpcTest {
|
||||||
@Test
|
@Test
|
||||||
public void invokeServiceWithHttpExtensionTest() throws IOException {
|
public void invokeServiceWithHttpExtensionTest() throws IOException {
|
||||||
HttpExtension httpExtension = new HttpExtension(
|
HttpExtension httpExtension = new HttpExtension(
|
||||||
DaprHttp.HttpMethods.GET, Collections.singletonMap("test", "1"), null);
|
DaprHttp.HttpMethods.GET, Collections.singletonMap("test", Arrays.asList("1", "ab/c")), null);
|
||||||
CommonProtos.InvokeRequest message = CommonProtos.InvokeRequest.newBuilder()
|
CommonProtos.InvokeRequest message = CommonProtos.InvokeRequest.newBuilder()
|
||||||
.setMethod("method")
|
.setMethod("method")
|
||||||
.setData(getAny("request"))
|
.setData(getAny("request"))
|
||||||
.setContentType("application/json")
|
.setContentType("application/json")
|
||||||
.setHttpExtension(CommonProtos.HTTPExtension.newBuilder()
|
.setHttpExtension(CommonProtos.HTTPExtension.newBuilder()
|
||||||
.setVerb(CommonProtos.HTTPExtension.Verb.GET)
|
.setVerb(CommonProtos.HTTPExtension.Verb.GET)
|
||||||
.putQuerystring("test", "1").build())
|
.setQuerystring("test=1&test=ab%2Fc").build())
|
||||||
.build();
|
.build();
|
||||||
DaprProtos.InvokeServiceRequest request = DaprProtos.InvokeServiceRequest.newBuilder()
|
DaprProtos.InvokeServiceRequest request = DaprProtos.InvokeServiceRequest.newBuilder()
|
||||||
.setId("appId")
|
.setId("appId")
|
||||||
|
|
|
@ -336,11 +336,12 @@ public class DaprClientHttpTest {
|
||||||
public void invokeServiceWithRequestAndQueryString() {
|
public void invokeServiceWithRequestAndQueryString() {
|
||||||
Map<String, String> map = new HashMap<>();
|
Map<String, String> map = new HashMap<>();
|
||||||
mockInterceptor.addRule()
|
mockInterceptor.addRule()
|
||||||
.get("http://127.0.0.1:3000/v1.0/invoke/41/method/neworder?test=1")
|
.get("http://127.0.0.1:3000/v1.0/invoke/41/method/neworder?param1=1¶m2=a¶m2=b%2Fc")
|
||||||
.respond(EXPECTED_RESULT);
|
.respond(EXPECTED_RESULT);
|
||||||
|
|
||||||
Map<String, String> queryString = new HashMap<>();
|
Map<String, List<String>> queryString = new HashMap<>();
|
||||||
queryString.put("test", "1");
|
queryString.put("param1", Collections.singletonList("1"));
|
||||||
|
queryString.put("param2", Arrays.asList("a", "b/c"));
|
||||||
HttpExtension httpExtension = new HttpExtension(DaprHttp.HttpMethods.GET, queryString, null);
|
HttpExtension httpExtension = new HttpExtension(DaprHttp.HttpMethods.GET, queryString, null);
|
||||||
Mono<Void> mono = daprClientHttp.invokeMethod("41", "neworder", "", httpExtension, map);
|
Mono<Void> mono = daprClientHttp.invokeMethod("41", "neworder", "", httpExtension, map);
|
||||||
assertNull(mono.block());
|
assertNull(mono.block());
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
|
|
||||||
package io.dapr.client;
|
package io.dapr.client;
|
||||||
|
|
||||||
import reactor.util.context.Context;
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.util.context.Context;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,7 +33,11 @@ public class DaprHttpStub extends DaprHttp {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Mono<Response> invokeApi(String method, String[] pathSegments, Map<String, String> urlParameters, Map<String, String> headers, Context context) {
|
public Mono<Response> invokeApi(String method,
|
||||||
|
String[] pathSegments,
|
||||||
|
Map<String, List<String>> urlParameters,
|
||||||
|
Map<String, String> headers,
|
||||||
|
Context context) {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +45,12 @@ public class DaprHttpStub extends DaprHttp {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Mono<Response> invokeApi(String method, String[] pathSegments, Map<String, String> urlParameters, String content, Map<String, String> headers, Context context) {
|
public Mono<Response> invokeApi(String method,
|
||||||
|
String[] pathSegments,
|
||||||
|
Map<String, List<String>> urlParameters,
|
||||||
|
String content,
|
||||||
|
Map<String, String> headers,
|
||||||
|
Context context) {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +58,12 @@ public class DaprHttpStub extends DaprHttp {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Mono<Response> invokeApi(String method, String[] pathSegments, Map<String, String> urlParameters, byte[] content, Map<String, String> headers, Context context) {
|
public Mono<Response> invokeApi(String method,
|
||||||
|
String[] pathSegments,
|
||||||
|
Map<String, List<String>> urlParameters,
|
||||||
|
byte[] content,
|
||||||
|
Map<String, String> headers,
|
||||||
|
Context context) {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,9 @@ import org.junit.contrib.java.lang.system.EnvironmentVariables;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -141,8 +143,8 @@ public class DaprHttpTest {
|
||||||
Map<String, String> headers = new HashMap<>();
|
Map<String, String> headers = new HashMap<>();
|
||||||
headers.put("header", "value");
|
headers.put("header", "value");
|
||||||
headers.put("header1", "value1");
|
headers.put("header1", "value1");
|
||||||
Map<String, String> urlParameters = new HashMap<>();
|
Map<String, List<String>> urlParameters = new HashMap<>();
|
||||||
urlParameters.put("orderId", "41");
|
urlParameters.put("orderId", Collections.singletonList("41"));
|
||||||
mockInterceptor.addRule()
|
mockInterceptor.addRule()
|
||||||
.get("http://127.0.0.1:3500/v1.0/state/order?orderId=41")
|
.get("http://127.0.0.1:3500/v1.0/state/order?orderId=41")
|
||||||
.respond(serializer.serialize(EXPECTED_RESULT));
|
.respond(serializer.serialize(EXPECTED_RESULT));
|
||||||
|
|
Loading…
Reference in New Issue