Case Study DigitalRoute Case Study: Success Story

How KrakenD API Gateway uses JSON Schema

by Albert Lombarte

Adopting best practices in the dynamic realm of API development is critical to ensuring data integrity, security, and seamless interactions.

In our experience, JSON Schema (project website) emerged as a fundamental tool in this journey. Since we started using it, the developer experience has dramatically improved for KrakenD core developers and KrakenD users.

KrakenD uses JSON Schema mainly for five very distinct use cases (though there are more):

  • Validating incoming requests on runtime
  • Ensure complete responses before returning them to users
  • Validate configuration files in deployment and build processes.
  • Document our software
  • Write End-to-End tests specifications

Let’s have a quick look at these five.

Validating Incoming Requests

Ensuring that data sent by end-users to an API adheres to a specific contract is crucial for maintaining integrity. Even when your upstream services can validate data, by placing JSON Schema validation in the gateway, you enforce data consistency before the request reaches all your endpoints, saving compute, preventing malformed requests, and enhancing the reliability of your system.

Let’s consider a simple, practical use case - a member wants to update their address. You could have a gateway definition like this:

{
    "version": 3,
    "port": 8080,
    "endpoints": [
        {
            "endpoint": "/member/{id}/address",
            "method": "PUT",
            "backend": [
                {
                    "host": ["http://members.svc"],
                    "url_pattern": "/updateMemberAddress/{id}"
                }
            ],
            "extra_config": {
                "validation/json-schema": {
                    "type": "object",
                    "required": ["number", "street_name"],
                    "properties": {
                        "number": { "type": "number" },
                        "street_name": { "type": "string" },
                        "street_type": {
                            "type": "string",
                            "enum": ["Street", "Avenue", "Boulevard"]
                        }
                    }
                }
            }
        }
    ]
}

In the example above, there is an endpoint receiving a PUT request, and we ensure that the incoming data is a JSON object with specific required fields (number and street_name) and that all fields follow their respective data types.

Validating Outgoing Responses

Consistency in responses is equally vital for a positive user experience and data consumption. As KrakenD aggregates content from multiple APIs in a single endpoint, the response schema validator allows you to specify the minimal expected structure of outgoing data, ensuring that your API delivers predictable and well-formed responses.

In the following example, the validator ensures that the final aggregated response contains at least a user_id and a status. But the schema could be anything.

{
  "response-schema-validator": {
    "schema": {
      "$schema": "http://json-schema.org/draft-07/schema",
      "type": "object",
      "properties": {
        "user": {
          "type": "object",
          "properties": {
            "user_id": {
              "type": "number"
            },
            "status": {
              "type": "string"
            }
          }
        }
      },
      "required": [
        "username",
        "status"
      ]
    },
    "error": {
      "body": "We couldn't process you request, try again later.",
      "status": 503
    }
  }
}

If the aggregated response does not comply, you return a custom error We couldn't process your request, try again later. with a 503 Service Unavailable status code.

Safe Configuration Files

Finally, the most beneficial usage of JSON Schema for developers is to deploy error-free configurations, and JSON schema participates in numerous places.

When writing your configuration, you can always specify which version of the schema you want to apply (yes, we maintain one schema for each version of the software) that we host at our website, and you can benefit from the IDE integration which provides documentation while hovering an attribute, explanation of errors, and autocompletion of properties.

In addition, if you split your configuration into multiple files, we keep individual JSON Schemas for each component. See the source code here

Finally, by incorporating JSON Schema into our configuration files, we bring a layer of clarity and validation, making it easier to understand, maintain, and evolve your system’s setup as the krakend check --lint command tells you what the incorrect pieces of configuration you are loading are.

Adding our check command with the JSON schema validation in your CI/CD will abort the deployment/build when you introduce incorrect configurations.

Documenting our software

If we have a JSON schema that can validate your configuration, why wouldn’t we add titles, descriptions, links, etc., and use it as the base for documentation?

All the documentation pages on KrakenD load a snippet that takes the data from the schema directly:

We write a simple snippet in our markdown pages:

{{ < schema data="krakend.json" filter="listen_ip,timeout" >}}

This renders the documentation table, including example values, defaults, enums, and the URL where the schema was taken from:

Fields of "false"
* required fields

listen_ip string
The IP address that KrakenD listens to in IPv4 or IPv6. An empty string, or no declaration at all means listening on all interfaces. The inclusion of :: is meant for IPv6 format only (this is not the port). Examples of valid addresses are 192.0.2.1 (IPv4), 2001:db8::68 (IPv6). The values :: and 0.0.0.0 listen to all addresses and both are valid for IPv4 and IPv6 simultaneously.
Examples: "172.12.1.1" , "::1"
Defaults to "0.0.0.0"
timeout string
Defines a default timeout for all endpoints. Can be overriden per endpoint.
Specify units using ns (nanoseconds), us or µs (microseconds), ms (milliseconds), s (seconds), m (minutes), or h (hours).
Defaults to "2s"

Defining end-to-end tests with JSON Schema

The last case is for End-to-End Testing. Sometimes test cases cannot be deterministic because querying an endpoint twice might bring different outputs (for instance, there is a field date or time that changes on every execution). In these cases, even if you cannot test a literal value, you can always ensure that the whole response adheres to a specific JSON schema, securing the information you get is what you expect.

Conclusion

In summary, embracing JSON Schema as a standard practice in API development offers a trifecta of benefits. It fortifies our APIs against malformed requests, ensures consistent responses, brings order to configuration files, and helps us have better documentation.

Adopting JSON Schema on KrakenD has been a game-changer in development.

As a result, you build robust and reliable APIs, streamline development processes, and foster collaboration within your team. JSON Schema isn’t just a validator; it’s a cornerstone of modern API development.

For more information about how JSON Schema defines structures, check their specification

Scarf

Stay up to date with KrakenD releases and important updates