Browse Source

Add support for "application/*+x-protobuf" media type

See gh-34645

Signed-off-by: Kamil Doroszkiewicz <kamil.doroszkiewicz@gmail.com>
pull/34996/head
Kamil Doroszkiewicz 12 months ago committed by Brian Clozel
parent
commit
c1839938ea
  1. 22
      spring-web/src/main/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverter.java
  2. 3
      spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverterTests.java
  3. 3
      spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufJsonFormatHttpMessageConverterTests.java

22
spring-web/src/main/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverter.java

@ -41,7 +41,6 @@ import org.springframework.http.converter.AbstractHttpMessageConverter; @@ -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; @@ -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; @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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

3
spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverterTests.java

@ -48,12 +48,14 @@ class ProtobufHttpMessageConverterTests { @@ -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 { @@ -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();
}

3
spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufJsonFormatHttpMessageConverterTests.java

@ -42,12 +42,14 @@ class ProtobufJsonFormatHttpMessageConverterTests { @@ -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 { @@ -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();
}

Loading…
Cancel
Save