Add support for "application/*+x-protobuf" media type
See gh-34645 Signed-off-by: Kamil Doroszkiewicz <kamil.doroszkiewicz@gmail.com>
This commit is contained in:
committed by
Brian Clozel
parent
79a793e44c
commit
c1839938ea
@@ -41,7 +41,6 @@ import org.springframework.http.converter.AbstractHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConversionException;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
|
||||
@@ -55,8 +54,8 @@ import static org.springframework.http.MediaType.TEXT_PLAIN;
|
||||
*
|
||||
* <p>To generate {@code Message} Java classes, you need to install the {@code protoc} binary.
|
||||
*
|
||||
* <p>This converter supports by default {@code "application/x-protobuf"} and {@code "text/plain"}
|
||||
* with the official {@code "com.google.protobuf:protobuf-java"} library.
|
||||
* <p>This converter supports by default {@code "application/x-protobuf"}, {@code "application/*+x-protobuf"}
|
||||
* and {@code "text/plain"} with the official {@code "com.google.protobuf:protobuf-java"} library.
|
||||
* The {@code "application/json"} format is also supported with the {@code "com.google.protobuf:protobuf-java-util"}
|
||||
* dependency. See {@link ProtobufJsonFormatHttpMessageConverter} for a configurable variant.
|
||||
*
|
||||
@@ -66,6 +65,7 @@ import static org.springframework.http.MediaType.TEXT_PLAIN;
|
||||
* @author Brian Clozel
|
||||
* @author Juergen Hoeller
|
||||
* @author Sebastien Deleuze
|
||||
* @author Kamil Doroszkiewicz
|
||||
* @since 4.1
|
||||
* @see JsonFormat
|
||||
* @see ProtobufJsonFormatHttpMessageConverter
|
||||
@@ -82,6 +82,11 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
|
||||
*/
|
||||
public static final MediaType PROTOBUF = new MediaType("application", "x-protobuf", DEFAULT_CHARSET);
|
||||
|
||||
/**
|
||||
* The media-type for protobuf {@code application/*+x-protobuf}.
|
||||
*/
|
||||
public static final MediaType PLUS_PROTOBUF = new MediaType("application", "*+x-protobuf", DEFAULT_CHARSET);
|
||||
|
||||
/**
|
||||
* The HTTP header containing the protobuf schema.
|
||||
*/
|
||||
@@ -132,7 +137,7 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
|
||||
}
|
||||
|
||||
setSupportedMediaTypes(Arrays.asList(this.protobufFormatSupport != null ?
|
||||
this.protobufFormatSupport.supportedMediaTypes() : new MediaType[] {PROTOBUF, TEXT_PLAIN}));
|
||||
this.protobufFormatSupport.supportedMediaTypes() : new MediaType[] {PROTOBUF, PLUS_PROTOBUF, TEXT_PLAIN}));
|
||||
|
||||
this.extensionRegistry = (extensionRegistry == null ? ExtensionRegistry.newInstance() : extensionRegistry);
|
||||
}
|
||||
@@ -162,7 +167,8 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
|
||||
}
|
||||
|
||||
Message.Builder builder = getMessageBuilder(clazz);
|
||||
if (PROTOBUF.isCompatibleWith(contentType)) {
|
||||
if (PROTOBUF.isCompatibleWith(contentType) ||
|
||||
PLUS_PROTOBUF.isCompatibleWith(contentType)) {
|
||||
builder.mergeFrom(inputMessage.getBody(), this.extensionRegistry);
|
||||
}
|
||||
else if (TEXT_PLAIN.isCompatibleWith(contentType)) {
|
||||
@@ -209,14 +215,14 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
|
||||
MediaType contentType = outputMessage.getHeaders().getContentType();
|
||||
if (contentType == null) {
|
||||
contentType = getDefaultContentType(message);
|
||||
Assert.state(contentType != null, "No content type");
|
||||
}
|
||||
Charset charset = contentType.getCharset();
|
||||
if (charset == null) {
|
||||
charset = DEFAULT_CHARSET;
|
||||
}
|
||||
|
||||
if (PROTOBUF.isCompatibleWith(contentType)) {
|
||||
if (PROTOBUF.isCompatibleWith(contentType) ||
|
||||
PLUS_PROTOBUF.isCompatibleWith(contentType)) {
|
||||
setProtoHeader(outputMessage, message);
|
||||
CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputMessage.getBody());
|
||||
message.writeTo(codedOutputStream);
|
||||
@@ -285,7 +291,7 @@ public class ProtobufHttpMessageConverter extends AbstractHttpMessageConverter<M
|
||||
|
||||
@Override
|
||||
public MediaType[] supportedMediaTypes() {
|
||||
return new MediaType[] {PROTOBUF, TEXT_PLAIN, APPLICATION_JSON};
|
||||
return new MediaType[] {PROTOBUF, PLUS_PROTOBUF, TEXT_PLAIN, APPLICATION_JSON};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,12 +48,14 @@ class ProtobufHttpMessageConverterTests {
|
||||
private ExtensionRegistry extensionRegistry = mock();
|
||||
|
||||
private Msg testMsg = Msg.newBuilder().setFoo("Foo").setBlah(SecondMsg.newBuilder().setBlah(123).build()).build();
|
||||
private MediaType testPlusProtoMediaType = MediaType.parseMediaType("application/vnd.example.public.v1+x-protobuf");
|
||||
|
||||
|
||||
@Test
|
||||
void canRead() {
|
||||
assertThat(this.converter.canRead(Msg.class, null)).isTrue();
|
||||
assertThat(this.converter.canRead(Msg.class, ProtobufHttpMessageConverter.PROTOBUF)).isTrue();
|
||||
assertThat(this.converter.canRead(Msg.class, this.testPlusProtoMediaType)).isTrue();
|
||||
assertThat(this.converter.canRead(Msg.class, MediaType.APPLICATION_JSON)).isTrue();
|
||||
assertThat(this.converter.canRead(Msg.class, MediaType.TEXT_PLAIN)).isTrue();
|
||||
}
|
||||
@@ -62,6 +64,7 @@ class ProtobufHttpMessageConverterTests {
|
||||
void canWrite() {
|
||||
assertThat(this.converter.canWrite(Msg.class, null)).isTrue();
|
||||
assertThat(this.converter.canWrite(Msg.class, ProtobufHttpMessageConverter.PROTOBUF)).isTrue();
|
||||
assertThat(this.converter.canRead(Msg.class, this.testPlusProtoMediaType)).isTrue();
|
||||
assertThat(this.converter.canWrite(Msg.class, MediaType.APPLICATION_JSON)).isTrue();
|
||||
assertThat(this.converter.canWrite(Msg.class, MediaType.TEXT_PLAIN)).isTrue();
|
||||
}
|
||||
|
||||
@@ -42,12 +42,14 @@ class ProtobufJsonFormatHttpMessageConverterTests {
|
||||
JsonFormat.parser(), JsonFormat.printer());
|
||||
|
||||
private final Msg testMsg = Msg.newBuilder().setFoo("Foo").setBlah(SecondMsg.newBuilder().setBlah(123).build()).build();
|
||||
private MediaType testPlusProtoMediaType = MediaType.parseMediaType("application/vnd.examle.public.v1+x-protobuf");
|
||||
|
||||
|
||||
@Test
|
||||
void canRead() {
|
||||
assertThat(this.converter.canRead(Msg.class, null)).isTrue();
|
||||
assertThat(this.converter.canRead(Msg.class, ProtobufHttpMessageConverter.PROTOBUF)).isTrue();
|
||||
assertThat(this.converter.canRead(Msg.class, this.testPlusProtoMediaType)).isTrue();
|
||||
assertThat(this.converter.canRead(Msg.class, MediaType.APPLICATION_JSON)).isTrue();
|
||||
assertThat(this.converter.canRead(Msg.class, MediaType.TEXT_PLAIN)).isTrue();
|
||||
}
|
||||
@@ -56,6 +58,7 @@ class ProtobufJsonFormatHttpMessageConverterTests {
|
||||
void canWrite() {
|
||||
assertThat(this.converter.canWrite(Msg.class, null)).isTrue();
|
||||
assertThat(this.converter.canWrite(Msg.class, ProtobufHttpMessageConverter.PROTOBUF)).isTrue();
|
||||
assertThat(this.converter.canWrite(Msg.class, this.testPlusProtoMediaType)).isTrue();
|
||||
assertThat(this.converter.canWrite(Msg.class, MediaType.APPLICATION_JSON)).isTrue();
|
||||
assertThat(this.converter.canWrite(Msg.class, MediaType.TEXT_PLAIN)).isTrue();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user