Skip to content

Commit efc804b

Browse files
committed
Motivation:
- Allow customization of JSON printer and parser configurations for gRPC transcoding trough WireFormat configuration. Changes: - Added ability to configure supported wireformats on server. - Added `JsonWireFormat` and `ProtobufWireFormat` as concrete implementations of `WireFormat`. - Updated `GrpcMessageEncoder` and `GrpcMessageDecoder` to respect custom wire formats. - Added `ProtobufJsonReader` and `ProtobufJsonWriter`. - Updated transcoding logic to use specific wire formats. Signed-off-by: Daniel Fiala <danfiala23@gmail.com>
1 parent 27277d0 commit efc804b

27 files changed

Lines changed: 1050 additions & 225 deletions

File tree

vertx-grpc-client/src/main/java/io/vertx/grpc/client/impl/Http2GrpcOutboundStream.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
import io.vertx.grpc.common.GrpcError;
1515
import io.vertx.grpc.common.GrpcHeaderNames;
1616
import io.vertx.grpc.common.GrpcMessage;
17+
import io.vertx.grpc.common.JsonWireFormat;
18+
import io.vertx.grpc.common.ProtobufWireFormat;
1719
import io.vertx.grpc.common.ServiceName;
20+
import io.vertx.grpc.common.WireFormat;
1821
import io.vertx.grpc.common.impl.DefaultGrpcMessage;
1922
import io.vertx.grpc.common.impl.GrpcFrame;
2023
import io.vertx.grpc.common.impl.GrpcHeadersFrame;
@@ -97,15 +100,13 @@ private Future<Void> handleHeadersFrame(GrpcHeadersFrame frame, boolean end) {
97100
}
98101

99102
String contentType;
100-
switch (frame.format()) {
101-
case PROTOBUF:
102-
contentType = "application/grpc";
103-
break;
104-
case JSON:
105-
contentType = "application/grpc+json";
106-
break;
107-
default:
108-
throw new UnsupportedOperationException();
103+
WireFormat format = frame.format();
104+
if (format instanceof ProtobufWireFormat) {
105+
contentType = "application/grpc";
106+
} else if (format instanceof JsonWireFormat) {
107+
contentType = "application/grpc+json";
108+
} else {
109+
throw new UnsupportedOperationException();
109110
}
110111

111112
String uri = serviceName.pathOf(methodName);

vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcMessageDecoder.java

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@
1515
import com.google.protobuf.Message;
1616
import com.google.protobuf.MessageOrBuilder;
1717
import com.google.protobuf.Parser;
18-
import com.google.protobuf.util.JsonFormat;
1918
import io.vertx.codegen.annotations.Unstable;
2019
import io.vertx.core.buffer.Buffer;
2120
import io.vertx.core.json.DecodeException;
2221
import io.vertx.core.json.Json;
2322
import io.vertx.core.json.JsonObject;
2423
import io.vertx.core.json.JsonArray;
2524

26-
import java.nio.charset.StandardCharsets;
2725
import java.util.function.Supplier;
2826

2927
public interface GrpcMessageDecoder<T> {
@@ -39,23 +37,20 @@ static <T> GrpcMessageDecoder<T> decoder(MessageOrBuilder messageOrBuilder) {
3937
return new GrpcMessageDecoder<>() {
4038
@Override
4139
public T decode(GrpcMessage msg) throws CodecException {
42-
switch (msg.format()) {
43-
case PROTOBUF:
44-
try {
45-
return parser.parseFrom(msg.payload().getBytes());
46-
} catch (InvalidProtocolBufferException e) {
47-
throw new CodecException(e);
48-
}
49-
case JSON:
50-
try {
51-
Message.Builder builder = dit.toBuilder();
52-
JsonFormat.parser().merge(msg.payload().toString(StandardCharsets.UTF_8), builder);
53-
return (T) builder.build();
54-
} catch (InvalidProtocolBufferException e) {
55-
throw new CodecException(e);
56-
}
57-
default:
58-
throw new IllegalArgumentException("Invalid wire format: " + msg.format());
40+
WireFormat format = msg.format();
41+
if (format instanceof ProtobufWireFormat) {
42+
try {
43+
return parser.parseFrom(msg.payload().getBytes());
44+
} catch (InvalidProtocolBufferException e) {
45+
throw new CodecException(e);
46+
}
47+
} else if (format instanceof JsonWireFormat) {
48+
JsonWireFormat json = (JsonWireFormat) format;
49+
Message.Builder builder = dit.toBuilder();
50+
ProtobufJsonReader.create(json.readerConfig()).merge(msg.payload(), builder);
51+
return (T) builder.build();
52+
} else {
53+
throw new IllegalArgumentException("Invalid wire format: " + format);
5954
}
6055
}
6156
@Override
@@ -89,17 +84,14 @@ static <T> GrpcMessageDecoder<T> json(Supplier<Message.Builder> builder) {
8984
return new GrpcMessageDecoder<>() {
9085
@Override
9186
public T decode(GrpcMessage msg) throws CodecException {
92-
try {
93-
Message.Builder builderInstance = builder.get();
94-
JsonFormat.parser().merge(msg.payload().toString(StandardCharsets.UTF_8), builderInstance);
95-
return (T) builderInstance.build();
96-
} catch (InvalidProtocolBufferException e) {
97-
throw new CodecException(e);
98-
}
87+
JsonWireFormat json = (JsonWireFormat) msg.format();
88+
Message.Builder builderInstance = builder.get();
89+
ProtobufJsonReader.create(json.readerConfig()).merge(msg.payload(), builderInstance);
90+
return (T) builderInstance.build();
9991
}
10092
@Override
10193
public boolean accepts(WireFormat format) {
102-
return format == WireFormat.JSON;
94+
return format instanceof JsonWireFormat;
10395
}
10496
};
10597
}
@@ -115,7 +107,7 @@ static <T> GrpcMessageDecoder<T> json(Class<T> clazz) {
115107
return new GrpcMessageDecoder<>() {
116108
@Override
117109
public T decode(GrpcMessage msg) throws CodecException {
118-
if (!WireFormat.JSON.equals(msg.format())) {
110+
if (!(msg.format() instanceof JsonWireFormat)) {
119111
throw new CodecException("Was expecting a json message");
120112
}
121113
try {
@@ -126,7 +118,7 @@ public T decode(GrpcMessage msg) throws CodecException {
126118
}
127119
@Override
128120
public boolean accepts(WireFormat format) {
129-
return format == WireFormat.JSON;
121+
return format instanceof JsonWireFormat;
130122
}
131123
};
132124
}
@@ -146,7 +138,7 @@ public JsonObject decode(GrpcMessage msg) throws CodecException {
146138
}
147139
@Override
148140
public boolean accepts(WireFormat format) {
149-
return format == WireFormat.JSON;
141+
return format instanceof JsonWireFormat;
150142
}
151143
};
152144

@@ -156,7 +148,7 @@ public boolean accepts(WireFormat format) {
156148
GrpcMessageDecoder<Object> JSON_VALUE = new GrpcMessageDecoder<Object>() {
157149
@Override
158150
public Object decode(GrpcMessage msg) throws CodecException {
159-
if (!WireFormat.JSON.equals(msg.format())) {
151+
if (!(msg.format() instanceof JsonWireFormat)) {
160152
throw new CodecException("Was expecting a json message");
161153
}
162154
try {
@@ -167,7 +159,7 @@ public Object decode(GrpcMessage msg) throws CodecException {
167159
}
168160
@Override
169161
public boolean accepts(WireFormat format) {
170-
return format == WireFormat.JSON;
162+
return format instanceof JsonWireFormat;
171163
}
172164
};
173165

vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcMessageEncoder.java

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package io.vertx.grpc.common;
22

3-
import com.google.protobuf.InvalidProtocolBufferException;
43
import com.google.protobuf.MessageLite;
54
import com.google.protobuf.MessageOrBuilder;
6-
import com.google.protobuf.util.JsonFormat;
75
import io.vertx.codegen.annotations.GenIgnore;
86
import io.vertx.core.buffer.Buffer;
97
import io.vertx.core.json.Json;
@@ -20,26 +18,17 @@ static <T extends MessageLite> GrpcMessageEncoder<T> encoder() {
2018
return new GrpcMessageEncoder<T>() {
2119
@Override
2220
public GrpcMessage encode(T msg, WireFormat format) throws CodecException {
23-
switch (format) {
24-
case PROTOBUF:
25-
byte[] bytes = msg.toByteArray();
26-
return GrpcMessage.message("identity", Buffer.buffer(bytes));
27-
case JSON:
28-
if (msg instanceof MessageOrBuilder) {
29-
MessageOrBuilder mob = (MessageOrBuilder) msg;
30-
try {
31-
String res = JsonFormat.printer().print(mob);
32-
return GrpcMessage.message("identity", WireFormat.JSON, Buffer.buffer(res));
33-
} catch (InvalidProtocolBufferException e) {
34-
throw new CodecException(e);
35-
}
36-
}
37-
return GrpcMessage.message(
38-
"identity",
39-
WireFormat.JSON,
40-
Json.encodeToBuffer(msg));
41-
default:
42-
throw new IllegalArgumentException("Invalid wire format: " + format);
21+
if (format instanceof ProtobufWireFormat) {
22+
byte[] bytes = msg.toByteArray();
23+
return GrpcMessage.message("identity", format, Buffer.buffer(bytes));
24+
} else if (format instanceof JsonWireFormat) {
25+
JsonWireFormat json = (JsonWireFormat) format;
26+
if (msg instanceof MessageOrBuilder) {
27+
return GrpcMessage.message("identity", format, ProtobufJsonWriter.create(json.writerConfig()).write((MessageOrBuilder) msg));
28+
}
29+
return GrpcMessage.message("identity", format, Json.encodeToBuffer(msg));
30+
} else {
31+
throw new IllegalArgumentException("Invalid wire format: " + format);
4332
}
4433
}
4534
@Override
@@ -70,23 +59,15 @@ static <T> GrpcMessageEncoder<T> json() {
7059
return new GrpcMessageEncoder<>() {
7160
@Override
7261
public GrpcMessage encode(T msg, WireFormat format) throws CodecException {
62+
JsonWireFormat json = (JsonWireFormat) format;
7363
if (msg instanceof MessageOrBuilder) {
74-
MessageOrBuilder mob = (MessageOrBuilder) msg;
75-
try {
76-
String res = JsonFormat.printer().print(mob);
77-
return GrpcMessage.message("identity", WireFormat.JSON, Buffer.buffer(res));
78-
} catch (InvalidProtocolBufferException e) {
79-
throw new CodecException(e);
80-
}
64+
return GrpcMessage.message("identity", format, ProtobufJsonWriter.create(json.writerConfig()).write((MessageOrBuilder) msg));
8165
}
82-
return GrpcMessage.message(
83-
"identity",
84-
WireFormat.JSON,
85-
Json.encodeToBuffer(msg));
66+
return GrpcMessage.message("identity", format, Json.encodeToBuffer(msg));
8667
}
8768
@Override
8869
public boolean accepts(WireFormat format) {
89-
return format == WireFormat.JSON;
70+
return format instanceof JsonWireFormat;
9071
}
9172
};
9273
}
@@ -97,11 +78,11 @@ public boolean accepts(WireFormat format) {
9778
GrpcMessageEncoder<JsonObject> JSON_OBJECT = new GrpcMessageEncoder<>() {
9879
@Override
9980
public GrpcMessage encode(JsonObject msg, WireFormat format) throws CodecException {
100-
return GrpcMessage.message("identity", WireFormat.JSON, msg == null ? Buffer.buffer("null") : msg.toBuffer());
81+
return GrpcMessage.message("identity", format, msg == null ? Buffer.buffer("null") : msg.toBuffer());
10182
}
10283
@Override
10384
public boolean accepts(WireFormat format) {
104-
return format == WireFormat.JSON;
85+
return format instanceof JsonWireFormat;
10586
}
10687
};
10788

0 commit comments

Comments
 (0)