Skip to content

Commit 8e593d4

Browse files
authored
bugfix: fail-on-request shouldn't fail if violation is excluded (#252)
1 parent 37dcabf commit 8e593d4

File tree

4 files changed

+47
-34
lines changed

4 files changed

+47
-34
lines changed

openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidator.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
1010
import com.getyourguide.openapi.validation.api.model.RequestMetaData;
1111
import com.getyourguide.openapi.validation.api.model.ResponseMetaData;
12+
import com.getyourguide.openapi.validation.core.exclusions.InternalViolationExclusions;
1213
import com.getyourguide.openapi.validation.core.mapper.ValidationReportToOpenApiViolationsMapper;
1314
import com.getyourguide.openapi.validation.core.validator.OpenApiInteractionValidatorWrapper;
1415
import java.net.URLDecoder;
@@ -25,17 +26,20 @@ public class OpenApiRequestValidator {
2526
private final Executor executor;
2627
private final OpenApiInteractionValidatorWrapper validator;
2728
private final ValidationReportToOpenApiViolationsMapper mapper;
29+
private final InternalViolationExclusions violationExclusions;
2830

2931
public OpenApiRequestValidator(
3032
Executor executor,
3133
MetricsReporter metricsReporter,
3234
OpenApiInteractionValidatorWrapper validator,
3335
ValidationReportToOpenApiViolationsMapper mapper,
36+
InternalViolationExclusions violationExclusions,
3437
OpenApiRequestValidationConfiguration configuration
3538
) {
3639
this.executor = executor;
3740
this.validator = validator;
3841
this.mapper = mapper;
42+
this.violationExclusions = violationExclusions;
3943

4044
metricsReporter.reportStartup(
4145
validator != null,
@@ -92,7 +96,10 @@ public List<OpenApiViolation> validateRequestObject(
9296
try {
9397
var simpleRequest = buildSimpleRequest(request, requestBody);
9498
var result = validator.validateRequest(simpleRequest);
95-
return mapper.map(result, request, response, Direction.REQUEST, requestBody);
99+
var violations = mapper.map(result, request, response, Direction.REQUEST, requestBody);
100+
return violations.stream()
101+
.filter(violation -> !violationExclusions.isExcluded(violation))
102+
.toList();
96103
} catch (Exception e) {
97104
log.error("[OpenAPI Validation] Could not validate request", e);
98105
return List.of();
@@ -136,7 +143,10 @@ public List<OpenApiViolation> validateResponseObject(
136143
Request.Method.valueOf(request.getMethod().toUpperCase()),
137144
responseBuilder.build()
138145
);
139-
return mapper.map(result, request, response, Direction.RESPONSE, responseBody);
146+
var violations = mapper.map(result, request, response, Direction.RESPONSE, responseBody);
147+
return violations.stream()
148+
.filter(violation -> !violationExclusions.isExcluded(violation))
149+
.toList();
140150
} catch (Exception e) {
141151
log.error("[OpenAPI Validation] Could not validate response", e);
142152
return List.of();

openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/log/ExclusionsOpenApiViolationHandler.java

Lines changed: 0 additions & 21 deletions
This file was deleted.

openapi-validation-core/src/test/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidatorTest.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
import static org.mockito.Mockito.when;
88

99
import com.atlassian.oai.validator.model.SimpleRequest;
10-
import com.getyourguide.openapi.validation.api.metrics.MetricsReporter;
10+
import com.atlassian.oai.validator.report.ValidationReport;
11+
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
1112
import com.getyourguide.openapi.validation.api.model.RequestMetaData;
13+
import com.getyourguide.openapi.validation.core.exclusions.InternalViolationExclusions;
1214
import com.getyourguide.openapi.validation.core.mapper.ValidationReportToOpenApiViolationsMapper;
1315
import com.getyourguide.openapi.validation.core.validator.OpenApiInteractionValidatorWrapper;
1416
import java.net.URI;
@@ -25,22 +27,25 @@ public class OpenApiRequestValidatorTest {
2527

2628
private Executor executor;
2729
private OpenApiInteractionValidatorWrapper validator;
30+
private ValidationReportToOpenApiViolationsMapper mapper;
2831

2932
private OpenApiRequestValidator openApiRequestValidator;
33+
private InternalViolationExclusions internalViolationExclusions;
3034

3135
@BeforeEach
3236
public void setup() {
3337
executor = mock();
3438
validator = mock();
35-
MetricsReporter metricsReporter = mock();
36-
var mapper = mock(ValidationReportToOpenApiViolationsMapper.class);
39+
mapper = mock(ValidationReportToOpenApiViolationsMapper.class);
3740
when(mapper.map(any(), any(), any(), any(), any())).thenReturn(List.of());
41+
internalViolationExclusions = mock();
3842

3943
openApiRequestValidator = new OpenApiRequestValidator(
4044
executor,
41-
metricsReporter,
45+
mock(),
4246
validator,
4347
mapper,
48+
internalViolationExclusions,
4449
mock()
4550
);
4651
}
@@ -66,6 +71,23 @@ public void testWhenEncodedQueryParamIsPassedThenValidationShouldHappenWithQuery
6671
verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "spaces", "this is a sparta");
6772
}
6873

74+
@Test
75+
public void testWhenViolationIsExcludedThenItShouldNotBeReturned() {
76+
var uri = URI.create("https://api.example.com/path");
77+
var request = new RequestMetaData("GET", uri, new HashMap<>());
78+
var validationReport = mock(ValidationReport.class);
79+
when(validator.validateRequest(any())).thenReturn(validationReport);
80+
var violationExcluded = mock(OpenApiViolation.class);
81+
var violations = List.of(violationExcluded, mock(OpenApiViolation.class));
82+
when(mapper.map(any(), any(), any(), any(), any())).thenReturn(violations);
83+
when(internalViolationExclusions.isExcluded(violationExcluded)).thenReturn(true);
84+
85+
var result = openApiRequestValidator.validateRequestObject(request, null);
86+
87+
assertEquals(1, result.size());
88+
assertEquals(violations.get(1), result.getFirst());
89+
}
90+
6991
private void verifyQueryParamValueEquals(
7092
ArgumentCaptor<SimpleRequest> simpleRequestArgumentCaptor,
7193
String name,

spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/autoconfigure/LibraryAutoConfiguration.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import com.getyourguide.openapi.validation.core.exclusions.InternalViolationExclusions;
2222
import com.getyourguide.openapi.validation.core.executor.VirtualThreadLimitedExecutor;
2323
import com.getyourguide.openapi.validation.core.log.DefaultOpenApiViolationHandler;
24-
import com.getyourguide.openapi.validation.core.log.ExclusionsOpenApiViolationHandler;
2524
import com.getyourguide.openapi.validation.core.log.ThrottlingOpenApiViolationHandler;
2625
import com.getyourguide.openapi.validation.core.mapper.ValidationReportToOpenApiViolationsMapper;
2726
import com.getyourguide.openapi.validation.core.metrics.DefaultMetricsReporter;
@@ -70,11 +69,15 @@ public MetricsReporter metricsReporter(
7069
);
7170
}
7271

72+
@Bean
73+
public InternalViolationExclusions internalExclusions(Optional<ViolationExclusions> violationExclusions) {
74+
return new InternalViolationExclusions(violationExclusions.orElseGet(NoViolationExclusions::new));
75+
}
76+
7377
@Bean
7478
public OpenApiViolationHandler openApiViolationHandler(
7579
ViolationLogger logger,
76-
MetricsReporter metricsReporter,
77-
Optional<ViolationExclusions> violationExclusions
80+
MetricsReporter metricsReporter
7881
) {
7982
OpenApiViolationHandler handler = new DefaultOpenApiViolationHandler(logger, metricsReporter);
8083

@@ -83,9 +86,6 @@ public OpenApiViolationHandler openApiViolationHandler(
8386
new ThrottlingOpenApiViolationHandler(handler, properties.getValidationReportThrottleWaitSeconds());
8487
}
8588

86-
var exclusions = new InternalViolationExclusions(violationExclusions.orElseGet(NoViolationExclusions::new));
87-
handler = new ExclusionsOpenApiViolationHandler(handler, exclusions);
88-
8989
return handler;
9090
}
9191

@@ -104,7 +104,8 @@ public ValidatorConfiguration validatorConfiguration() {
104104
@Bean
105105
public OpenApiRequestValidator openApiRequestValidator(
106106
MetricsReporter metricsReporter,
107-
ValidatorConfiguration validatorConfiguration
107+
ValidatorConfiguration validatorConfiguration,
108+
InternalViolationExclusions internalExclusions
108109
) {
109110
var threadPoolExecutor = createThreadPoolExecutor();
110111

@@ -114,6 +115,7 @@ public OpenApiRequestValidator openApiRequestValidator(
114115
new OpenApiInteractionValidatorFactory()
115116
.build(properties.getSpecificationFilePath(), validatorConfiguration),
116117
new ValidationReportToOpenApiViolationsMapper(),
118+
internalExclusions,
117119
properties.toOpenApiRequestValidationConfiguration()
118120
);
119121
}

0 commit comments

Comments
 (0)