This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
commit 3d4c0b071ca676e20d8c4f65bb664fcb65081fc0 Author: liubao <[email protected]> AuthorDate: Mon Aug 21 20:18:37 2023 +0800 [SCB-2803]add request proto-buffer codec --- common/common-protobuf/pom.xml | 4 - common/common-rest/pom.xml | 4 + .../rest/codec/param/BodyProcessorCreator.java | 184 ++++++++++++++++----- .../rest/codec/param/CookieProcessorCreator.java | 4 +- .../rest/codec/param/FormProcessorCreator.java | 4 +- .../rest/codec/param/HeaderProcessorCreator.java | 4 +- .../codec/param/ParamValueProcessorCreator.java | 5 +- .../rest/codec/param/PathProcessorCreator.java | 4 +- .../rest/codec/param/QueryProcessorCreator.java | 4 +- .../common/rest/definition/RestOperationMeta.java | 4 +- .../common/rest/definition/RestParam.java | 18 +- .../common/rest/codec/TestRestCodec.java | 2 +- .../common/rest/codec/param/TestBodyProcessor.java | 48 +++--- .../rest/codec/param/TestBodyProcessorCreator.java | 4 +- .../codec/param/TestCookieProcessorCreator.java | 2 +- .../rest/codec/param/TestFormProcessorCreator.java | 2 +- .../codec/param/TestHeaderProcessorCreator.java | 2 +- .../rest/codec/param/TestPathProcessorCreator.java | 2 +- .../codec/param/TestQueryProcessorCreator.java | 4 +- .../common/rest/definition/TestPath.java | 6 +- .../definition/path/QueryVarParamWriterTest.java | 6 +- .../rest/definition/path/URLPathBuilderTest.java | 2 +- .../parameter/RawJsonRequestBodyProcessor.java | 6 + .../src/test/resources/schemas/echo.yaml | 3 - .../src/test/resources/schemas/echo.yaml | 3 - 25 files changed, 228 insertions(+), 103 deletions(-) diff --git a/common/common-protobuf/pom.xml b/common/common-protobuf/pom.xml index 08e2a9a02..b94386e03 100644 --- a/common/common-protobuf/pom.xml +++ b/common/common-protobuf/pom.xml @@ -31,10 +31,6 @@ <groupId>org.apache.servicecomb</groupId> <artifactId>java-chassis-core</artifactId> </dependency> - <dependency> - <groupId>org.apache.servicecomb</groupId> - <artifactId>swagger-invocation-core</artifactId> - </dependency> <dependency> <groupId>org.apache.servicecomb</groupId> diff --git a/common/common-rest/pom.xml b/common/common-rest/pom.xml index 1233e8fed..d9202f5be 100644 --- a/common/common-rest/pom.xml +++ b/common/common-rest/pom.xml @@ -34,6 +34,10 @@ <groupId>org.apache.servicecomb</groupId> <artifactId>java-chassis-core</artifactId> </dependency> + <dependency> + <groupId>org.apache.servicecomb</groupId> + <artifactId>common-protobuf</artifactId> + </dependency> <dependency> <groupId>io.vertx</groupId> diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java index 4c58902eb..dd177a31c 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java @@ -21,16 +21,26 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; -import java.util.Locale; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.http.entity.ContentType; +import org.apache.servicecomb.codec.protobuf.utils.ScopedProtobufSchemaManager; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.foundation.protobuf.ProtoMapper; +import org.apache.servicecomb.foundation.protobuf.RootDeserializer; +import org.apache.servicecomb.foundation.protobuf.RootSerializer; +import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper; import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream; import org.apache.servicecomb.swagger.SwaggerUtils; -import org.apache.servicecomb.swagger.converter.ConverterMgr; import org.apache.servicecomb.swagger.generator.SwaggerConst; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; @@ -43,7 +53,7 @@ import com.fasterxml.jackson.databind.type.SimpleType; import com.fasterxml.jackson.databind.type.TypeFactory; import com.netflix.config.DynamicPropertyFactory; -import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.parameters.RequestBody; import io.vertx.core.buffer.Buffer; import io.vertx.core.buffer.impl.BufferImpl; @@ -56,6 +66,8 @@ import jakarta.ws.rs.core.Response.Status; public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestBody> { private static final Logger LOGGER = LoggerFactory.getLogger(BodyProcessorCreator.class); + public static final String EXT_ID = "protobuf"; + public static final String PARAM_TYPE = "body"; private static final JavaType OBJECT_TYPE = SimpleType.constructUnsafe(Object.class); @@ -64,6 +76,8 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB private static final boolean decodeAsObject = DynamicPropertyFactory.getInstance() .getBooleanProperty("servicecomb.rest.parameter.decodeAsObject", false).get(); + private static final Object LOCK = new Object(); + public static class BodyProcessor implements ParamValueProcessor { protected JavaType targetType; @@ -71,21 +85,57 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB protected boolean isRequired; - public BodyProcessor(JavaType targetType, boolean isString, boolean isRequired) { - this(targetType, null, isString, isRequired); - } + protected OpenAPI openAPI; - public BodyProcessor(JavaType targetType, String serialViewClass, boolean isString, boolean isRequired) { - if (!StringUtils.isEmpty(serialViewClass)) { + protected ScopedProtobufSchemaManager scopedProtobufSchemaManager; + + protected List<String> supportedContentTypes = new ArrayList<>(); + + protected OperationMeta operationMeta; + + protected RequestBody requestBody; + + public BodyProcessor(OperationMeta operationMeta, JavaType targetType, RequestBody parameter) { + if (!StringUtils.isEmpty((String) parameter.getExtensions() + .get(SwaggerConst.EXT_JSON_VIEW))) { try { - this.serialViewClass = Class.forName(serialViewClass); + this.serialViewClass = Class.forName((String) parameter.getExtensions() + .get(SwaggerConst.EXT_JSON_VIEW)); } catch (Throwable e) { //ignore LOGGER.warn("Failed to create body processor {}, annotation @JsonView may be invalid", serialViewClass, e); } } + + this.requestBody = new RequestBody(); this.targetType = targetType; - this.isRequired = isRequired; + this.isRequired = parameter.getRequired() != null && parameter.getRequired(); + if (parameter.getContent() != null) { + supportedContentTypes.addAll(parameter.getContent().keySet()); + } + + if (operationMeta != null) { + this.operationMeta = operationMeta; + this.openAPI = operationMeta.getSchemaMeta().getSwagger(); + if (supportedContentTypes.contains(SwaggerConst.PROTOBUF_TYPE)) { + this.scopedProtobufSchemaManager = getOrCreateScopedProtobufSchemaManager( + operationMeta.getMicroserviceMeta()); + } + } + } + + private ScopedProtobufSchemaManager getOrCreateScopedProtobufSchemaManager(MicroserviceMeta microserviceMeta) { + ScopedProtobufSchemaManager scopedProtobufSchemaManager = microserviceMeta.getExtData(EXT_ID); + if (scopedProtobufSchemaManager == null) { + synchronized (LOCK) { + scopedProtobufSchemaManager = microserviceMeta.getExtData(EXT_ID); + if (scopedProtobufSchemaManager == null) { + scopedProtobufSchemaManager = new ScopedProtobufSchemaManager(); + microserviceMeta.putExtData(EXT_ID, scopedProtobufSchemaManager); + } + } + } + return scopedProtobufSchemaManager; } @Override @@ -109,10 +159,9 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB } // edge support convert from form-data or x-www-form-urlencoded to json automatically - String contentType = request.getContentType(); - contentType = contentType == null ? "" : contentType.toLowerCase(Locale.US); - if (contentType.startsWith(MediaType.MULTIPART_FORM_DATA) - || contentType.startsWith(MediaType.APPLICATION_FORM_URLENCODED)) { + String contentType = parseContentType(request); + if (contentType.equals(MediaType.MULTIPART_FORM_DATA) + || contentType.equals(MediaType.APPLICATION_FORM_URLENCODED)) { return convertValue(request.getParameterMap(), targetType); } @@ -124,10 +173,25 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB return null; } - if (!contentType.isEmpty() && !contentType.startsWith(MediaType.APPLICATION_JSON)) { - // TODO: we should consider body encoding - return IOUtils.toString(inputStream, StandardCharsets.UTF_8); + if (!supportedContentTypes.contains(contentType)) { + throw new IllegalArgumentException(String.format("operation %s not support content-type %s", + operationMeta.getSchemaQualifiedName(), contentType)); + } + + if (SwaggerConst.PROTOBUF_TYPE.equals(contentType)) { + String messageName = (String) requestBody.getContent().get(SwaggerConst.PROTOBUF_TYPE).getExtensions() + .get(SwaggerConst.EXT_BODY_NAME); + ProtoMapper protoMapper = scopedProtobufSchemaManager + .getOrCreateProtoMapper(openAPI, operationMeta.getSchemaId(), + messageName, + requestBody.getContent().get(SwaggerConst.PROTOBUF_TYPE).getSchema()); + RootDeserializer<PropertyWrapper<Object>> deserializer = protoMapper.getDeserializerSchemaManager() + .createRootDeserializer(protoMapper.getProto().getMessage(messageName), targetType); + PropertyWrapper<Object> result = deserializer.deserialize(inputStream.readAllBytes()); + return result.getValue(); } + + // For application/json and text/plain try { ObjectReader reader = serialViewClass != null ? RestObjectMapperFactory.getRestObjectMapper().readerWithView(serialViewClass) @@ -147,6 +211,21 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB } } + private String parseContentType(HttpServletRequest request) { + String type = request.getContentType(); + if (StringUtils.isEmpty(type)) { + if (supportedContentTypes.size() == 0) { + throw new IllegalArgumentException("operation do not have any content type support."); + } + if (supportedContentTypes.contains(MediaType.APPLICATION_JSON)) { + return MediaType.APPLICATION_JSON; + } + return supportedContentTypes.get(0); + } + ContentType contentType = ContentType.parse(type); + return contentType.getMimeType(); + } + @Override public void setValue(RestClientRequest clientRequest, Object arg) throws Exception { ensureContentType(clientRequest); @@ -160,13 +239,22 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB * Deserialize body object into body buffer, according to the Content-Type. */ private Buffer createBodyBuffer(String contentType, Object arg) throws IOException { - if (MediaType.TEXT_PLAIN.equals(contentType)) { - if (!(arg instanceof String)) { - throw new IllegalArgumentException("Content-Type is text/plain while arg type is not String"); - } - return new BufferImpl().appendBytes(((String) arg).getBytes(StandardCharsets.UTF_8)); + if (SwaggerConst.PROTOBUF_TYPE.equals(contentType)) { + String messageName = (String) requestBody.getContent().get(SwaggerConst.PROTOBUF_TYPE).getExtensions() + .get(SwaggerConst.EXT_BODY_NAME); + ProtoMapper protoMapper = scopedProtobufSchemaManager + .getOrCreateProtoMapper(openAPI, operationMeta.getSchemaId(), + messageName, + requestBody.getContent().get(SwaggerConst.PROTOBUF_TYPE).getSchema()); + RootSerializer serializer = protoMapper.getSerializerSchemaManager() + .createRootSerializer(protoMapper.getProto().getMessage(messageName), + targetType); + Map<String, Object> bodyArg = new HashMap<>(1); + bodyArg.put("value", arg); + return new BufferImpl().appendBytes(serializer.serialize(bodyArg)); } + // For application/json and text/plain try (BufferOutputStream output = new BufferOutputStream()) { RestObjectMapperFactory.getConsumerWriterMapper().writeValue(output, arg); return output.getBuffer(); @@ -194,13 +282,28 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB } } - public static class RawJsonBodyProcessor extends BodyProcessor { - public RawJsonBodyProcessor(JavaType targetType, boolean isString, boolean isRequired) { - this(targetType, null, isString, isRequired); + public static class RawJsonBodyProcessor implements ParamValueProcessor { + protected JavaType targetType; + + protected Class<?> serialViewClass; + + protected boolean isRequired; + + public RawJsonBodyProcessor(JavaType targetType, boolean isRequired) { + this(targetType, null, isRequired); } - public RawJsonBodyProcessor(JavaType targetType, String serialViewClass, boolean isString, boolean isRequired) { - super(targetType, serialViewClass, isString, isRequired); + public RawJsonBodyProcessor(JavaType targetType, String serialViewClass, boolean isRequired) { + if (!StringUtils.isEmpty(serialViewClass)) { + try { + this.serialViewClass = Class.forName(serialViewClass); + } catch (Throwable e) { + //ignore + LOGGER.warn("Failed to create body processor {}, annotation @JsonView may be invalid", serialViewClass, e); + } + } + this.targetType = targetType; + this.isRequired = isRequired; } @Override @@ -215,7 +318,6 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB return null; } - // TODO: we should consider body encoding return IOUtils.toString(inputStream, StandardCharsets.UTF_8); } @@ -227,7 +329,17 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB return; } - super.setValue(clientRequest, arg); + throw new IllegalArgumentException("@RawJsonRequestBody only supports string type."); + } + + @Override + public String getParameterPath() { + return ""; + } + + @Override + public String getProcessorType() { + return PARAM_TYPE; } } @@ -236,23 +348,17 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator<RequestB } @Override - public ParamValueProcessor create(String parameterName, RequestBody parameter, Type genericParamType) { - String mediaType = parameter.getContent().keySet().iterator().next(); - Schema model = parameter.getContent().get(mediaType).getSchema(); - JavaType swaggerType = ConverterMgr.findJavaType(model.getType(), model.getFormat()); - boolean isString = swaggerType != null && swaggerType.getRawClass().equals(String.class); - + public ParamValueProcessor create(OperationMeta operationMeta, String parameterName, + RequestBody parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); boolean rawJson = SwaggerUtils.isRawJsonType(parameter); if (rawJson) { return new RawJsonBodyProcessor(targetType, (String) parameter.getExtensions() - .get(SwaggerConst.EXT_JSON_VIEW), isString, + .get(SwaggerConst.EXT_JSON_VIEW), parameter.getRequired() != null && parameter.getRequired()); } - return new BodyProcessor(targetType, (String) parameter.getExtensions() - .get(SwaggerConst.EXT_JSON_VIEW), isString, - parameter.getRequired() != null && parameter.getRequired()); + return new BodyProcessor(operationMeta, targetType, parameter); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java index 4ff9d31a3..9426cc2e2 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java @@ -22,6 +22,7 @@ import java.util.Objects; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import com.fasterxml.jackson.databind.JavaType; @@ -85,7 +86,8 @@ public class CookieProcessorCreator implements ParamValueProcessorCreator<Parame } @Override - public ParamValueProcessor create(String parameterName, Parameter parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String parameterName, Parameter parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); return new CookieProcessor(parameterName, targetType, parameter.getSchema().getDefault(), diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java index 7721c3f9a..0f7bf6a63 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java @@ -25,6 +25,7 @@ import java.util.stream.Collectors; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.swagger.generator.SwaggerConst; import org.apache.servicecomb.swagger.invocation.converter.Converter; @@ -100,7 +101,8 @@ public class FormProcessorCreator implements ParamValueProcessorCreator<RequestB } @Override - public ParamValueProcessor create(String paramName, RequestBody parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String paramName, RequestBody parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java index fc70bb009..ab03afd49 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java @@ -23,6 +23,7 @@ import java.util.Enumeration; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -103,7 +104,8 @@ public class HeaderProcessorCreator implements ParamValueProcessorCreator<Parame } @Override - public ParamValueProcessor create(String parameterName, Parameter parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String parameterName, Parameter parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); return new HeaderProcessor((HeaderParameter) parameter, targetType); diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessorCreator.java index 85b408a10..1c3378dc6 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessorCreator.java @@ -19,8 +19,11 @@ package org.apache.servicecomb.common.rest.codec.param; import java.lang.reflect.Type; +import org.apache.servicecomb.core.definition.OperationMeta; + public interface ParamValueProcessorCreator<T> { - default ParamValueProcessor create(String paramName, T parameter, Type genericParamType) { + default ParamValueProcessor create(OperationMeta operationMeta, String paramName, T parameter, + Type genericParamType) { throw new IllegalStateException("not implemented"); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/PathProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/PathProcessorCreator.java index 53d60c599..861b7490f 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/PathProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/PathProcessorCreator.java @@ -23,6 +23,7 @@ import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.core.definition.OperationMeta; import org.springframework.util.StringUtils; import com.fasterxml.jackson.databind.JavaType; @@ -70,7 +71,8 @@ public class PathProcessorCreator implements ParamValueProcessorCreator<Paramete } @Override - public ParamValueProcessor create(String parameterName, Parameter parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String parameterName, Parameter parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); return new PathProcessor(parameterName, targetType, parameter.getSchema().getDefault(), true); diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/QueryProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/QueryProcessorCreator.java index 0874fa31a..1462e413a 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/QueryProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/QueryProcessorCreator.java @@ -24,6 +24,7 @@ import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.query.QueryCodec; import org.apache.servicecomb.common.rest.codec.query.QueryCodecsUtils; +import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import com.fasterxml.jackson.databind.JavaType; @@ -129,7 +130,8 @@ public class QueryProcessorCreator implements ParamValueProcessorCreator<Paramet } @Override - public ParamValueProcessor create(String parameterName, Parameter parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String parameterName, Parameter parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); return new QueryProcessor((QueryParameter) parameter, targetType); diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java index 22b48c4ce..764160100 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java @@ -108,7 +108,7 @@ public class RestOperationMeta { Parameter parameter = operation.getParameters().get(swaggerParameterIdx); Type type = operationMeta.getSwaggerProducerOperation() != null ? operationMeta.getSwaggerProducerOperation() .getSwaggerParameterTypes().get(parameter.getName()) : null; - RestParam param = new RestParam(parameter, type); + RestParam param = new RestParam(operationMeta, parameter, type); addParam(param); } } @@ -135,7 +135,7 @@ public class RestOperationMeta { Type type = operationMeta.getSwaggerProducerOperation() != null ? operationMeta.getSwaggerProducerOperation() .getSwaggerParameterTypes().get(name) : null; type = correctFormBodyType(operation.getRequestBody(), type); - RestParam param = new RestParam(name, operation.getRequestBody(), formData, type); + RestParam param = new RestParam(operationMeta, name, operation.getRequestBody(), formData, type); addParam(param); } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestParam.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestParam.java index ef0c9fffb..a2b44674c 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestParam.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestParam.java @@ -26,6 +26,7 @@ import org.apache.servicecomb.common.rest.codec.param.FormProcessorCreator; import org.apache.servicecomb.common.rest.codec.param.ParamValueProcessor; import org.apache.servicecomb.common.rest.codec.param.ParamValueProcessorCreator; import org.apache.servicecomb.common.rest.codec.param.ParamValueProcessorCreatorManager; +import org.apache.servicecomb.core.definition.OperationMeta; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; @@ -41,16 +42,17 @@ public class RestParam { protected String paramName; - public RestParam(Parameter parameter, Type genericParamType) { + public RestParam(OperationMeta operationMeta, Parameter parameter, Type genericParamType) { this.paramName = parameter.getName(); - init(parameter, genericParamType); + init(operationMeta, parameter, genericParamType); } - public RestParam(String paramName, RequestBody parameter, boolean isForm, Type genericParamType) { + public RestParam(OperationMeta operationMeta, + String paramName, RequestBody parameter, boolean isForm, Type genericParamType) { this.paramName = paramName; - init(parameter, isForm, genericParamType); + init(operationMeta, parameter, isForm, genericParamType); } @@ -66,15 +68,15 @@ public class RestParam { return paramName; } - protected void init(Parameter parameter, Type genericParamType) { + protected void init(OperationMeta operationMeta, Parameter parameter, Type genericParamType) { String paramType = parameter.getIn(); ParamValueProcessorCreator creator = ParamValueProcessorCreatorManager.INSTANCE.ensureFindValue(paramType); - this.setParamProcessor(creator.create(parameter.getName(), parameter, genericParamType)); + this.setParamProcessor(creator.create(operationMeta, parameter.getName(), parameter, genericParamType)); } - protected void init(RequestBody parameter, boolean isForm, Type genericParamType) { + protected void init(OperationMeta operationMeta, RequestBody parameter, boolean isForm, Type genericParamType) { ParamValueProcessorCreator creator; if (isForm) { creator = @@ -84,7 +86,7 @@ public class RestParam { ParamValueProcessorCreatorManager.INSTANCE.ensureFindValue(BodyProcessorCreator.PARAM_TYPE); } - this.setParamProcessor(creator.create(this.paramName, + this.setParamProcessor(creator.create(operationMeta, this.paramName, parameter, genericParamType)); } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestCodec.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestCodec.java index dc30986b1..ebbe2975a 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestCodec.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestCodec.java @@ -60,7 +60,7 @@ public class TestRestCodec { Parameter hp = new HeaderParameter(); hp.setName("header"); hp.setSchema(new Schema()); - RestParam restParam = new RestParam(hp, int.class); + RestParam restParam = new RestParam(null, hp, int.class); restOperation = Mockito.mock(RestOperationMeta.class); paramList = new ArrayList<>(); diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java index b7c810050..5ad90a83a 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java @@ -19,18 +19,17 @@ package org.apache.servicecomb.common.rest.codec.param; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; +import java.util.Set; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.param.BodyProcessorCreator.BodyProcessor; import org.apache.servicecomb.common.rest.codec.param.BodyProcessorCreator.RawJsonBodyProcessor; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.junit.jupiter.api.Assertions; @@ -42,10 +41,16 @@ import com.fasterxml.jackson.databind.type.TypeFactory; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.parameters.RequestBody; import io.vertx.core.MultiMap; import io.vertx.core.buffer.Buffer; import io.vertx.core.buffer.impl.BufferImpl; import io.vertx.core.http.impl.headers.HeadersMultiMap; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; public class TestBodyProcessor { @@ -67,11 +72,24 @@ public class TestBodyProcessor { String value; private void createProcessor(Class<?> type) { - processor = new BodyProcessor(TypeFactory.defaultInstance().constructType(type), type.equals(String.class), true); + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); + OpenAPI openAPI = Mockito.mock(OpenAPI.class); + Mockito.when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + Mockito.when(schemaMeta.getSwagger()).thenReturn(openAPI); + RequestBody requestBody = Mockito.mock(RequestBody.class); + Content content = Mockito.mock(Content.class); + Mockito.when(requestBody.getContent()).thenReturn(content); + Mockito.when(requestBody.getRequired()).thenReturn(true); + Set<String> supported = new HashSet<>(); + supported.add(MediaType.APPLICATION_JSON); + supported.add(MediaType.TEXT_PLAIN); + Mockito.when(content.keySet()).thenReturn(supported); + processor = new BodyProcessor(operationMeta, TypeFactory.defaultInstance().constructType(type), requestBody); } private void createRawJsonProcessor() { - processor = new RawJsonBodyProcessor(TypeFactory.defaultInstance().constructType(String.class), true, true); + processor = new RawJsonBodyProcessor(TypeFactory.defaultInstance().constructType(String.class), true); } private void createClientRequest() { @@ -118,7 +136,7 @@ public class TestBodyProcessor { @Test public void testGetValueTextPlain() throws Exception { setupGetValue(String.class); - inputBodyByteBuf.writeCharSequence("abc", StandardCharsets.UTF_8); + inputBodyByteBuf.writeCharSequence("\"abc\"", StandardCharsets.UTF_8); Mockito.when(request.getContentType()).thenReturn(MediaType.TEXT_PLAIN); @@ -179,20 +197,6 @@ public class TestBodyProcessor { Assertions.assertEquals(value, outputBodyBuffer.toString()); } - @Test - public void testSetValueTextPlainTypeMismatch() { - createClientRequest(); - createProcessor(String.class); - headers.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN); - - try { - processor.setValue(clientRequest, new Date()); - Assertions.fail("an exception is expected!"); - } catch (Exception e) { - Assertions.assertEquals(IllegalArgumentException.class, e.getClass()); - Assertions.assertEquals("Content-Type is text/plain while arg type is not String", e.getMessage()); - } - } @Test public void testGetParameterPath() { diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessorCreator.java index 15a50f0ef..0de4a04c4 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessorCreator.java @@ -42,7 +42,7 @@ public class TestBodyProcessorCreator { param.getContent().get(SwaggerConst.DEFAULT_MEDIA_TYPE).setSchema(new Schema()); param.setExtensions(new HashMap<>()); - ParamValueProcessor processor = creator.create(null, param, String.class); + ParamValueProcessor processor = creator.create(null, null, param, String.class); Assertions.assertEquals(BodyProcessor.class, processor.getClass()); } @@ -57,7 +57,7 @@ public class TestBodyProcessorCreator { param.getContent().get(SwaggerConst.DEFAULT_MEDIA_TYPE).setSchema(new Schema()); param.addExtension(SwaggerConst.EXT_RAW_JSON_TYPE, true); - ParamValueProcessor processor = creator.create(null, param, String.class); + ParamValueProcessor processor = creator.create(null, null, param, String.class); Assertions.assertEquals(RawJsonBodyProcessor.class, processor.getClass()); } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessorCreator.java index df7dd2326..7cae38cd0 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessorCreator.java @@ -32,7 +32,7 @@ public class TestCookieProcessorCreator { CookieParameter p = new CookieParameter(); p.setName("p1"); p.setSchema(new Schema()); - ParamValueProcessor processor = creator.create(p.getName(), p, String.class); + ParamValueProcessor processor = creator.create(null, p.getName(), p, String.class); Assertions.assertEquals(CookieProcessor.class, processor.getClass()); } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessorCreator.java index 4d82126e4..f2b7b9c39 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessorCreator.java @@ -41,7 +41,7 @@ public class TestFormProcessorCreator { p.getContent().get(SwaggerConst.FORM_MEDIA_TYPE).setSchema(new Schema()); p.getContent().get(SwaggerConst.FORM_MEDIA_TYPE).getSchema().setProperties(new HashMap<>()); - ParamValueProcessor processor = creator.create("p1", p, String.class); + ParamValueProcessor processor = creator.create(null, "p1", p, String.class); Assertions.assertEquals(FormProcessor.class, processor.getClass()); } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessorCreator.java index 6ad2418c7..2ea7c3823 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessorCreator.java @@ -33,7 +33,7 @@ public class TestHeaderProcessorCreator { hp.setName("h1"); hp.setSchema(new Schema()); - ParamValueProcessor processor = creator.create(hp.getName(), hp, String.class); + ParamValueProcessor processor = creator.create(null, hp.getName(), hp, String.class); Assertions.assertEquals(HeaderProcessor.class, processor.getClass()); } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessorCreator.java index 2a58dc3e3..0f40291c8 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessorCreator.java @@ -34,7 +34,7 @@ public class TestPathProcessorCreator { parameter.setName("path"); parameter.setSchema(new Schema()); - ParamValueProcessor processor = creator.create(parameter.getName(), parameter, String.class); + ParamValueProcessor processor = creator.create(null, parameter.getName(), parameter, String.class); Assertions.assertEquals(PathProcessor.class, processor.getClass()); } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessorCreator.java index e262d3055..6f59823b0 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessorCreator.java @@ -38,7 +38,7 @@ public class TestQueryProcessorCreator { Parameter parameter = new QueryParameter(); parameter.setName("query"); parameter.setSchema(new Schema()); - ParamValueProcessor processor = creator.create(parameter.getName(), parameter, String.class); + ParamValueProcessor processor = creator.create(null, parameter.getName(), parameter, String.class); Assertions.assertEquals(QueryProcessor.class, processor.getClass()); @@ -63,7 +63,7 @@ public class TestQueryProcessorCreator { parameter.setName("query"); parameter.setSchema(new Schema()); - ParamValueProcessor processor = creator.create(parameter.getName(), parameter, String.class); + ParamValueProcessor processor = creator.create(null, parameter.getName(), parameter, String.class); Assertions.assertEquals(QueryProcessor.class, processor.getClass()); diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestPath.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestPath.java index 46fdccb5f..51a4cf26e 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestPath.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestPath.java @@ -101,13 +101,13 @@ public class TestPath { Parameter pathParameter = new PathParameter(); pathParameter.setName("id"); pathParameter.setSchema(new Schema<>()); - RestParam oRestParam = new RestParam(pathParameter, int.class); + RestParam oRestParam = new RestParam(null, pathParameter, int.class); paramMap.put(oRestParam.getParamName(), oRestParam); Parameter queryParameter = new QueryParameter(); queryParameter.setName("q"); queryParameter.setSchema(new Schema<>()); - oRestParam = new RestParam(queryParameter, String.class); + oRestParam = new RestParam(null, queryParameter, String.class); paramMap.put(oRestParam.getParamName(), oRestParam); URLPathBuilder oURLPathBuilder = new URLPathBuilder("/root/{id}", paramMap); @@ -124,7 +124,7 @@ public class TestPath { Parameter parameter = new QueryParameter(); parameter.setSchema(new Schema<>()); - RestParam restParam = new RestParam(parameter, String.class); + RestParam restParam = new RestParam(null, parameter, String.class); RestParam spy = Mockito.spy(restParam); Mockito.when(spy.getParamName()).thenReturn("queryVar"); QueryVarParamWriter writer = new QueryVarParamWriter(spy); diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriterTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriterTest.java index 737319aca..55c69bf60 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriterTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriterTest.java @@ -49,7 +49,7 @@ public class QueryVarParamWriterTest { parameter.setStyle(StyleEnum.FORM); parameter.setExplode(false); queryVarParamWriterCsv = new QueryVarParamWriter( - new RestParam(parameter, String[].class)); + new RestParam(null, parameter, String[].class)); parameter = new QueryParameter(); parameter.setName("q"); @@ -57,13 +57,13 @@ public class QueryVarParamWriterTest { parameter.setStyle(StyleEnum.FORM); parameter.setExplode(true); queryVarParamWriterMulti = new QueryVarParamWriter( - new RestParam(parameter, String[].class)); + new RestParam(null, parameter, String[].class)); parameter = new QueryParameter(); parameter.setName("q"); parameter.setSchema(new Schema()); queryVarParamWriterDefault = new QueryVarParamWriter( - new RestParam(parameter, String[].class)); + new RestParam(null, parameter, String[].class)); } @Test diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilderTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilderTest.java index 5bd774515..43f2b1396 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilderTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilderTest.java @@ -119,7 +119,7 @@ public class URLPathBuilderTest { Parameter parameter = constructor.construct(); parameter.setName(paramName); parameter.setSchema(new Schema()); - paramMap.put(paramName, new RestParam(parameter, paramType)); + paramMap.put(paramName, new RestParam(null, parameter, paramType)); } interface ParameterConstructor { diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parameter/RawJsonRequestBodyProcessor.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parameter/RawJsonRequestBodyProcessor.java index 8eb8c6bdc..1d6414436 100644 --- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parameter/RawJsonRequestBodyProcessor.java +++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parameter/RawJsonRequestBodyProcessor.java @@ -17,6 +17,8 @@ package org.apache.servicecomb.swagger.generator.core.processor.parameter; +import java.util.Arrays; + import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.swagger.extend.annotations.RawJsonRequestBody; import org.apache.servicecomb.swagger.generator.OperationGenerator; @@ -25,6 +27,8 @@ import org.apache.servicecomb.swagger.generator.SwaggerGenerator; import org.apache.servicecomb.swagger.generator.SwaggerParameterAnnotationProcessor; import org.apache.servicecomb.swagger.generator.core.model.HttpParameterType; +import jakarta.ws.rs.core.MediaType; + public class RawJsonRequestBodyProcessor extends SwaggerParameterAnnotationProcessor<RawJsonRequestBody> { @Override @@ -53,5 +57,7 @@ public class RawJsonRequestBodyProcessor extends parameterGenerator.getParameterGeneratorContext().setRequired(annotation.required()); parameterGenerator.getParameterGeneratorContext().setRawJson(true); + parameterGenerator.getParameterGeneratorContext().updateConsumes(Arrays.asList(MediaType.APPLICATION_JSON, + MediaType.TEXT_PLAIN)); } } diff --git a/swagger/swagger-generator/generator-jaxrs/src/test/resources/schemas/echo.yaml b/swagger/swagger-generator/generator-jaxrs/src/test/resources/schemas/echo.yaml index 04ba2b2be..d5227f916 100644 --- a/swagger/swagger-generator/generator-jaxrs/src/test/resources/schemas/echo.yaml +++ b/swagger/swagger-generator/generator-jaxrs/src/test/resources/schemas/echo.yaml @@ -480,9 +480,6 @@ paths: application/json: schema: type: string - application/protobuf: - schema: - type: string text/plain: schema: type: string diff --git a/swagger/swagger-generator/generator-springmvc/src/test/resources/schemas/echo.yaml b/swagger/swagger-generator/generator-springmvc/src/test/resources/schemas/echo.yaml index 7e70e366c..77cc098d7 100644 --- a/swagger/swagger-generator/generator-springmvc/src/test/resources/schemas/echo.yaml +++ b/swagger/swagger-generator/generator-springmvc/src/test/resources/schemas/echo.yaml @@ -266,9 +266,6 @@ paths: application/json: schema: type: string - application/protobuf: - schema: - type: string text/plain: schema: type: string
