Landing pages & conformance¶
OGC clients don't read your docs — they start at
GET /and follow links, and they askGET /conformancewhat you support. These are the models for both.
A generic OGC client discovers a service, not the other way around: it fetches
the landing page, follows rel-tagged links to capabilities, and checks the
conformance declaration before relying on a feature. That only works if those
two documents are accurate — which is why gazebo models them (here) and, in the
FastAPI glue, derives them from the running app
so they can't drift from what's actually wired.
Landing page¶
LandingPage is the OGC API Common root document (GET /): a title, a
description, and a links list (deferred Links, like everywhere). It allows
extras for profile-specific members. This is the plain model; if your landing
page mirrors your router tree, the FastAPI glue can
generate a hierarchical one for you
instead of your building it by hand.
from gazebo.link import Link
from gazebo.ogc import LandingPage
from gazebo.rels import Rel
page = LandingPage(
title='Gazebo Gardens',
description='A plant catalog',
links=[
Link.self_link(),
Link.to_route('conformance', rel=Rel.CONFORMANCE),
],
)
Conformance¶
A service advertises which OGC conformance classes it implements at
GET /conformance. The Conformance registry collects the class URIs —
construct it with some, .add() more — and .declaration() produces a
ConformanceDeclaration that serializes as conformsTo. Common Common-spec URIs
are bundled as constants (Conformance.CORE, LANDING_PAGE, JSON, OAS30,
HTML).
from gazebo.ogc import Conformance
conformance = Conformance(Conformance.CORE, Conformance.JSON)
conformance.add(Conformance.LANDING_PAGE)
declaration = conformance.declaration()
Collections & extents¶
Right after the landing page, the OGC API Common endpoints are /collections
(a list) and /collections/{id} (one collection's metadata). Collection
describes a dataset — id, title, description, an extent, an itemType
(serialized as itemType), the crs list (defaulting to
CRS84), and links. Extent carries an optional
SpatialExtent (one or more bounding boxes in a CRS) and TemporalExtent (one or
more [start, end] intervals in a temporal RS, null meaning open). Collections
is the /collections envelope — a LinkedCollection whose items
serialize under collections:
from datetime import datetime, UTC
from gazebo.ogc import Collection, Collections, Extent, SpatialExtent, TemporalExtent
beds = Collection(
id='beds',
title='Garden Beds',
extent=Extent(
spatial=SpatialExtent(bbox=[[-123.0, 35.0, 140.0, 49.0]]),
# null on either side of an interval means open/unbounded
temporal=TemporalExtent(interval=[[datetime(2020, 1, 1, tzinfo=UTC), None]]),
),
)
# `/collections` is the envelope around the collection list.
catalog = Collections(items=[beds], links=[Link.self_link()])
For the actual feature items of a collection, see GeoJSON.
Reference¶
See gazebo.ogc.