Protobuf: Enhance textual content-types detection (#444)

- Move content-type introspection in a separate support class.
- Add unit tests to ensure introspection is correct.

Signed-off-by: Day, Jeremy(jday) <jday@paypal.com>
This commit is contained in:
Jem Day 2022-01-31 01:18:22 -08:00 committed by GitHub
parent 4784f03e8c
commit a4bc7a8368
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 104 additions and 10 deletions

View File

@ -77,15 +77,6 @@ class ProtoSerializer {
}
}
// The proto spec says all text data should go into the text field. It is really difficult to figure out every case
// of text data based on the media type though, so I am just going to check for some common cases.
private static boolean isTextType(String type) {
if (type == null) {
return false;
}
return type.startsWith("text/") || "application/json".equals(type) || "application/xml".equals(type);
}
/**
* Defines a {@link CloudEventContextWriter} that will allow setting the attributes within a Protobuf object.
*/
@ -272,9 +263,16 @@ class ProtoSerializer {
throw CloudEventRWException.newDataConversion(e, "byte[]", "com.google.protobuf.Any");
}
protoBuilder.setProtoData(dataAsAny);
} else if (isTextType(dataContentType)) {
} else if (ProtoSupport.isTextContent(dataContentType)) {
/**
* The protobuf format specification states that textual data must
* be carried in the 'text_data' field.
*/
protoBuilder.setTextDataBytes(ByteString.copyFrom(data.toBytes()));
} else {
/**
* All other content is assumed to be binary.
*/
ByteString byteString = ByteString.copyFrom(data.toBytes());
protoBuilder.setBinaryData(byteString);
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.cloudevents.protobuf;
/**
* General support functions.
*/
final class ProtoSupport {
// Prevent Instantiation
private ProtoSupport() {
}
/**
* Determine if the given content type indicates that
* content is textual.
*/
static boolean isTextContent(String contentType) {
if (contentType == null) {
return false;
}
return contentType.startsWith("text/")
|| "application/json".equals(contentType)
|| "application/xml".equals(contentType)
|| contentType.endsWith("+json")
|| contentType.endsWith("+xml")
;
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.cloudevents.protobuf;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.io.IOException;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
public class ProtoSupportTest {
@ParameterizedTest
@MethodSource("textContentArguments")
public void serialize(String contentType, boolean isText) throws IOException {
assertThat(isText).isEqualTo(ProtoSupport.isTextContent(contentType));
}
// Test Data set for contentType text determination.
public static Stream<Arguments> textContentArguments() {
return Stream.of(
Arguments.of("application/json", true),
Arguments.of("application/xml", true),
Arguments.of("text/plain", true),
Arguments.of("application/protobuf", false),
Arguments.of("application/fubar+xml", true),
Arguments.of("application/fubar+json", true)
);
}
}