Skip to content

Commit

Permalink
feat(#1175): adds open api validation by standard citrus schema valid…
Browse files Browse the repository at this point in the history
…aton mechanism
  • Loading branch information
Thorsten Schlathoelter authored and bbortt committed Oct 15, 2024
1 parent 2e0a9fa commit 425b2d0
Show file tree
Hide file tree
Showing 48 changed files with 1,173 additions and 511 deletions.
2 changes: 1 addition & 1 deletion connectors/citrus-openapi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<dependency>
<groupId>com.atlassian.oai</groupId>
<artifactId>swagger-request-validator-core</artifactId>
<version>2.40.0</version>
<version>${swagger-request-validator.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.citrusframework.openapi;

import org.citrusframework.message.MessageHeaders;

public class OpenApiMessageHeaders {

public static final String OAS_PREFIX = MessageHeaders.PREFIX + "oas_";

public static final String OAS_OPERATION = OAS_PREFIX + "operation";

public static final String OAS_MEDIA_TYPE = OAS_PREFIX + "media_type";

public static final String OAS_UNIQUE_OPERATION_ID = OAS_PREFIX + "unique_operation_id";

public static final String OAS_MESSAGE_TYPE = OAS_PREFIX + "message_type";

public static final String RESPONSE_TYPE = OAS_PREFIX + "response";

public static final String REQUEST_TYPE = OAS_PREFIX + "request";

private OpenApiMessageHeaders() {
// Static access only
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.citrusframework.openapi;

/**
* The {@code OpenApiMessageType} enum defines the types of OpenAPI messages,
* specifically REQUEST and RESPONSE. Each type is associated with a specific
* header name, which is used to identify the type of message in the OpenAPI
* message headers.
*/
public enum OpenApiMessageType {

REQUEST(OpenApiMessageHeaders.REQUEST_TYPE), RESPONSE(OpenApiMessageHeaders.RESPONSE_TYPE);

private final String headerName;

OpenApiMessageType(String headerName) {
this.headerName = headerName;
}

public String toHeaderName() {
return headerName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ static Optional<String> determineResourceAlias(Resource openApiResource) {
try {
File file = openApiResource.getFile();
if (file != null) {
return Optional.of(file.getName());
resourceAlias = file.getName();
int index = resourceAlias.lastIndexOf(".");
if (index != -1 && index != resourceAlias.length()-1) {
resourceAlias = resourceAlias.substring(0, index);
}
return Optional.of(resourceAlias);
}
} catch (Exception e) {
// Ignore and try with url
Expand All @@ -130,6 +135,11 @@ static Optional<String> determineResourceAlias(Resource openApiResource) {
if (index != -1 && index != urlString.length()-1) {
resourceAlias = resourceAlias.substring(index+1);
}
index = resourceAlias.lastIndexOf(".");
if (index != -1 && index != resourceAlias.length()-1) {
resourceAlias = resourceAlias.substring(0, index);
}

}
} catch (MalformedURLException e) {
logger.error("Unable to determine resource alias from resource!", e);
Expand All @@ -141,4 +151,13 @@ static Optional<String> determineResourceAlias(Resource openApiResource) {
public List<OpenApiSpecification> getOpenApiSpecifications() {
return openApiSpecifications;
}

public OpenApiRepository locations(List<String> locations) {
setLocations(locations);
return this;
}

public OpenApiSpecification openApi(String alias) {
return getOpenApiSpecifications().stream().filter(spec -> spec.getAliases().contains(alias)).findFirst().orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,13 @@ private void storeOperationPathAdapter(OasOperation operation, String path) {
String basePath = OasModelHelper.getBasePath(openApiDoc);
String fullOperationPath = StringUtils.appendSegmentToUrlPath(basePath, path);

OperationPathAdapter operationPathAdapter = new OperationPathAdapter(path, rootContextPath,
StringUtils.appendSegmentToUrlPath(rootContextPath, path), operation);

String uniqueOperationId = OpenApiUtils.createFullPathOperationIdentifier(fullOperationPath,
operation);
operationToUniqueId.put(operation, uniqueOperationId);

OperationPathAdapter operationPathAdapter = new OperationPathAdapter(path, rootContextPath,
StringUtils.appendSegmentToUrlPath(rootContextPath, path), operation, uniqueOperationId);

operationIdToOperationPathAdapter.put(uniqueOperationId, operationPathAdapter);
if (StringUtils.hasText(operation.operationId)) {
operationIdToOperationPathAdapter.put(operation.operationId, operationPathAdapter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,17 @@
*/
public class OpenApiActionBuilder extends AbstractReferenceResolverAwareTestActionBuilder<TestAction> {

private OpenApiSpecification specification;
private OpenApiSpecificationSource openApiSpecificationSource;

public OpenApiActionBuilder() {
}

public OpenApiActionBuilder(OpenApiSpecification specification) {
this.specification = specification;
this.openApiSpecificationSource = new OpenApiSpecificationSource(specification);
}

public OpenApiActionBuilder(String openApiAlias) {
this.openApiSpecificationSource = new OpenApiSpecificationSource(openApiAlias);
}

/**
Expand All @@ -55,8 +59,17 @@ public static OpenApiActionBuilder openapi(OpenApiSpecification specification) {
return new OpenApiActionBuilder(specification);
}

public static OpenApiActionBuilder openapi(String openApiAlias) {
return new OpenApiActionBuilder(openApiAlias);
}

public OpenApiActionBuilder specification(OpenApiSpecification specification) {
this.specification = specification;
this.openApiSpecificationSource = new OpenApiSpecificationSource(specification);
return this;
}

public OpenApiActionBuilder specificationByAlias(String openApiAlias) {
this.openApiSpecificationSource = new OpenApiSpecificationSource(openApiAlias);
return this;
}

Expand All @@ -70,7 +83,11 @@ public OpenApiActionBuilder specification(String specUrl) {

public OpenApiClientActionBuilder client() {
assertSpecification();
return client(specification.getRequestUrl());
OpenApiClientActionBuilder clientActionBuilder = new OpenApiClientActionBuilder(
openApiSpecificationSource)
.withReferenceResolver(referenceResolver);
this.delegate = clientActionBuilder;
return clientActionBuilder;
}

/**
Expand All @@ -80,10 +97,11 @@ public OpenApiClientActionBuilder client(HttpClient httpClient) {
assertSpecification();

if (httpClient.getEndpointConfiguration().getRequestUrl() != null) {
specification.setRequestUrl(httpClient.getEndpointConfiguration().getRequestUrl());
openApiSpecificationSource.setHttpClient(httpClient.getEndpointConfiguration().getRequestUrl());
}

OpenApiClientActionBuilder clientActionBuilder = new OpenApiClientActionBuilder(httpClient, specification)
OpenApiClientActionBuilder clientActionBuilder = new OpenApiClientActionBuilder(httpClient,
openApiSpecificationSource)
.withReferenceResolver(referenceResolver);
this.delegate = clientActionBuilder;
return clientActionBuilder;
Expand All @@ -95,9 +113,10 @@ public OpenApiClientActionBuilder client(HttpClient httpClient) {
public OpenApiClientActionBuilder client(String httpClient) {
assertSpecification();

specification.setHttpClient(httpClient);
openApiSpecificationSource.setHttpClient(httpClient);

OpenApiClientActionBuilder clientActionBuilder = new OpenApiClientActionBuilder(httpClient, specification)
OpenApiClientActionBuilder clientActionBuilder = new OpenApiClientActionBuilder(httpClient,
openApiSpecificationSource)
.withReferenceResolver(referenceResolver);
this.delegate = clientActionBuilder;
return clientActionBuilder;
Expand All @@ -109,15 +128,16 @@ public OpenApiClientActionBuilder client(String httpClient) {
public OpenApiServerActionBuilder server(Endpoint endpoint) {
assertSpecification();

OpenApiServerActionBuilder serverActionBuilder = new OpenApiServerActionBuilder(endpoint, specification)
OpenApiServerActionBuilder serverActionBuilder = new OpenApiServerActionBuilder(endpoint,
openApiSpecificationSource)
.withReferenceResolver(referenceResolver);
this.delegate = serverActionBuilder;
return serverActionBuilder;
}

private void assertSpecification() {
if (specification == null) {
throw new CitrusRuntimeException("Invalid OpenApi specification - please set specification first");
if (openApiSpecificationSource == null) {
throw new CitrusRuntimeException("Invalid OpenApiSpecificationSource - please set specification first");
}
}

Expand All @@ -127,7 +147,8 @@ private void assertSpecification() {
public OpenApiServerActionBuilder server(String httpServer) {
assertSpecification();

OpenApiServerActionBuilder serverActionBuilder = new OpenApiServerActionBuilder(httpServer, specification)
OpenApiServerActionBuilder serverActionBuilder = new OpenApiServerActionBuilder(httpServer,
openApiSpecificationSource)
.withReferenceResolver(referenceResolver);
this.delegate = serverActionBuilder;
return serverActionBuilder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
*/
public class OpenApiClientActionBuilder extends AbstractReferenceResolverAwareTestActionBuilder<TestAction> {

private final OpenApiSpecification specification;
private final OpenApiSpecificationSource openApiSpecificationSource;

/** Target http client instance */
private Endpoint httpClient;
Expand All @@ -40,24 +40,29 @@ public class OpenApiClientActionBuilder extends AbstractReferenceResolverAwareTe
/**
* Default constructor.
*/
public OpenApiClientActionBuilder(Endpoint httpClient, OpenApiSpecification specification) {
public OpenApiClientActionBuilder(Endpoint httpClient, OpenApiSpecificationSource openApiSpecificationSource) {
this.httpClient = httpClient;
this.specification = specification;
this.openApiSpecificationSource = openApiSpecificationSource;
}

/**
* Default constructor.
*/
public OpenApiClientActionBuilder(String httpClientUri, OpenApiSpecification specification) {
public OpenApiClientActionBuilder(String httpClientUri, OpenApiSpecificationSource openApiSpecificationSource) {
this.httpClientUri = httpClientUri;
this.specification = specification;
this.openApiSpecificationSource = openApiSpecificationSource;
}

public OpenApiClientActionBuilder(OpenApiSpecificationSource openApiSpecificationSource) {
this.openApiSpecificationSource = openApiSpecificationSource;
}

/**
* Sends Http requests as client.
*/
public OpenApiClientRequestActionBuilder send(String operationId) {
OpenApiClientRequestActionBuilder builder = new OpenApiClientRequestActionBuilder(specification, operationId);
OpenApiClientRequestActionBuilder builder = new OpenApiClientRequestActionBuilder(
openApiSpecificationSource, operationId);
if (httpClient != null) {
builder.endpoint(httpClient);
} else {
Expand Down Expand Up @@ -90,7 +95,8 @@ public OpenApiClientResponseActionBuilder receive(String operationId, HttpStatus
* Receives Http response messages as client.
*/
public OpenApiClientResponseActionBuilder receive(String operationId, String statusCode) {
OpenApiClientResponseActionBuilder builder = new OpenApiClientResponseActionBuilder(specification, operationId, statusCode);
OpenApiClientResponseActionBuilder builder = new OpenApiClientResponseActionBuilder(
openApiSpecificationSource, operationId, statusCode);
if (httpClient != null) {
builder.endpoint(httpClient);
} else {
Expand Down
Loading

0 comments on commit 425b2d0

Please sign in to comment.