Skip to content

Commit cf59ddd

Browse files
Merge pull request #223 from stac-utils/feature/new-titiler-version-0.22.0
update for new titiler version
2 parents 4e78134 + 6e313a1 commit cf59ddd

18 files changed

+430
-832
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Release Notes
22

3+
## 1.8.0
4+
5+
* update titiler requirement to `>=0.22,<0.23`
6+
* add `/conformance` endpoint
7+
* use HTML templates for landing page from `titiler.core`
8+
39
## 1.7.2 (2025-04-03)
410

511
* fix Landing page links when app is behind proxy

docs/src/endpoints/collections_endpoints.md

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@
66
| ------ | ---------------------------------------------------------------------------------|-----------------------------------------|--------------
77
| `GET` | `/collections/{collection_id}/tiles` | JSON | List of OGC Tilesets available
88
| `GET` | `/collections/{collection_id}/tiles/{tileMatrixSetId}` | JSON | OGC Tileset metadata
9-
| `GET` | `/collections/{collection_id}/tiles/{TileMatrixSetId}/{z}/{x}/{Y}/assets` | JSON | Return a list of assets which overlap a given tile
109
| `GET` | `/collections/{collection_id}/tiles/{TileMatrixSetId}/{z}/{x}/{y}[@{scale}x][.{format}]` | image/bin | Create a web map tile image for a collection and a tile index
11-
| `GET` | `/collections/{collection_id}/{TileMatrixSetId}/map` | HTML | simple map viewer
10+
| `GET` | `/collections/{collection_id}/{TileMatrixSetId}/map.html` | HTML | simple map viewer
1211
| `GET` | `/collections/{collection_id}/{TileMatrixSetId}/tilejson.json` | JSON ([TileJSON][tilejson_model]) | Return a Mapbox TileJSON document
1312
| `GET` | `/collections/{collection_id}/{TileMatrixSetId}/WMTSCapabilities.xml` | XML | return OGC WMTS Get Capabilities
1413
| `POST` | `/collections/{collection_id}/statistics` | GeoJSON ([Statistics][statitics_model]) | Return statistics for geojson features
1514
| `GET` | `/collections/{collection_id}/bbox/{minx},{miny},{maxx},{maxy}[/{width}x{height}].{format}`| image/bin | Create an image from part of a dataset
1615
| `POST` | `/collections/{collection_id}/feature[/{width}x{height}][.{format}]` | image/bin | Create an image from a GeoJSON feature
1716
| `GET` | `/collections/{collection_id}/point/{lon},{lat}` | JSON ([Point][point_model]) | Return pixel values from assets intersecting with a given point
1817
| `GET` | `/collections/{collection_id}/point/{lon},{lat}/assets` | JSON | Return a list of assets which overlap a given point
18+
| `GET` | `/collections/{collection_id}/bbox/{minx},{miny},{maxx},{maxy}/assets` | JSON | Return a list of assets which overlap a given bounding box
19+
| `GET` | `/collections/{collection_id}/tiles/{TileMatrixSetId}/{z}/{x}/{Y}/assets` | JSON | Return a list of assets which overlap a given tile
1920
| `GET` | `/collections/{collection_id}/info` | JSON ([Info][info_model]) | Return **Search** query infos from `collection_id`
2021

2122
### Tiles
@@ -136,7 +137,6 @@ Example:
136137
- **datetime** (str):Filters items that have a temporal property that intersects this value. Either a date-time or an interval, open or closed.
137138

138139

139-
140140
!!! important
141141
additional query-parameters will be forwarded to the `tile` URL. If no `defaults` mosaic metadata, **assets** OR **expression** will be required
142142

@@ -147,7 +147,7 @@ Example:
147147
- `https://myendpoint/collections/my-collection/WorldCRS84Quad/WMTSCapabilities.xml?assets=B01&tile_scale=2`
148148

149149

150-
### Assets for Point or Tile
150+
### Assets for Point or Tile or bbox
151151

152152
`:endpoint:/collections/{collection_id}/tiles/{TileMatrixSetId}/{z}/{x}/{y}/assets`
153153

@@ -168,11 +168,11 @@ Example:
168168
- **bbox** (str): Filters items intersecting this bounding box.
169169
- **datetime** (str):Filters items that have a temporal property that intersects this value. Either a date-time or an interval, open or closed.
170170

171-
172171
Example:
173172

174173
- `https://myendpoint/collections/my-collection/tiles/WebMercatorQuad/0/0/0/assets`
175174

175+
176176
`:endpoint:/collections/{collection_id}/point/{lon},{lat}/assets`
177177

178178
- PathParams:
@@ -190,10 +190,32 @@ Example:
190190
- **bbox** (str): Filters items intersecting this bounding box.
191191
- **datetime** (str):Filters items that have a temporal property that intersects this value. Either a date-time or an interval, open or closed.
192192

193+
Example:
194+
195+
- `https://myendpoint/collections/my-collection/point/0.0,0.0/assets`
196+
197+
198+
`:endpoint:/collections/{collection_id}/bbox/{minx},{miny},{maxx},{maxy}/assets`
199+
200+
- PathParams:
201+
- **collection_id**: STAC Collection Identifier.
202+
- **minx,miny,maxx,maxy** (str): Comma (',') delimited bounding box
203+
204+
- QueryParams:
205+
- **scan_limit** (int): Return as soon as we scan N items, Default is 10,000 in PgSTAC.
206+
- **items_limit** (int): Return as soon as we have N items per geometry, Default is 100 in PgSTAC.
207+
- **time_limit** (int): Return after N seconds to avoid long requests, Default is 5sec in PgSTAC.
208+
- **exitwhenfull** (bool): Return as soon as the geometry is fully covered, Default is `True` in PgSTAC.
209+
- **skipcovered** (bool): Skip any items that would show up completely under the previous items, Default is `True` in PgSTAC.
210+
- **ids** (str): Array of Item ids to show.
211+
- **bbox** (str): Filters items intersecting this bounding box.
212+
- **datetime** (str):Filters items that have a temporal property that intersects this value. Either a date-time or an interval, open or closed.
213+
- **coord_crs** (str): Coordinate Reference System of the input coordinates. Default to `epsg:4326`.
193214

194215
Example:
195216

196-
- `https://myendpoint/collections/my-collection/0.0,0.0/assets`
217+
- `https://myendpoint/collections/my-collection/bbox/0,0,0,0/assets`
218+
197219

198220
### Statistics
199221

@@ -237,13 +259,13 @@ Example:
237259
- **datetime** (str):Filters items that have a temporal property that intersects this value. Either a date-time or an interval, open or closed.
238260

239261
!!! important
240-
if **height** and **width** are provided **max_size** will be ignored.
262+
if **height** or **width** is provided **max_size** will be ignored.
241263

242264
Example:
243265

244266
- `https://myendpoint/collections/my-collection/statistics?assets=B01`
245267

246-
### BBOX/Feature
268+
### Bbox
247269

248270
`:endpoint:/collections/{collection_id}/bbox/{minx},{miny},{maxx},{maxy}.{format}`
249271

@@ -286,15 +308,20 @@ Example:
286308
- **datetime** (str):Filters items that have a temporal property that intersects this value. Either a date-time or an interval, open or closed.
287309

288310
!!! important
289-
if **height** and **width** are provided **max_size** will be ignored.
311+
if **height** or **width** is provided **max_size** will be ignored.
290312

291313
Example:
292314

293315
- `https://myendpoint/collections/my-collection/bbox/0,0,10,10.png?assets=B01`
294316
- `https://myendpoint/collections/my-collection/bbox/0,0,10,10/400x300.png?assets=B01`
295317

318+
### Feature
319+
320+
`:endpoint:/collections/{collection_id}/feature - [POST]`
321+
322+
`:endpoint:/collections/{collection_id}/feature.{format} - [POST]`
296323

297-
`:endpoint:/collections/{collection_id}/feature[/{width}x{height}][].{format}] - [POST]`
324+
`:endpoint:/collections/{collection_id}/feature/{width}x{height}.{format} - [POST]`
298325

299326
- Body:
300327
- **feature** (JSON): A valid GeoJSON feature (Polygon or MultiPolygon)
@@ -335,7 +362,7 @@ Example:
335362
- **datetime** (str):Filters items that have a temporal property that intersects this value. Either a date-time or an interval, open or closed.
336363

337364
!!! important
338-
if **height** and **width** are provided **max_size** will be ignored.
365+
if **height** or **width** is provided **max_size** will be ignored.
339366

340367
Example:
341368

@@ -500,25 +527,25 @@ curl 'http://myendpoint/collections/my-collection/info' | jq
500527
"title": "TileJSON link for `visualr` layer (Template URL)."
501528
},
502529
{
503-
"href": "http://myendpoint/collections/my-collection/{tileMatrixSetId}/map",
530+
"href": "http://myendpoint/collections/my-collection/{tileMatrixSetId}/map.html",
504531
"rel": "map",
505532
"templated": true,
506533
"title": "Map viewer link (Template URL)."
507534
},
508535
{
509-
"href": "http://myendpoint/collections/my-collection/{tileMatrixSetId}/map?colormap=%7B%221%22%3A+%5B0%2C+0%2C+0%2C+255%5D%2C+%221000%22%3A+%5B255%2C+255%2C+255%2C+255%5D%7D&assets=visual&asset_bidx=visual%7C1",
536+
"href": "http://myendpoint/collections/my-collection/{tileMatrixSetId}/map.html?colormap=%7B%221%22%3A+%5B0%2C+0%2C+0%2C+255%5D%2C+%221000%22%3A+%5B255%2C+255%2C+255%2C+255%5D%7D&assets=visual&asset_bidx=visual%7C1",
510537
"rel": "map",
511538
"templated": true,
512539
"title": "Map viewer link for `color` layer (Template URL)."
513540
},
514541
{
515-
"href": "http://myendpoint/collections/my-collection/{tileMatrixSetId}/map?maxzoom=22&minzoom=8&assets=visual&asset_bidx=visual%7C1%2C2%2C3",
542+
"href": "http://myendpoint/collections/my-collection/{tileMatrixSetId}/map.html?maxzoom=22&minzoom=8&assets=visual&asset_bidx=visual%7C1%2C2%2C3",
516543
"rel": "map",
517544
"templated": true,
518545
"title": "Map viewer link for `visual` layer (Template URL)."
519546
},
520547
{
521-
"href": "http://myendpoint/collections/my-collection/{tileMatrixSetId}/map?rescale=0%2C100&assets=visual&asset_bidx=visual%7C1",
548+
"href": "http://myendpoint/collections/my-collection/{tileMatrixSetId}/map.html?rescale=0%2C100&assets=visual&asset_bidx=visual%7C1",
522549
"rel": "map",
523550
"templated": true,
524551
"title": "Map viewer link for `visualr` layer (Template URL)."

docs/src/endpoints/items_endpoints.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The `Item` endpoints are created using TiTiler's [MultiBaseTilerFactory](https:/
1414
| `GET` | `/collections/{collection_id}/items/{item_id}/tiles[/{TileMatrixSetId}]/{z}/{x}/{y}[@{scale}x][.{format}]` | image/bin | create a web map tile image from assets
1515
| `GET` | `/collections/{collection_id}/items/{item_id}[/{TileMatrixSetId}]/tilejson.json` | JSON ([TileJSON][tilejson_model]) | return a Mapbox TileJSON document
1616
| `GET` | `/collections/{collection_id}/items/{item_id}[/{TileMatrixSetId}]/WMTSCapabilities.xml` | XML | return OGC WMTS Get Capabilities
17-
| `GET` | `/collections/{collection_id}/items/{item_id}[/{TileMatrixSetId}]/map` | HTML | simple map viewer
17+
| `GET` | `/collections/{collection_id}/items/{item_id}[/{TileMatrixSetId}]/map.html` | HTML | simple map viewer
1818
| `GET` | `/collections/{collection_id}/items/{item_id}/point/{lon},{lat}` | JSON ([Point][multipoint_model]) | return pixel values from assets
1919
| `GET` | `/collections/{collection_id}/items/{item_id}/preview[.{format}]` | image/bin | create a preview image from assets
2020
| `GET` | `/collections/{collection_id}/items/{item_id}/bbox/{minx},{miny},{maxx},{maxy}[/{width}x{height}].{format}` | image/bin | create an image from part of assets

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ classifiers = [
2828
"Topic :: Scientific/Engineering :: GIS",
2929
]
3030
dependencies = [
31-
"titiler.core>=0.21,<0.22",
32-
"titiler.mosaic>=0.21,<0.22",
33-
"geojson-pydantic~=1.0",
31+
"titiler.core>=0.22,<0.23",
32+
"titiler.mosaic>=0.22,<0.23",
3433
"pydantic>=2.4,<3.0",
3534
"pydantic-settings~=2.0",
3635
]

tests/test_collections.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,38 @@ def test_assets_for_tile_collections(app):
7474
assert resp["detail"] == "CollectionId `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` not found"
7575

7676

77+
def test_assets_for_bbox_collections(app):
78+
"""Get assets for a Point."""
79+
80+
bbox = [-86.0, 36.0, -85.0, 37.0]
81+
str_bbox = ",".join(map(str, bbox))
82+
83+
response = app.get(f"/collections/{collection_id}/bbox/{str_bbox}/assets")
84+
assert response.status_code == 200
85+
resp = response.json()
86+
assert len(resp) == 61
87+
88+
bbox = [-9573476, 4300621, -9462156, 4439106]
89+
str_bbox = ",".join(map(str, bbox))
90+
91+
# with coord-crs
92+
response = app.get(
93+
f"/collections/{collection_id}/bbox/{str_bbox}/assets",
94+
params={"coord_crs": "epsg:3857"},
95+
)
96+
assert response.status_code == 200
97+
resp = response.json()
98+
assert len(resp) == 61
99+
100+
# CollectionId not found
101+
response = app.get(
102+
f"/collections/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbox/{str_bbox}/assets"
103+
)
104+
assert response.status_code == 404
105+
resp = response.json()
106+
assert resp["detail"] == "CollectionId `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` not found"
107+
108+
77109
def test_tilejson_collections(app):
78110
"""Create TileJSON."""
79111
response = app.get(f"/collections/{collection_id}/WebMercatorQuad/tilejson.json")
@@ -221,7 +253,7 @@ def test_wmts_collections(app):
221253
assert response.status_code == 400
222254
assert (
223255
response.json()["detail"]
224-
== "assets must be defined either via expression or assets options."
256+
== "Could not find any valid layers in metadata or construct one from Query Parameters."
225257
)
226258

227259
response = app.get(
@@ -314,11 +346,12 @@ def test_statistics_collections(rio, app):
314346

315347
def test_map_collection(app):
316348
"""test /map endpoint."""
317-
response = app.get(f"/collections/{collection_id}/WebMercatorQuad/map")
349+
response = app.get(f"/collections/{collection_id}/WebMercatorQuad/map.html")
318350
assert response.status_code == 400
319351

320352
response = app.get(
321-
f"/collections/{collection_id}/WebMercatorQuad/map", params={"assets": "cog"}
353+
f"/collections/{collection_id}/WebMercatorQuad/map.html",
354+
params={"assets": "cog"},
322355
)
323356
assert response.status_code == 200
324357

tests/test_items.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@ def test_stac_items(rio, app):
7777
)
7878

7979
response = app.get(
80-
"/collections/noaa-emergency-response/items/20200307aC0853900w361030/WebMercatorQuad/map",
80+
"/collections/noaa-emergency-response/items/20200307aC0853900w361030/WebMercatorQuad/map.html",
8181
)
8282
assert response.status_code == 400
8383

8484
response = app.get(
85-
"/collections/noaa-emergency-response/items/20200307aC0853900w361030/WebMercatorQuad/map",
85+
"/collections/noaa-emergency-response/items/20200307aC0853900w361030/WebMercatorQuad/map.html",
8686
params={
8787
"assets": "cog",
8888
},

tests/test_readonly.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def pgstac_info(request: Request):
135135
searches.pixel_selection_dependency,
136136
searches.process_dependency,
137137
searches.render_dependency,
138-
searches.pgstac_dependency,
138+
searches.assets_accessor_dependency,
139139
searches.reader_dependency,
140140
searches.backend_dependency,
141141
],

tests/test_searches.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ def test_wmts(app, search_no_bbox):
307307
assert response.status_code == 400
308308
assert (
309309
response.json()["detail"]
310-
== "assets must be defined either via expression or assets options."
310+
== "Could not find any valid layers in metadata or construct one from Query Parameters."
311311
)
312312

313313
response = app.get(
@@ -599,7 +599,7 @@ def test_query_with_metadata(app):
599599
assert response.status_code == 400
600600
assert (
601601
response.json()["detail"]
602-
== "assets must be defined either via expression or assets options."
602+
== "Could not find any valid layers in metadata or construct one from Query Parameters."
603603
)
604604

605605
# 2. assets and no metadata layers
@@ -839,11 +839,11 @@ def test_mosaic_list(app):
839839

840840
def test_map(app, search_bbox):
841841
"""test /map endpoint."""
842-
response = app.get(f"/searches/{search_bbox}/WebMercatorQuad/map")
842+
response = app.get(f"/searches/{search_bbox}/WebMercatorQuad/map.html")
843843
assert response.status_code == 400
844844

845845
response = app.get(
846-
f"/searches/{search_bbox}/WebMercatorQuad/map", params={"assets": "cog"}
846+
f"/searches/{search_bbox}/WebMercatorQuad/map.html", params={"assets": "cog"}
847847
)
848848
assert response.status_code == 200
849849

titiler/pgstac/backend.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,10 @@ def _reader(
271271
with self.reader(item, tms=self.tms, **self.reader_options) as src_dst:
272272
return src_dst.tile(x, y, z, **kwargs)
273273

274-
return mosaic_reader(mosaic_assets, _reader, tile_x, tile_y, tile_z, **kwargs)
274+
img, used_assets = mosaic_reader(
275+
mosaic_assets, _reader, tile_x, tile_y, tile_z, **kwargs
276+
)
277+
return img, [x["id"] for x in used_assets]
275278

276279
def point(
277280
self,
@@ -351,14 +354,15 @@ def _reader(item: Dict[str, Any], bbox: BBox, **kwargs: Any) -> ImageData:
351354
with self.reader(item, **self.reader_options) as src_dst:
352355
return src_dst.part(bbox, **kwargs)
353356

354-
return mosaic_reader(
357+
img, used_assets = mosaic_reader(
355358
mosaic_assets,
356359
_reader,
357360
bbox,
358361
bounds_crs=bounds_crs,
359362
dst_crs=dst_crs or bounds_crs,
360363
**kwargs,
361364
)
365+
return img, [x["id"] for x in used_assets]
362366

363367
def feature(
364368
self,
@@ -398,7 +402,7 @@ def _reader(item: Dict[str, Any], shape: Dict, **kwargs: Any) -> ImageData:
398402
with self.reader(item, **self.reader_options) as src_dst:
399403
return src_dst.feature(shape, **kwargs)
400404

401-
return mosaic_reader(
405+
img, used_assets = mosaic_reader(
402406
mosaic_assets,
403407
_reader,
404408
shape,
@@ -407,3 +411,4 @@ def _reader(item: Dict[str, Any], shape: Dict, **kwargs: Any) -> ImageData:
407411
max_size=max_size,
408412
**kwargs,
409413
)
414+
return img, [x["id"] for x in used_assets]

titiler/pgstac/dependencies.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,19 @@ def CollectionIdParams(
159159
Optional[str],
160160
Query(
161161
description="Array of Item ids",
162-
json_schema_extra={
163-
"example": "item1,item2",
162+
openapi_examples={
163+
"user-provided": {"value": None},
164+
"multiple-items": {"value": "item1,item2"},
164165
},
165166
),
166167
] = None,
167168
bbox: Annotated[
168169
Optional[str],
169170
Query(
170171
description="Filters items intersecting this bounding box",
171-
json_schema_extra={
172-
"example": "-175.05,-85.05,175.05,85.05",
172+
openapi_examples={
173+
"user-provided": {"value": None},
174+
"Montreal": {"value": "-73.896103,45.364690,-73.413734,45.674283"},
173175
},
174176
),
175177
] = None,
@@ -179,6 +181,7 @@ def CollectionIdParams(
179181
description="""Filters items that have a temporal property that intersects this value.\n
180182
Either a date-time or an interval, open or closed. Date and time expressions adhere to RFC 3339. Open intervals are expressed using double-dots.""",
181183
openapi_examples={
184+
"user-defined": {"value": None},
182185
"datetime": {"value": "2018-02-12T23:20:50Z"},
183186
"closed-interval": {
184187
"value": "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z"

0 commit comments

Comments
 (0)