Skip to content

Instantly share code, notes, and snippets.

@saibotsivad
Created December 14, 2021 22:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saibotsivad/3c1734c7aea85c88b21e276266d31ad6 to your computer and use it in GitHub Desktop.
Save saibotsivad/3c1734c7aea85c88b21e276266d31ad6 to your computer and use it in GitHub Desktop.
OpenAPI with @cfworker/json-schema

Given an OpenAPI definition, I would like to validate a request (query params, path params, etc.) using @cfworker/json-schema.

I've developed a way to do it, but it requires me to use the validate function instead of new Validator.

A simple OpenAPI definition might look like this:

{
    "openapi": "3.1.0",
    "components": {
        "parameters": {
            "taskId": {
                "name": "taskId",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "integer",
                    "minimum": 100
                }
            }
        },
        "schemas": {
            "task": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "minimum": 100
                    },
                    "completed": {
                        "type": "boolean"
                    }
                }
            }
        }
    },
    "paths": {
        "/tasks/{taskId}": {
            "parameters": [
                { "$ref": "#/components/parameters/taskId" }
            ],
            "patch": {
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/task"
                            }
                        }
                    }
                }
            }
        }
    }
}

A few things to note, if you're new to OpenAPI:

  • It's not a valid JSON-Schema document, so any validation will need some setup anyway.
  • Within OpenAPI there's also some type coercion that needs to happen prior to validation. E.g. path parameters can have different "styles" which would need to get cast to different data structures.

Some technical issues with schema validation:

  • The $ref instances point to an object that's not necessarily a schema. See the reference to #/components/parameters/taskId instead of #/components/parameters/taskId/schema for example.

I could not figure out a way to instantiate a Validator instance based on an OpenAPI definition, so instead I followed this approach:

// Use the raw `validate` instead
import { validate } from '@cfworker/json-schema'
import definition from './open-api-definition.json'

// I have some utils to do this, but basically you need to map each
// actual schema to its own hash reference, which looks like this, for
// the example above
const lookup = {
    '#/components/parameters/taskId': definition.components.parameters.taskId.schema,
    '#/components/schemas/task': definition.components.schemas.task,
    '#/paths/%2Ftasks%2F%7BtaskId%7D/patch/requestBody/content/application%2Fjson': definition.paths['/tasks/{taskId}'].patch.requestBody.content['application/json'].schema
}

// Based on the request you'd build the `lookup` key
const requestKey = [
    'paths',
    encodeURIComponent(request.path),
    request.method.toLowerCase(),
    'content',
    request.headers.get('Accept')
].join('/')
const { valid, errors } = validate(
    { id: 123, completed: true },
    lookup['#/' + requestKey],
    '2019-09',
    lookup,
    false
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment