From 4d8d408ed25e1e26d0cd5bf4171f540a4df22f30 Mon Sep 17 00:00:00 2001 From: Joshua Bauer Date: Fri, 29 Oct 2021 09:07:16 -0700 Subject: [PATCH] Cleanup OpenAPI module and add json spec support. --- CHANGELOG.md | 5 + .../src/main/resources/reference.conf | 2 +- proteus-openapi/pom.xml | 6 - .../openapi/services/OpenAPIService.java | 97 +++-- .../test/controllers/OpenAPITests.java | 359 ------------------ .../test/converters/MoneyModelConverter.java | 145 ------- .../openapi/test/modules/JacksonModule.java | 3 +- .../TestOpenAPIControllerEndpoints.java | 239 +----------- .../src/test/resources/application.conf | 39 ++ 9 files changed, 127 insertions(+), 768 deletions(-) delete mode 100644 proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/converters/MoneyModelConverter.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 42edb5e..118cb6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ Proteus Changelog. ## Unreleased ### No issue +**Improved error logging and shutdown process.** + + +[09f630e8f400db9](https://github.com/noboomu/proteus/commit/09f630e8f400db9) Joshua Bauer *2021-10-25 19:29:23* + **Improve Optional bean parsing.** diff --git a/proteus-core/src/main/resources/reference.conf b/proteus-core/src/main/resources/reference.conf index 1bd3ba9..cd456d9 100644 --- a/proteus-core/src/main/resources/reference.conf +++ b/proteus-core/src/main/resources/reference.conf @@ -78,7 +78,7 @@ openapi { port = ${application.ports.http} - specFilename="openapi.yaml" + specFilename="openapi" openapi="3.0.1" diff --git a/proteus-openapi/pom.xml b/proteus-openapi/pom.xml index f8d8d3a..dca38cd 100644 --- a/proteus-openapi/pom.xml +++ b/proteus-openapi/pom.xml @@ -108,12 +108,6 @@ ${openapi.version} - - org.zalando - jackson-datatype-money - 1.1.1 - test - io.sinistral diff --git a/proteus-openapi/src/main/java/io/sinistral/proteus/openapi/services/OpenAPIService.java b/proteus-openapi/src/main/java/io/sinistral/proteus/openapi/services/OpenAPIService.java index 8830861..dedec6c 100644 --- a/proteus-openapi/src/main/java/io/sinistral/proteus/openapi/services/OpenAPIService.java +++ b/proteus-openapi/src/main/java/io/sinistral/proteus/openapi/services/OpenAPIService.java @@ -51,7 +51,12 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; import java.util.jar.JarFile; @@ -68,16 +73,20 @@ public class OpenAPIService extends DefaultService implements Supplier securitySchemes = mapper.convertValue(openAPIConfig.getValue("securitySchemes").unwrapped(), new TypeReference>() {}); + Map securitySchemes = jsonMapper.convertValue(openAPIConfig.getValue("securitySchemes").unwrapped(), new TypeReference>() {}); if (openApi.getComponents() == null) { @@ -265,7 +271,7 @@ protected void generateSpec() throws Exception openApi.getComponents().setSecuritySchemes(securitySchemes); - List servers = mapper.convertValue(openAPIConfig.getValue("servers").unwrapped(), new TypeReference>() {}); + List servers = jsonMapper.convertValue(openAPIConfig.getValue("servers").unwrapped(), new TypeReference>() {}); openApi.setServers(servers); @@ -298,8 +304,12 @@ protected void generateSpec() throws Exception .init(); openApi = ctx.read(); + this.openApi = openApi; - this.spec = writer.writeValueAsString(openApi); + + this.yamlSpec = Yaml.pretty().writeValueAsString(openApi); + + this.jsonSpec = Json.pretty().writeValueAsString(openApi); } @@ -317,14 +327,14 @@ protected void startUp() throws Exception { generateSpec(); - log.debug("\nOpenAPI Spec:\n" + writer.writeValueAsString(this.openApi)); + log.debug("\nOpenAPI Spec:\n{}", Yaml.pretty().writeValueAsString(this.openApi)); } catch (Exception e) { log.error("Error generating OpenAPI spec", e); } - }, this.executor()); + }); router.addAll(this.get()); } @@ -332,45 +342,64 @@ protected void startUp() throws Exception public RoutingHandler get() { + FileResourceManager resourceManager = new FileResourceManager(this.resourcePath.toFile(), 1024); + RoutingHandler router = new RoutingHandler(); + router.add(HttpMethod.GET, basePath, (HttpServerExchange exchange) -> + { + exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, MediaType.TEXT_HTML); + exchange.getResponseSender().send(indexHTML); + }); + /* * YAML path */ - String pathTemplate = this.applicationPath + "/" + this.specFilename; - FileResourceManager resourceManager = new FileResourceManager(this.resourcePath.toFile(), 1024); + String yamlTemplatePath = String.format("%s/%s.yaml", this.applicationPath, this.specFilename); - router.add(HttpMethod.GET, pathTemplate, (HttpServerExchange exchange) -> + router.add(HttpMethod.GET, yamlTemplatePath, (HttpServerExchange exchange) -> { exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, io.sinistral.proteus.protocol.MediaType.TEXT_YAML.contentType()); - exchange.getResponseSender().send(spec); + exchange.getResponseSender().send(yamlSpec); }); this.registeredEndpoints.add(EndpointInfo.builder() .withConsumes("*/*") - .withPathTemplate(pathTemplate) + .withPathTemplate(yamlTemplatePath) .withControllerName(this.getClass().getSimpleName()) .withMethod(Methods.GET) .withProduces(io.sinistral.proteus.protocol.MediaType.TEXT_YAML.contentType()) .build()); - router.add(HttpMethod.GET, basePath, (HttpServerExchange exchange) -> + this.registeredEndpoints.add(EndpointInfo.builder() + .withConsumes(MediaType.WILDCARD) + .withProduces(MediaType.TEXT_HTML) + .withPathTemplate(yamlTemplatePath) + .withControllerName(this.getClass().getSimpleName()) + .withMethod(Methods.GET) + .build()); + + String jsonTemplatePath = String.format("%s/%s.json", this.applicationPath, this.specFilename); + + router.add(HttpMethod.GET, jsonTemplatePath, (HttpServerExchange exchange) -> { - exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, MediaType.TEXT_HTML); - exchange.getResponseSender().send(indexHTML); + exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, io.sinistral.proteus.protocol.MediaType.JSON.contentType()); + + exchange.getResponseSender().send(jsonSpec); }); this.registeredEndpoints.add(EndpointInfo.builder() - .withConsumes(MediaType.WILDCARD) - .withProduces(MediaType.TEXT_HTML) - .withPathTemplate(pathTemplate) + .withConsumes("*/*") + .withPathTemplate(jsonTemplatePath) .withControllerName(this.getClass().getSimpleName()) .withMethod(Methods.GET) + .withProduces(io.sinistral.proteus.protocol.MediaType.JSON.contentType()) .build()); - final String specPath = pathTemplate; + + final String specPath = yamlTemplatePath; router.add(HttpMethod.GET, this.basePath + "/" + this.redocPath, (HttpServerExchange exchange) -> { @@ -394,10 +423,10 @@ public RoutingHandler get() try { - pathTemplate = this.basePath + "/*"; + String wildcardPathTemplate = this.basePath + "/*"; router.add(HttpMethod.GET, - pathTemplate, + wildcardPathTemplate, new ResourceHandler(resourceManager) { @Override public void handleRequest(HttpServerExchange exchange) throws Exception @@ -441,7 +470,7 @@ public void handleRequest(HttpServerExchange exchange) throws Exception this.registeredEndpoints.add(EndpointInfo.builder() .withConsumes(MediaType.WILDCARD) .withProduces(MediaType.WILDCARD) - .withPathTemplate(pathTemplate) + .withPathTemplate(wildcardPathTemplate) .withControllerName(this.getClass().getSimpleName()) .withMethod(Methods.GET) .build()); diff --git a/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/controllers/OpenAPITests.java b/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/controllers/OpenAPITests.java index 85c1e04..70eb154 100644 --- a/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/controllers/OpenAPITests.java +++ b/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/controllers/OpenAPITests.java @@ -8,9 +8,6 @@ import com.google.common.io.Files; import com.google.inject.Inject; import com.google.inject.Singleton; -import io.restassured.RestAssured; -import io.restassured.filter.log.RequestLoggingFilter; -import io.restassured.filter.log.ResponseLoggingFilter; import io.sinistral.proteus.annotations.Blocking; import io.sinistral.proteus.annotations.Chain; import io.sinistral.proteus.annotations.Debug; @@ -23,8 +20,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tags; import io.undertow.server.HttpServerExchange; -import org.javamoney.moneta.Money; -import org.junit.BeforeClass; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,360 +57,6 @@ @Singleton public class OpenAPITests { - private static final Logger logger = LoggerFactory.getLogger(OpenAPITests.class.getName()); - private static final ByteBuffer buffer; - static { - String message = "Hello, World!"; - byte[] messageBytes = message.getBytes(java.nio.charset.StandardCharsets.US_ASCII); - buffer = ByteBuffer.allocateDirect(messageBytes.length); - buffer.put(messageBytes); - buffer.flip(); - } - - - - @Inject - protected ObjectMapper objectMapper; - - - - @GET - @Path("exchange/plaintext") - @Produces((MediaType.TEXT_PLAIN)) - @Operation(description = "Plaintext endpoint" ) - public void exchangePlaintext(HttpServerExchange exchange) - { - response("Hello, World!").textPlain().send(exchange); - - } - - - @GET - @Path("response/plaintext") - @Produces((MediaType.TEXT_PLAIN)) - @Operation(description = "Plaintext endpoint" ) - public ServerResponse responsePlaintext(ServerRequest request) - { - return response("Hello, World!").textPlain(); - - } - - @GET - @Path("response/future/map") - @Operation(description = "Future map endpoint" ) - public CompletableFuture>> responseFutureMap( ServerRequest request ) - { - Map map = ImmutableMap.of("message", "success"); - return CompletableFuture.completedFuture(response( map ).applicationJson()); - } - - @GET - @Path("response/map") - @Operation(description = "Map endpoint" ) - public ServerResponse> futureMap( ServerRequest request ) - { - Map map = ImmutableMap.of("message", "success"); - return response( map ).applicationJson(); - } - - @POST - @Path("response/file/path") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Operation(description = "Upload file path endpoint" ) - public ServerResponse responseUploadFilePath(ServerRequest request, @FormParam("file") java.nio.file.Path file ) throws Exception - { - return response(ByteBuffer.wrap(Files.toByteArray(file.toFile()))).applicationOctetStream(); - } - - @POST - @Path("response/file/path/optional") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Operation(description = "Upload optional file path endpoint" ) - public ServerResponse responseUploadOptionalFilePath(ServerRequest request, @FormParam("file") Optional file ) throws Exception - { - if(file.isPresent()) - { - return response(ByteBuffer.wrap(Files.toByteArray(file.get().toFile()))).applicationOctetStream(); - } - else - { - return response().noContent(); - } - } - - @GET - @Path("generic/set") - @Produces((MediaType.APPLICATION_JSON)) - @Operation(description = "Generic set endpoint" ) - public ServerResponse> genericSet( ServerRequest request, @QueryParam("ids") Set ids ) throws Exception - { - return response( ids ).applicationJson(); - } - - - @GET - @Path("types/money") - @Produces((MediaType.APPLICATION_JSON)) - @Operation(description = "Money type endpoint" ) - public ServerResponse getMoney(ServerRequest request ) throws Exception - { - return response( Money.of(123.23,"USD") ).applicationJson(); - } - - - @GET - @Path("types/pojo") - @Produces((MediaType.APPLICATION_JSON)) - @Operation(description = "Pojo type endpoint" ) - public ServerResponse getPojo(ServerRequest request ) throws Exception - { - return response( new Pojo(100L,"John Doe") ).applicationJson(); - } - - @POST - @Path("generic/set/bean") - @Produces((MediaType.APPLICATION_JSON)) - @Consumes(MediaType.APPLICATION_JSON) - @Operation(description = "Generic bean set endpoint" ) - public ServerResponse> genericBeanSet( ServerRequest request, @BeanParam Set ids ) throws Exception - { - return response( ids ).applicationJson(); - } - - - @POST - @Path("generic/list/bean") - @Produces((MediaType.APPLICATION_JSON)) - @Consumes(MediaType.APPLICATION_JSON) - - @Operation(description = "Generic bean list endpoint" ) - public ServerResponse> genericBeanList( ServerRequest request, @BeanParam List ids ) throws Exception - { - return response( ids ).applicationJson(); - } - - @GET - @Path("optional/set") - @Produces((MediaType.APPLICATION_JSON)) - @Operation(description = "Generic optional set endpoint" ) - public ServerResponse> genericOptionalSet( ServerRequest request, @QueryParam("ids") Optional> ids ) throws Exception - { - return response( ids.get() ).applicationJson(); - } - - - @POST - @Path("response/parse/ids") - @Blocking - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @Operation(description = "Convert ids") - public ServerResponse> listConversion( ServerRequest request, @BeanParam List ids ) throws Exception - { - - return response( ids ).applicationJson(); - - - } - - @GET - @Path("response/parse/timestamp") - @Blocking - @Produces(MediaType.TEXT_PLAIN) - @Operation(description = "Convert timestamp") - public ServerResponse timestampConversion( ServerRequest request, @QueryParam("timestamp") Timestamp timestamp ) throws Exception - { - return response().body(timestamp.toString()).textPlain(); - } - - @GET - @Path("response/parse/instant") - @Blocking - @Produces(MediaType.TEXT_PLAIN) - @Operation(description = "Convert instant") - public ServerResponse instantConversion( ServerRequest request, @QueryParam("instant") Instant instant ) throws Exception - { - - return response().body(instant.toString()).textPlain(); - - - } - - @POST - @Path("response/bytebuffer") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @Consumes("*/*") - @Operation(description = "Upload file path endpoint") - public ServerResponse responseUploadByteBuffer(ServerRequest request, @FormParam("file") ByteBuffer file ) throws Exception - { - - return response(file).applicationOctetStream(); - - - } - - @POST - @Path("response/file") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @Consumes("*/*") - @Operation(description = "Upload file path endpoint") - public ServerResponse responseUploadFile(ServerRequest request, @FormParam("file") File file ) throws Exception - { - - ByteBuffer response = ByteBuffer.wrap(Files.asByteSource(file).read()); - - - return response(response).applicationOctetStream(); - - - } - - @GET - @Path("response/debug") - @Operation(description = "Debug endpoint") - public ServerResponse> debugEndpoint(ServerRequest request) - { - try - { - Map map = ImmutableMap.of("message", "Hello, World!"); - - return response( map ).applicationJson(); - } catch(Exception e) - { - return response().badRequest(e).applicationJson(); - } - } - - @GET - @Path("response/debug/blocking") - @Blocking - @Operation(description="Debug blocking endpoint") - public ServerResponse> debugBlockingEndpoint(ServerRequest request) - { - try - { - Map map = ImmutableMap.of("message", "Hello, World!"); - - return response( map ).applicationJson(); - } catch(Exception e) - { - return response().badRequest(e).applicationJson(); - } - } - - @POST - @Path("list/file") - @Produces(MediaType.APPLICATION_JSON) - @Consumes("*/*") - @Blocking - @Debug - public ServerResponse> uploadMultipleFileList(ServerRequest request, @FormParam("files") List files, @FormParam("names") List names ) throws Exception - { - -logger.debug("files {} names {}",files,names); - Map map = new HashMap<>(); - - for(int i = 0; i < files.size(); i++) - { - map.put(names.get(i),files.get(i).getTotalSpace()+""); - } - - logger.debug("map {}",map); - - return response(map).applicationJson(); - - - } - - @POST - @Path("list/path") - @Produces(MediaType.APPLICATION_JSON) - @Consumes("*/*") - @Blocking - @Debug - public ServerResponse> uploadMultiplePathList(ServerRequest request, @FormParam("files") List files, @FormParam("names") List names ) throws Exception - { - - Map map = new HashMap<>(); - - for(int i = 0; i < files.size(); i++) - { - map.put(names.get(i),files.get(i).toFile().getTotalSpace()+""); - } - - - return response(map).applicationJson(); - - - } - - @POST - @Path("map/file") - @Produces(MediaType.APPLICATION_JSON) - @Consumes("*/*") - @Blocking - public ServerResponse> uploadMultipleFileMap(ServerRequest request, @FormParam("files") Map files ) throws Exception - { - - Map map = new HashMap<>(); - - for(String k : files.keySet()) - { - map.put(k,files.get(k).getTotalSpace()+""); - } - - - return response(map).applicationJson(); - - - } - - @POST - @Path("map/path") - @Produces(MediaType.APPLICATION_JSON) - @Consumes("*/*") - @Blocking - public ServerResponse> uploadMultiplePathMap(ServerRequest request, @FormParam("files") Map files ) throws Exception - { - - Map map = new HashMap<>(); - - for(String k : files.keySet()) - { - map.put(k,files.get(k).toFile().getTotalSpace()+""); - } - - return response(map).applicationJson(); - - - } - - @GET - @SecurityRequirement(name = "testRequirement") - @Path("secure/resource") - @Operation(description="Secure resource") - @Produces(MediaType.APPLICATION_JSON) - public ServerResponse> responseSecureContext() - { - Map responseMap = new HashMap<>(); - responseMap.put("secure",true); - - return response(responseMap); - } - - - @Chain({JsonViewWrapper.class}) - @GET - @Path("response/jsonview") - @Produces(MediaType.APPLICATION_JSON) - public ServerResponse jsonViewEndpoint() - { - - - return response( "ok" ).applicationJson(); - } } diff --git a/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/converters/MoneyModelConverter.java b/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/converters/MoneyModelConverter.java deleted file mode 100644 index 94aaf2c..0000000 --- a/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/converters/MoneyModelConverter.java +++ /dev/null @@ -1,145 +0,0 @@ -package io.sinistral.proteus.openapi.test.converters; - - -import com.fasterxml.jackson.databind.JavaType; -import com.google.common.collect.ImmutableMap; -import io.swagger.v3.core.converter.AnnotatedType; -import io.swagger.v3.core.converter.ModelConverter; -import io.swagger.v3.core.converter.ModelConverterContext; -import io.swagger.v3.core.util.Json; -import io.swagger.v3.oas.models.media.NumberSchema; -import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.media.StringSchema; -import org.javamoney.moneta.Money; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public class MoneyModelConverter implements ModelConverter -{ - - private final Schema schema = new MoneySchema(); - - @Override - public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { - - JavaType _type = Json.mapper().constructType(type.getType()); - - if(_type != null && (_type.getRawClass().equals(Money.class))) - { - context.defineModel("Money",schema, type, null); - - return schema; - } - - if (type.getType() instanceof Class) { - - Class cls = (Class) type.getType(); - - if(cls.isAssignableFrom(Money.class)) - { - context.defineModel("Money",schema, type, null); - - return schema; - } - } - else if(type.getType().getTypeName().equals("[simple type, class org.javamoney.moneta.Money]")) - { - context.defineModel("Money",schema, type, null); - - return schema; - } - else if (type.isSchemaProperty()) { - - _type = Json.mapper().constructType(type.getType()); - - if (_type != null) { - Class cls = _type.getRawClass(); - if (Money.class.isAssignableFrom(cls)) { - - context.defineModel("Money",schema, type, null); - - return schema; - } - } - } - - if (chain.hasNext()) { - return chain.next().resolve(type, context, chain); - } - - return null; - - } - - - public static class MoneySchema extends Schema - { - private String _type = "object"; - - private String _$ref = null; - - private String _description = "A monetary amount"; - - private Map _properties = ImmutableMap.of("amount",new NumberSchema(),"currency",new StringSchema()); - - private List _required = Arrays.asList("amount","currency"); - - public MoneySchema() - { - super(); - super.setName("Money"); - super.setType("object"); - super.set$ref(_$ref); - super.description(_description); - super.properties(_properties); - super.required(_required); - } - - @Override - protected Money cast(Object value) - { - if (value != null) { - try { - if (value instanceof Money) { - return (Money) value; - } - } catch (Exception e) { - } - } - return null; - } - - @Override - public boolean equals(java.lang.Object o) - { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MoneySchema MoneySchema = (MoneySchema) o; - return Objects.equals(this._type, MoneySchema._type) && - Objects.equals(this._properties, MoneySchema._properties) && - Objects.equals(this._description, MoneySchema._description) && - super.equals(o); - } - - @Override - public int hashCode() - { - return Objects.hash(_type, _properties, super.hashCode()); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - - - } -} diff --git a/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/modules/JacksonModule.java b/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/modules/JacksonModule.java index 4bf0036..14bca1a 100644 --- a/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/modules/JacksonModule.java +++ b/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/modules/JacksonModule.java @@ -6,7 +6,6 @@ import com.fasterxml.jackson.module.afterburner.AfterburnerModule; import com.google.inject.AbstractModule; import com.google.inject.Singleton; -import org.zalando.jackson.datatype.money.MoneyModule; @Singleton public class JacksonModule extends AbstractModule @@ -25,7 +24,7 @@ protected void configure() objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true); - objectMapper.registerModule(new MoneyModule()) + objectMapper .registerModule(new AfterburnerModule()) .registerModule(new Jdk8Module()); diff --git a/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/server/TestOpenAPIControllerEndpoints.java b/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/server/TestOpenAPIControllerEndpoints.java index c23693d..4be4643 100644 --- a/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/server/TestOpenAPIControllerEndpoints.java +++ b/proteus-openapi/src/test/java/io/sinistral/proteus/openapi/test/server/TestOpenAPIControllerEndpoints.java @@ -1,241 +1,38 @@ /** - * + * */ package io.sinistral.proteus.openapi.test.server; -import io.restassured.RestAssured; -import io.restassured.filter.log.RequestLoggingFilter; -import io.restassured.filter.log.ResponseLoggingFilter; -import io.restassured.http.ContentType; -import org.apache.commons.io.IOUtils; -import org.hamcrest.CoreMatchers; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; -import java.io.File; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.stream.LongStream; - import static io.restassured.RestAssured.when; -import static org.hamcrest.CoreMatchers.equalTo; -import static io.restassured.RestAssured.given; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; -import io.restassured.http.ContentType; + /** * @author jbauer */ @RunWith(OpenAPIDefaultServer.class) -public class TestOpenAPIControllerEndpoints -{ - - private File file = null; - - - private List files = new ArrayList<>(); - - private Set idSet = new HashSet<>(); - - - - @Before - public void setUp() - { - try - { - for(int i = 0; i < 4; i++) - { - byte[] bytes = new byte[8388608]; - Random random = new Random(); - random.nextBytes(bytes); - - files.add(Files.createTempFile("test-asset", ".mp4").toFile()); - - LongStream.range(1L,10L).forEach( l -> { - - idSet.add(l); - }); - } - - file = files.get(0); - - } catch (Exception e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - - - @Test - public void testOpenAPIDocs() - { - when().get("v1/openapi.yaml").then().statusCode(200); - } - - @Test - public void testPojoType() - { - when().get("v1/tests/types/pojo").then().statusCode(200).body("id", org.hamcrest.CoreMatchers.equalTo(100),"name", org.hamcrest.CoreMatchers.equalTo("John Doe")); - } - - @Test - public void testMoneyType() - { - when().get("v1/tests/types/money").then().statusCode(200).body("amount", org.hamcrest.CoreMatchers.equalTo(123.23f),"currency", org.hamcrest.CoreMatchers.equalTo("USD")); - } - - - @Test - public void testSecurityRequirementEndpoint() - { - when().get("v1/tests/secure/resource").then().statusCode(200); - } - - @Test - public void testJsonViewEndpoint() - { - when().get("v1/tests/response/jsonview").then().statusCode(200); - } - - @Test - public void uploadMultipleFileList() - { - - try - { - - - Map map = given().multiPart("files", files.get(0)).multiPart("files",files.get(1)).multiPart("files",files.get(2)).multiPart("files",files.get(3)) - .multiPart("names",files.get(0).getName()) - .multiPart("names",files.get(1).getName()) - .multiPart("names",files.get(2).getName()) - .multiPart("names",files.get(3).getName()) - .accept(ContentType.JSON).when().post("v1/tests/list/file").as(Map.class); - - - assertThat(map.size(), org.hamcrest.CoreMatchers.equalTo(4)); - - assertThat(map.get(files.get(0).getName()), org.hamcrest.CoreMatchers.equalTo(files.get(0).getTotalSpace()+"")); - - } catch (Exception e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - fail(e.getMessage()); - } - - } - - @Test - public void uploadMultiplePathList() - { - - try - { - - - Map map = given().multiPart("files", files.get(0)).multiPart("files",files.get(1)).multiPart("files",files.get(2)).multiPart("files",files.get(3)) - .multiPart("names",files.get(0).getName()) - .multiPart("names",files.get(1).getName()) - .multiPart("names",files.get(2).getName()) - .multiPart("names",files.get(3).getName()) - .accept(ContentType.JSON).when().post("v1/tests/list/file").as(Map.class); - - - assertThat(map.size(), org.hamcrest.CoreMatchers.equalTo(4)); - - assertThat(map.get(files.get(0).getName()), org.hamcrest.CoreMatchers.equalTo(files.get(0).getTotalSpace()+"")); - - } catch (Exception e) - { - // TODO Auto-generated catch block - - e.printStackTrace(); - fail(e.getMessage()); - } - - } - - @Test - public void uploadMultipleFileMap() - { - - try - { - - Map map = given().multiPart("files", files.get(0)).multiPart("files",files.get(1)).multiPart("files",files.get(2)).multiPart("files",files.get(3)) - .accept(ContentType.TEXT).when().post("v1/tests/map/file").as(Map.class); - - - assertThat(map.size(), org.hamcrest.CoreMatchers.equalTo(4)); - - assertThat(map.get(files.get(0).getName()), org.hamcrest.CoreMatchers.equalTo(files.get(0).getTotalSpace()+"")); - - } catch (Exception e) - { - // TODO Auto-generated catch block - - e.printStackTrace(); - fail(e.getMessage()); - } - - } - - @Test - public void uploadMultiplePathMap() - { - - try - { - - - Map map = given().multiPart("files", files.get(0)).multiPart("files",files.get(1)).multiPart("files",files.get(2)).multiPart("files",files.get(3)) - - .accept(ContentType.JSON).when().post("v1/tests/map/file").as(Map.class); - +public class TestOpenAPIControllerEndpoints { - assertThat(map.size(), org.hamcrest.CoreMatchers.equalTo(4)); + @Test + public void testYamlSpec() + { - assertThat(map.get(files.get(0).getName()), org.hamcrest.CoreMatchers.equalTo(files.get(0).getTotalSpace()+"")); + when().get("v1/openapi.yaml").then().statusCode(200).header("content-type", "text/yaml"); + } - } catch (Exception e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - fail(e.getMessage()); - } + @Test + public void testJsonSpec() + { - } + when().get("v1/openapi.json").then().statusCode(200).header("content-type", "application/json"); + } - @After - public void tearDown() - { - try - { - if(file.exists()) - { - file.delete(); - } + @Test + public void testDocumentation() + { - } catch (Exception e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } + when().get("v1/openapi").then().statusCode(200).header("content-type", "text/html"); + } } diff --git a/proteus-openapi/src/test/resources/application.conf b/proteus-openapi/src/test/resources/application.conf index c943f1b..9b64074 100644 --- a/proteus-openapi/src/test/resources/application.conf +++ b/proteus-openapi/src/test/resources/application.conf @@ -45,6 +45,45 @@ jackson { } +openapi { + + basePath= ${application.path}"/openapi" + + redocPath= "redoc" + + port = ${application.ports.http} + + specFilename="openapi" + + openapi="3.0.1" + + # openapi info + info { + title = ${application.name} + version = ${application.version} + description="Proteus Server" + } + + securitySchemes { + ApiKeyAuth = { + type="apiKey" + in="header" + name="X-API-KEY" + } + } + + servers = [ + { + url=${application.path} + description="Default Server" + } + ] + + converterClasses = [ + + ] +} + globalHeaders { # Access-Control-Allow-Origin: "*"