Schemav2Validator Plugin
Validates Beckn protocol requests against OpenAPI 3.1 specifications using kin-openapi library.
Features
- Validates requests against OpenAPI 3.1 specs
- Supports remote URL and local file loading
- Automatic external $ref resolution
- TTL-based caching with automatic refresh
- Generic path matching (no hardcoded paths)
- Direct schema validation without router overhead
- Extended schema validation for domain-specific objects with
@context references
Configuration
schemaValidator:
id: schemav2validator
config:
type: url
location: https://example.com/openapi-spec.yaml
cacheTTL: "3600"
extendedSchema_enabled: "true"
extendedSchema_cacheTTL: "86400"
extendedSchema_maxCacheSize: "100"
extendedSchema_downloadTimeout: "30"
extendedSchema_allowedDomains: "beckn.org,example.com"
Configuration Parameters
| Parameter |
Type |
Required |
Default |
Description |
type |
string |
Yes |
- |
Type of spec source: "url" or "file" ("dir" reserved for future) |
location |
string |
Yes |
- |
URL or file path to OpenAPI 3.1 spec |
cacheTTL |
string |
No |
"3600" |
Cache TTL in seconds before reloading spec |
extendedSchema_enabled |
string |
No |
"false" |
Enable extended schema validation for @context objects |
extendedSchema_cacheTTL |
string |
No |
"86400" |
Domain schema cache TTL in seconds |
extendedSchema_maxCacheSize |
string |
No |
"100" |
Maximum number of cached domain schemas |
extendedSchema_downloadTimeout |
string |
No |
"30" |
Timeout for downloading domain schemas |
extendedSchema_allowedDomains |
string |
No |
"" |
Comma-separated domain whitelist (empty = all allowed) |
How It Works
Initialization (Load Time)
Core Protocol Validation Setup:
- Load OpenAPI Spec: Loads main spec from
location (URL or file) with external $ref resolution
- Build Action Index: Creates action→schema map for O(1) lookup by scanning all paths/methods
- Validate Spec: Validates OpenAPI spec structure (warnings logged, non-fatal)
- Cache Spec: Stores loaded spec with
loadedAt timestamp
Extended Schema Setup (if extendedSchema_enabled: "true"):
5. Initialize Schema Cache: Creates LRU cache with maxCacheSize (default: 100)
6. Start Background Refresh: Launches goroutine with two tickers:
- Core spec refresh every
cacheTTL seconds (default: 3600)
- Extended schema cleanup every
extendedSchema_cacheTTL seconds (default: 86400)
Request Validation (Runtime)
Core Protocol Validation (always runs):
- Parse Request: Unmarshal JSON and extract
context.action
- Lookup Schema: O(1) lookup in action index (built at load time)
- Validate: Call
schema.Value.VisitJSON() with:
- Required fields validation
- Data type validation (string, number, boolean, object, array)
- Format validation (email, uri, date-time, uuid, etc.)
- Constraint validation (min/max, pattern, enum, const)
- Nested object and array validation
- Return Errors: If validation fails, format and return errors
Extended Schema Validation (if extendedSchema_enabled: "true" AND core validation passed):
5. Scan for @context: Recursively traverse message field for objects with @context and @type
6. Filter Core Schemas: Skip objects with /schema/core/ in @context URL
7. Validate Each Domain Object:
- Check domain whitelist (if
allowedDomains configured)
- Transform
@context URL: context.jsonld → attributes.yaml
- Load schema from URL/file (check cache first, download if miss)
- Find schema by
@type (direct match or x-jsonld.@type fallback)
- Strip
@context and @type metadata from object
- Validate remaining data against domain schema
- Prefix error paths with object location (e.g.,
message.order.field)
- Return Errors: Returns first validation error (fail-fast)
Action-Based Matching
The validator uses action-based schema matching, not URL path matching. It searches for schemas where the context.action field has an enum constraint containing the request's action value.
Example OpenAPI Schema
paths:
/beckn/search:
post:
requestBody:
content:
application/json:
schema:
properties:
context:
properties:
action:
enum: ["search"] # ← Matches action="search"
Matching Examples
| Request Action |
Schema Enum |
Match |
search |
enum: ["search"] |
✅ Matches |
select |
enum: ["select", "init"] |
✅ Matches |
discover |
enum: ["search"] |
❌ No match |
on_search |
enum: ["on_search"] |
✅ Matches |
External References
The validator automatically resolves external $ref references in OpenAPI specs:
# Main spec at https://example.com/api.yaml
paths:
/search:
post:
requestBody:
content:
application/json:
schema:
$ref: 'https://example.com/schemas/search.yaml#/SearchRequest'
The loader will automatically fetch and resolve the external reference.
Example Usage
Remote URL
schemaValidator:
id: schemav2validator
config:
type: url
location: https://raw.githubusercontent.com/beckn/protocol-specifications/master/api/beckn-2.0.0.yaml
cacheTTL: "7200"
Local File
schemaValidator:
id: schemav2validator
config:
type: file
location: ./validation-scripts/l2-config/mobility_1.1.0_openapi_3.1.yaml
cacheTTL: "3600"
With Extended Schema Validation
schemaValidator:
id: schemav2validator
config:
type: url
location: https://raw.githubusercontent.com/beckn/protocol-specifications-new/refs/heads/draft/api-specs/beckn-protocol-api.yaml
cacheTTL: "3600"
extendedSchema_enabled: "true"
extendedSchema_cacheTTL: "86400"
extendedSchema_maxCacheSize: "100"
extendedSchema_downloadTimeout: "30"
extendedSchema_allowedDomains: "raw.githubusercontent.com,schemas.beckn.org"
At Load Time:
- Creates LRU cache for domain schemas (max 100 entries)
- Starts background goroutine for cache cleanup every 24 hours
At Runtime (after core validation passes):
- Scans
message field for objects with @context and @type
- Skips core Beckn schemas (containing
/schema/core/)
- Downloads domain schemas from
@context URLs (cached for 24 hours)
- Validates domain-specific data against schemas
- Returns errors with full JSON paths (e.g.,
message.order.chargingRate)
- Fail-fast: returns on first validation error
Dependencies
github.com/getkin/kin-openapi - OpenAPI 3 parser and validator
Error Messages
| Scenario |
Error Message |
| Action is number |
"failed to parse JSON payload: json: cannot unmarshal number into Go struct field .context.action of type string" |
| Action is empty |
"missing field Action in context" |
| Action not in spec |
"unsupported action: <action>" |
| Invalid URL |
"Invalid URL or unreachable: <url>" |
| Schema validation fails |
Returns detailed field-level errors |