Photo by Willian Justen de Vasconcellos on Unsplash
Validating API requests and responses
Shift left with Postman and OpenAPI specification
There are plenty of excellent and well-established tools that help design, create and validate an OpenAPI specification. But surely it is (at least) as critical to ensuring that the API contracts are honoured by the API we are developing.
In this article: find out how you can use Postman to validate the requests and responses, catch inconsistencies early, try out the OpenAPI Request Response Validator.
What we are going to do
The goal is to validate the API behaviour at runtime, so we are going to pass headers, request and response bodies to the validator and verify the API “does what it says”, according to its OpenAPI specification.
There are several components involved:
the OpenAPI file (obviously)
your REST API (running somewhere)
Postman to invoke the API endpoints
the Validator tool running on localhost
Why Postman
The OpenAPI Validator is a standalone application (see later) and could be used in different ways (CI, integration testing, API gateway), but the Postman integration is powerful as it helps developers validate the API locally (shift-left), catch issues early, fix them before everyone finds out 😁.
Postman Tests allow writing test scripts that run after the execution of the request: we are going to use this feature to create a script that validates the interaction with the API, using an assertion to validate the expected result.
While a Test can be defined for each request, it is also possible (and extremely useful in this case) to create the Test script at the Collection level. You have already guessed, didn’t you? Doing this the script will run after every request in the collection.
Collection Test Script
In the Collection Tests add the snippet below.
// define object
openapiRequestResponseValidation = {
// define function
validate: function(pm) {
const postRequest = {
url: 'http://localhost:8080/validate',
method: 'POST',
header: {'Content-Type': 'application/json'},
body: {
mode: 'raw',
raw: JSON.stringify({
method: pm.request.method,
path: pm.request.url.getPath(),
headers: pm.request.headers,
requestAsJson: (pm.request.body != "") ? pm.request.body.raw : null,
responseAsJson: pm.response.text(),
statusCode: pm.response.code
})
}
};
pm.sendRequest(postRequest, (error, response) => {
if(error != undefined) {
pm.expect.fail('Unexpected error ' + error);
} else {
var data = response.json();
if(data.valid == false) {
console.log(data.errors);
}
pm.test("OpenAPI validation", () => {
pm.expect(data.valid, "Invalid request/response (check Console)").to.equal(true);
});
}
});
}
};
// invoke function
openapiRequestResponseValidation.validate(pm);
Let’s break down what happens:
first, create the object
openapiRequestResponseValidation
that includes a single functionvalidate
.the function
validate
performs 3 steps: it collects all data we need (headers, request, response, HTTP status), sends a POST request to the Validator and verifies the outcome.
If it goes smoothly the test passes and is marked as green.
OpenAPI validation
OpenAPI Request Response Validator
The openapi-request-response-validator is a SpringBoot application with a REST controller to allow Postman scripts (or other clients) to send the payload to validate. The OpenAPI file can be supplied at startup.
The outcome of the validation (together with the list of errors — if any) is returned to Postman (displayed in the Postman console) and logged by the application.
Run with Java
Copy/rename your OpenAPI specs to openapi/openapi.yaml
or openapi/openapi.json
and start the application:
mvn spring-boot:run
If needed you can customise the location of the OpenAPI file
mvn spring-boot:run
-Dspring-boot.run.arguments="--inputSpecs=/path/to/myopenapi.yaml"
Run with Docker
You can also run it on Docker
# run using default openapi/openapi.yaml or openapi/openapi.json
docker run -v $(pwd):/openapi -it --rm \
--name openapi-request-response-validation \
gcatanese/openapi-request-response-validation
Once the validator is running you can crack on: run the Postman requests and check the Test Results (in case of errors).
Final remarks
OpenAPI examples
A little bonus is when your Postman collection uses (i.e. request body) the examples included in the OpenAPI file. The validation can then confirm those examples match the OpenAPI specs. We all know the API evolves and the specs change but the examples can be overlooked.
Business as usual
The idea behind the tool is that developers can focus on creating the best API while the validation is performed in the background. Go on and develop, test and ship your API (the validator will not bother you if everything works as expected).
API fails, validation doesn’t
That's a perfectly valid scenario. API calls might fail (backend errors, business rules) but the OpenAPI contract is not broken. The response with the error should be documented in the OpenAPI file and will also be validated.