A Python library for validating OpenAPI documents published by OGC API servers
Project description
OGC API Registry Validator
A Python library for validating OpenAPI documents published by OGC API servers against OGC specification requirements.
Why This Library?
OGC API standards (Features, Tiles, Processes, Records, etc.) define specific requirements for the OpenAPI documents that servers must publish. These requirements include:
- Required endpoints (e.g.,
/collections,/conformance) - Required HTTP operations (GET, POST, etc.)
- Conformance class declarations
- Response schemas and content types
This library performs static validation of these OpenAPI documents, helping you verify that your OGC API server's published specification meets the standard requirements before deployment.
Difference from OGC CITE Test Suite
| Aspect | ogcapi-registry | OGC CITE Test Suite |
|---|---|---|
| Type | Static analysis | Runtime testing |
| What it validates | OpenAPI document structure | Actual server behavior |
| Requires running server | No (only the OpenAPI doc) | Yes |
| Speed | Fast (seconds) | Slow (minutes to hours) |
| When to use | CI/CD, pre-deployment | Certification, compliance |
| Catches | Missing paths, wrong methods, schema errors | 500 errors, wrong responses, bugs |
Use both tools together:
- ogcapi-registry → Fast feedback during development, catches specification errors early
- OGC CITE → Full compliance certification, validates actual server responses
Development Workflow:
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Write Code │ --> │ ogcapi-registry │ --> │ OGC CITE │
│ │ │ (static check) │ │ (runtime) │
└─────────────┘ └──────────────────┘ └─────────────┘
Fast Seconds Minutes+
Features
- OGC API Validation: Validate against OGC API - Features, Tiles, Processes, Records, Coverages, EDR, Maps, Styles, Routes
- Conformance-Based Detection: Automatically detect API type from conformance classes
- Error Severity Levels: Distinguish between critical errors, warnings, and informational messages
- Extensible Strategy Pattern: Add custom validation strategies for new specifications
- Async Support: Full async/await support for high-performance validation
Installation
pip install ogcapi-registry
Or with uv:
uv add ogcapi-registry
Quick Start
Validating an OGC API Server
from ogcapi_registry import (
OpenAPIClient,
validate_ogc_api,
parse_conformance_classes,
)
# Fetch the OpenAPI document from your server
client = OpenAPIClient()
openapi_doc, metadata = client.fetch("https://demo.pygeoapi.io/master/openapi")
# Parse conformance classes (usually from /conformance endpoint)
conformance_uris = [
"http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core",
"http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson",
"http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30",
]
conformance_classes = parse_conformance_classes(conformance_uris)
# Validate against OGC API requirements
result = validate_ogc_api(openapi_doc, conformance_classes)
if result.is_valid:
print("OpenAPI document is fully compliant!")
else:
# Check error severity
for error in result.critical_errors:
print(f"CRITICAL: {error['message']}")
for warning in result.warnings:
print(f"WARNING: {warning['message']}")
Understanding Error Severity
The library classifies validation errors by severity:
from ogcapi_registry import ErrorSeverity
# Critical errors: Must be fixed for OGC compliance
result.critical_errors # Missing required endpoints, wrong HTTP methods
# Warnings: Should be fixed but API may still function
result.warnings # Missing recommended features like CRS support
# Info: Optional improvements
result.info_errors # Missing optional features like filtering
# Check if API is compliant (no critical errors)
if result.is_compliant:
print("API meets minimum OGC requirements")
Automatic API Type Detection
from ogcapi_registry import detect_api_types, get_primary_api_type
# Detect all API types from conformance classes
api_types = detect_api_types(conformance_classes)
# e.g., {OGCAPIType.FEATURES, OGCAPIType.TILES}
# Get the primary (most specific) API type
primary = get_primary_api_type(conformance_classes)
# e.g., OGCAPIType.FEATURES
Application Example: CI/CD Validation
Integrate OGC API validation into your deployment pipeline to catch specification errors before they reach production.
Using the Example Script
The library includes a ready-to-use validation script in examples/validate_ogc_api_server.py:
# Clone the repository
git clone https://github.com/francbartoli/ogcapi-registry.git
cd ogcapi-registry
# Install dependencies
uv sync --all-extras --dev
# Run validation against a real OGC API server
uv run python -c "
from examples.validate_ogc_api_server import validate_server, print_report
report = validate_server('https://demo.ldproxy.net/daraa')
print_report(report)
"
The script will:
- Fetch the OpenAPI document from
/api - Fetch conformance classes from
/conformance - Analyze conformance coverage
- Validate against OGC API requirements
- Print a detailed report with errors by severity
Custom CI/CD Script
#!/usr/bin/env python
"""validate_ogc_server.py - CI/CD validation script"""
import sys
import httpx
from ogcapi_registry import (
OpenAPIClient,
validate_ogc_api,
parse_conformance_classes,
)
def validate_server(base_url: str) -> bool:
"""Validate an OGC API server's OpenAPI document."""
# 1. Fetch conformance classes
response = httpx.get(f"{base_url}/conformance")
response.raise_for_status()
conformance_uris = response.json().get("conformsTo", [])
if not conformance_uris:
print("ERROR: No conformance classes declared")
return False
conformance_classes = parse_conformance_classes(conformance_uris)
print(f"Found {len(conformance_classes)} conformance classes")
# 2. Fetch and validate OpenAPI document
client = OpenAPIClient()
openapi_doc, metadata = client.fetch(f"{base_url}/openapi")
print(f"Validating OpenAPI {openapi_doc.get('openapi', 'unknown')}")
# 3. Run OGC API validation
result = validate_ogc_api(openapi_doc, conformance_classes)
# 4. Report results
print(f"\n{'='*50}")
print(f"Validation Result: {'PASSED' if result.is_valid else 'FAILED'}")
print(f"{'='*50}")
if result.critical_errors:
print(f"\nCritical Errors ({len(result.critical_errors)}):")
for err in result.critical_errors:
print(f" - {err['path']}: {err['message']}")
if result.warnings:
print(f"\nWarnings ({len(result.warnings)}):")
for warn in result.warnings:
print(f" - {warn['path']}: {warn['message']}")
summary = result.get_summary()
print(f"\nSummary: {summary['critical']} critical, "
f"{summary['warning']} warnings, {summary['info']} info")
# Return True only if no critical errors
return result.is_compliant
if __name__ == "__main__":
server_url = sys.argv[1] if len(sys.argv) > 1 else "https://demo.pygeoapi.io/master"
success = validate_server(server_url)
sys.exit(0 if success else 1)
Use in GitHub Actions:
- name: Install ogcapi-registry
run: pip install ogcapi-registry
- name: Validate OGC API Compliance
run: python validate_ogc_server.py ${{ env.SERVER_URL }}
Or using the library's example script directly:
- name: Checkout ogcapi-registry
uses: actions/checkout@v4
with:
repository: francbartoli/ogcapi-registry
path: ogcapi-registry
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: cd ogcapi-registry && uv sync --all-extras --dev
- name: Validate OGC API Server
run: |
cd ogcapi-registry
uv run python -c "
from examples.validate_ogc_api_server import validate_server, print_report
report = validate_server('${{ env.SERVER_URL }}')
print_report(report)
exit(0 if report['status'] in ['valid', 'compliant'] else 1)
"
Supported OGC API Standards
| Standard | Strategy Class | Key Validations |
|---|---|---|
| OGC API - Common | CommonStrategy |
Landing page, conformance, API definition |
| OGC API - Features | FeaturesStrategy |
Collections, items, bbox, CRS |
| OGC API - Tiles | TilesStrategy |
Tile matrix sets, tile endpoints |
| OGC API - Processes | ProcessesStrategy |
Process list, execution, jobs |
| OGC API - Records | RecordsStrategy |
Catalog, record queries |
| OGC API - Coverages | CoveragesStrategy |
Coverage data access |
| OGC API - EDR | EDRStrategy |
Environmental data queries |
| OGC API - Maps | MapsStrategy |
Map rendering endpoints |
| OGC API - Styles | StylesStrategy |
Style management |
| OGC API - Routes | RoutesStrategy |
Routing endpoints |
Advanced Usage
Custom Validation Strategy
from ogcapi_registry import ValidationStrategy, OGCAPIType, ValidationResult
class MyCustomStrategy(ValidationStrategy):
"""Custom validation for organization-specific requirements."""
api_type = OGCAPIType.FEATURES
def validate(self, document, conformance_classes):
errors = []
# Add custom validation logic
if "/health" not in document.get("paths", {}):
errors.append({
"path": "paths",
"message": "Missing /health endpoint (org requirement)",
"severity": "warning",
})
return ValidationResult.success() if not errors else ValidationResult.failure(errors)
Async Validation
import asyncio
from ogcapi_registry import AsyncOpenAPIClient, validate_ogc_api
async def validate_multiple_servers(urls: list[str]):
client = AsyncOpenAPIClient()
async def validate_one(url):
doc, _ = await client.fetch(f"{url}/openapi")
# ... fetch conformance and validate
return url, result
results = await asyncio.gather(*[validate_one(url) for url in urls])
return dict(results)
Documentation
Full documentation: https://francbartoli.github.io/ogcapi-registry/
Development
# Clone and install
git clone https://github.com/francbartoli/ogcapi-registry.git
cd ogcapi-registry
uv sync --all-extras --dev
# Run tests
uv run pytest -v
# Run linting
uv run ruff check src/ tests/
uv run mypy src/ogcapi_registry
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ogcapi_registry-0.3.0.tar.gz.
File metadata
- Download URL: ogcapi_registry-0.3.0.tar.gz
- Upload date:
- Size: 33.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
45893a8a836191232ff7e7045e74e94b646f807a38f982f72b3717774f98fc59
|
|
| MD5 |
6581fa673f222af5ec9e804d5a21ab56
|
|
| BLAKE2b-256 |
c1471f31862802a984de5336527c3bee02e4164d353f9a1d5f4b2d4a66a29f93
|
Provenance
The following attestation bundles were made for ogcapi_registry-0.3.0.tar.gz:
Publisher:
release.yml on francbartoli/ogcapi-registry
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ogcapi_registry-0.3.0.tar.gz -
Subject digest:
45893a8a836191232ff7e7045e74e94b646f807a38f982f72b3717774f98fc59 - Sigstore transparency entry: 760581836
- Sigstore integration time:
-
Permalink:
francbartoli/ogcapi-registry@1bfe086458ecde92d4ddaddee32bf8c0defafc03 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/francbartoli
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1bfe086458ecde92d4ddaddee32bf8c0defafc03 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ogcapi_registry-0.3.0-py3-none-any.whl.
File metadata
- Download URL: ogcapi_registry-0.3.0-py3-none-any.whl
- Upload date:
- Size: 45.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63b8c59685e691012b15a90bf1a52bc81545fea3be456f670265fba0cc266611
|
|
| MD5 |
4e0fdf9730cf7d5cd84ac4369ce098ff
|
|
| BLAKE2b-256 |
9ad9c49deff2744d136369bcbe4e0d2b7e2a09eec542608e96228953777b0953
|
Provenance
The following attestation bundles were made for ogcapi_registry-0.3.0-py3-none-any.whl:
Publisher:
release.yml on francbartoli/ogcapi-registry
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ogcapi_registry-0.3.0-py3-none-any.whl -
Subject digest:
63b8c59685e691012b15a90bf1a52bc81545fea3be456f670265fba0cc266611 - Sigstore transparency entry: 760581839
- Sigstore integration time:
-
Permalink:
francbartoli/ogcapi-registry@1bfe086458ecde92d4ddaddee32bf8c0defafc03 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/francbartoli
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1bfe086458ecde92d4ddaddee32bf8c0defafc03 -
Trigger Event:
push
-
Statement type: