Build trust in your spec by validating live requests and responses against your OpenAPI spec. Get informed through logs or metrics when violations occur.
There are separate integrations for spring-boot-starter-web (servlet) and spring-boot-starter-webflux (reactive).
dependencies {
implementation "com.getyourguide.openapi.validation:spring-boot-starter-web:{latest-version}"
}dependencies {
implementation "com.getyourguide.openapi.validation:spring-boot-starter-webflux:{latest-version}"
}Spring 2.7.x is also supported but requires to add -spring2.7 to the spring-boot-starter-web
or spring-boot-starter-webflux artifact name.
Following is an example for spring-boot-starter-web:
dependencies {
implementation "com.getyourguide.openapi.validation:spring-boot-starter-web-spring2.7:{latest-version}"
}The library will require a valid OpenAPI specification file to be present in the classpath.
By default, it will look for openapi.yaml, openapi.json, spec.yaml or spec.json.
Do one of the following.
- Copy spec into
src/main/resources - Generate a single spec file that you add to
src/main/resources
Copy all the spec files to src/main/resources and make sure that the main file has a correct name as mentioned
above. This can be done as part of the CI pipeline.
Use openapi-generator to generate a single
openapi.yaml or openapi.json file and add that to src/main/resources.
See openapi-generator Installation for more
information on how to use it with various methods (artifact, docker, brew, npm, ...).
One example for installing openapi-generator with brew and generating a single spec file:
brew install openapi-generator
openapi-generator generate -g openapi -i spec/index.yaml -o /tmp/openapi-spec/
cp /tmp/openapi-spec/openapi.json src/main/resources/openapi.jsonPlease adjust the commands to fit your folder structure.
Without any configuration the library will
- Search for specification file of name (
openapi.yaml/jsonorspec.yaml/json) in resources - Validate 0.1% of all requests
The following configuration can be done within the application.properties.
# Control the percentage of requests that are validated. The default is 0.1% of traffic.
# Here set to validate 100% of traffic
openapi.validation.sample-rate=1.0
# Custom location of specification file within resources or filesystem.
openapi.validation.specification-file-path=/tmp/openapi-spec/openapi.json
# Comma separated list of paths to be excluded from validation. Default is no excluded paths
openapi.validation.excluded-paths=/_readiness,/_liveness,/_metrics
# Throttle the validation reporting (logs & metrics) to a maximum of 1 log/metric per 10 seconds.
# Default is null which results in no throttling.
openapi.validation.validation-report-throttle-wait-seconds=10
# Throttle the validation reporting (logs & metrics) to a maximum of 1 log/metric per 10 seconds.
# Default is "openapi.validation.error".
openapi.validation.validation-report-metric-name=openapi.violation
# Add additional tags to be logged with metrics. They should be in the format {KEY}={VALUE},{KEY}={VALUE}
# Default is no additional tags.
openapi.validation.validation-report-metric-additional-tags=service=example,team=chkTo use DataDog metrics, you need to add the following dependency to your build.gradle:
dependencies {
implementation "com.getyourguide.openapi.validation:metrics-reporter-datadog-spring-boot:{latest-version}"
}By default, the existing StatsDClient bean will be used to log metrics.
If that bean doesn't exist it will not log any metrics.
It is possible to configure the StatsDClient to be used with the following properties:
openapi.validation.datadog.statsd.service.host=localhost
openapi.validation.datadog.statsd.service.port=8125@Component
public class ExampleLoggerExtension implements LoggerExtension {
@Override
public Closeable addToLoggingContext(@NonNull Map<String, String> newTags) {
return LoggingContext.putAll(newTags);
}
}@Slf4j
@Component
public class CustomViolationLogger implements ViolationLogger {
@Override
public void log(OpenApiViolation violation) {
log.error("!!! Spec Violation on {}", violation.getRequestMetaData().getUri());
}
}Define which traffic should be validated. This can be used to only include specific traffic or to enable validation based on a feature flag or experiment.
@Component
public class SampleRateTrafficSelector implements TrafficSelector {
private final FeatureFlag featureFlags;
public SampleRateTrafficSelector(FeatureFlags featureFlags) {
this.featureFlags = featureFlags;
}
@Override
public boolean shouldRequestBeValidated(RequestMetaData requestMetaData) {
return featureFlags.isEnabled("MY_FEATURE_FLAG");
}
}Run examples with ./gradlew :examples:example-spring-boot-starter-web:bootRun or ./gradlew :examples:example-spring-boot-starter-webflux:bootRun.
These are current known limitations of the library. Any help on resolving these is appreciated. PRs are always welcome.
- Only supports Content-Type JSON/XML/HTML
- In order to avoid accidentally caching bigger resources (videos, streams, ...)
- Ignores the error
Instance failed to match exactly one schema (matched X out of Y)- This is currently on purpose, but should be configurable
- Error responses can't (yet) be validated in webflux/reactive
The library is following Semantic Versioning.
Since most of the updates to the library are dependency updates, we also follow their semver changes as well. As there will be (most probably) a multiple dependencies updated with a version we release, we always consider the "highest" version bump (from semver perspective) as the decisioning factor.
- A
majorversion of this library indicates at least one of the dependencies has had amajorrelease. - Similarly, a
minorversion bump indicates that there was nomajordependency update, onlyminorones.