@@ -331,6 +331,8 @@ def stac_validate(
331
331
errors : Errors ,
332
332
context : Context ,
333
333
method : Method = Method .GET ,
334
+ open_assets_urls : bool = True ,
335
+ headers : Optional [dict ] = None ,
334
336
) -> None :
335
337
if not body :
336
338
errors += f"[{ context } ] : { method } { url } body was empty when running stac-validate and stac-check"
@@ -350,8 +352,14 @@ def stac_validate(
350
352
errors += f"[{ context } ] : { method } { url } '{ body .get ('id' )} ' failed pystac hydration: { e } "
351
353
352
354
if _type in ["Collection" , "Feature" ]:
355
+ logger .debug (f"stac-validator validation: { url } " )
353
356
if not (
354
- stac_validator := StacValidate (links = True , assets = True )
357
+ stac_validator := StacValidate (
358
+ links = True ,
359
+ assets = True ,
360
+ assets_open_urls = open_assets_urls ,
361
+ headers = headers or {},
362
+ )
355
363
).validate_dict (body ):
356
364
errors += f"[{ context } ] : { method } { url } failed stac-validator validation: { stac_validator .message } "
357
365
@@ -365,9 +373,12 @@ def stac_check(
365
373
warnings : Warnings ,
366
374
context : Context ,
367
375
method : Method = Method .GET ,
376
+ open_assets_urls : bool = True ,
377
+ headers : Optional [dict ] = None ,
368
378
) -> None :
369
379
try :
370
- linter = Linter (url )
380
+ logger .debug (f"stac-check validation: { url } " )
381
+ linter = Linter (url , assets_open_urls = open_assets_urls , headers = headers or {})
371
382
if not linter .valid_stac :
372
383
errors += f"[{ context } ] : { method } { url } is not a valid STAC object: { linter .error_msg } "
373
384
if msgs := linter .best_practices_msg [1 :]: # first msg is a header, so skip
@@ -548,6 +559,7 @@ def validate_api(
548
559
query_config : QueryConfig ,
549
560
transaction_collection : Optional [str ],
550
561
headers : Optional [Dict [str , str ]],
562
+ open_assets_urls : bool = True ,
551
563
) -> Tuple [Warnings , Errors ]:
552
564
warnings = Warnings ()
553
565
errors = Errors ()
@@ -598,13 +610,17 @@ def validate_api(
598
610
599
611
if "collections" in ccs_to_validate :
600
612
logger .info ("Validating STAC API - Collections conformance class." )
601
- validate_collections (landing_page_body , collection , errors , warnings , r_session )
613
+ validate_collections (
614
+ landing_page_body , collection , errors , warnings , r_session , open_assets_urls
615
+ )
602
616
603
617
conforms_to = landing_page_body .get ("conformsTo" , [])
604
618
605
619
if "features" in ccs_to_validate :
606
620
logger .info ("Validating STAC API - Features conformance class." )
607
- validate_collections (landing_page_body , collection , errors , warnings , r_session )
621
+ validate_collections (
622
+ landing_page_body , collection , errors , warnings , r_session , open_assets_urls
623
+ )
608
624
validate_features (
609
625
landing_page_body ,
610
626
conforms_to ,
@@ -613,7 +629,8 @@ def validate_api(
613
629
warnings ,
614
630
errors ,
615
631
r_session ,
616
- validate_pagination = validate_pagination ,
632
+ validate_pagination ,
633
+ open_assets_urls ,
617
634
)
618
635
619
636
if "transaction" in ccs_to_validate :
@@ -664,6 +681,7 @@ def validate_api(
664
681
conformance_classes = ccs_to_validate ,
665
682
r_session = r_session ,
666
683
validate_pagination = validate_pagination ,
684
+ open_assets_urls = open_assets_urls ,
667
685
)
668
686
669
687
if "item-search#fields" in ccs_to_validate :
@@ -963,6 +981,7 @@ def validate_collections(
963
981
errors : Errors ,
964
982
warnings : Warnings ,
965
983
r_session : Session ,
984
+ open_assets_urls : bool = True ,
966
985
) -> None :
967
986
if not (data_link := link_by_rel (root_body ["links" ], "data" )):
968
987
errors += f"[{ Context .COLLECTIONS } ] /: Link[rel=data] must href /collections"
@@ -1019,7 +1038,15 @@ def validate_collections(
1019
1038
)
1020
1039
else :
1021
1040
for body in collections_list :
1022
- stac_validate (collections_url , body , errors , Context .COLLECTIONS )
1041
+ stac_validate (
1042
+ collections_url ,
1043
+ body ,
1044
+ errors ,
1045
+ Context .COLLECTIONS ,
1046
+ Method .GET ,
1047
+ open_assets_urls ,
1048
+ r_session .headers ,
1049
+ )
1023
1050
1024
1051
collection_url = f"{ data_link ['href' ]} /{ collection } "
1025
1052
_ , body , resp_headers = retrieve (
@@ -1047,8 +1074,24 @@ def validate_collections(
1047
1074
if not link_by_rel (body .get ("links" , []), "parent" ):
1048
1075
errors += f"[{ Context .COLLECTIONS } ] : { collection_url } does not have parent link"
1049
1076
1050
- stac_validate (collection_url , body , errors , Context .COLLECTIONS )
1051
- stac_check (collection_url , errors , warnings , Context .COLLECTIONS )
1077
+ stac_validate (
1078
+ collection_url ,
1079
+ body ,
1080
+ errors ,
1081
+ Context .COLLECTIONS ,
1082
+ Method .GET ,
1083
+ open_assets_urls ,
1084
+ r_session .headers ,
1085
+ )
1086
+ stac_check (
1087
+ collection_url ,
1088
+ errors ,
1089
+ warnings ,
1090
+ Context .COLLECTIONS ,
1091
+ Method .GET ,
1092
+ open_assets_urls ,
1093
+ r_session .headers ,
1094
+ )
1052
1095
1053
1096
# todo: collection pagination
1054
1097
@@ -1062,6 +1105,7 @@ def validate_features(
1062
1105
errors : Errors ,
1063
1106
r_session : Session ,
1064
1107
validate_pagination : bool ,
1108
+ open_assets_urls : bool = True ,
1065
1109
) -> None :
1066
1110
if not geometry :
1067
1111
errors += f"[{ Context .FEATURES } ] Geometry parameter required for running Features validations."
@@ -1132,7 +1176,15 @@ def validate_features(
1132
1176
if not body :
1133
1177
errors += f"[{ Context .FEATURES } ] GET { collection_items_url } returned an empty body"
1134
1178
else :
1135
- stac_validate (collection_items_url , body , errors , Context .FEATURES )
1179
+ stac_validate (
1180
+ collection_items_url ,
1181
+ body ,
1182
+ errors ,
1183
+ Context .FEATURES ,
1184
+ Method .GET ,
1185
+ open_assets_urls ,
1186
+ r_session .headers ,
1187
+ )
1136
1188
1137
1189
item_url = link_by_rel (body .get ("features" , [])[0 ]["links" ], "self" )[
1138
1190
"href"
@@ -1147,8 +1199,24 @@ def validate_features(
1147
1199
r_session = r_session ,
1148
1200
)
1149
1201
1150
- stac_validate (item_url , body , errors , Context .FEATURES )
1151
- stac_check (item_url , errors , warnings , Context .FEATURES )
1202
+ stac_validate (
1203
+ item_url ,
1204
+ body ,
1205
+ errors ,
1206
+ Context .FEATURES ,
1207
+ Method .GET ,
1208
+ open_assets_urls ,
1209
+ r_session .headers ,
1210
+ )
1211
+ stac_check (
1212
+ item_url ,
1213
+ errors ,
1214
+ warnings ,
1215
+ Context .FEATURES ,
1216
+ Method .GET ,
1217
+ open_assets_urls ,
1218
+ r_session .headers ,
1219
+ )
1152
1220
1153
1221
# Validate Features non-existent item
1154
1222
if not (collections_link := link_by_rel (root_links , "data" )):
@@ -1195,7 +1263,15 @@ def validate_features(
1195
1263
if not link_by_rel (body .get ("links" , []), "root" ):
1196
1264
errors += f"[{ Context .FEATURES } ] GET { collection_items_url } does not have root link"
1197
1265
1198
- stac_validate (collection_items_url , body , errors , Context .FEATURES )
1266
+ stac_validate (
1267
+ collection_items_url ,
1268
+ body ,
1269
+ errors ,
1270
+ Context .FEATURES ,
1271
+ Method .GET ,
1272
+ open_assets_urls ,
1273
+ r_session .headers ,
1274
+ )
1199
1275
1200
1276
item = next (iter (body .get ("features" , [])), None )
1201
1277
@@ -1233,8 +1309,24 @@ def validate_features(
1233
1309
if not link_by_rel (body .get ("links" , []), "parent" ):
1234
1310
errors += f"[{ Context .FEATURES } ] GET { item_url } does not have parent link"
1235
1311
1236
- stac_validate (item_url , body , errors , Context .FEATURES )
1237
- stac_check (item_url , errors , warnings , Context .FEATURES )
1312
+ stac_validate (
1313
+ item_url ,
1314
+ body ,
1315
+ errors ,
1316
+ Context .FEATURES ,
1317
+ Method .GET ,
1318
+ open_assets_urls ,
1319
+ r_session .headers ,
1320
+ )
1321
+ stac_check (
1322
+ item_url ,
1323
+ errors ,
1324
+ warnings ,
1325
+ Context .FEATURES ,
1326
+ Method .GET ,
1327
+ open_assets_urls ,
1328
+ r_session .headers ,
1329
+ )
1238
1330
1239
1331
if validate_pagination :
1240
1332
# Items pagination validation
@@ -1270,6 +1362,7 @@ def validate_item_search(
1270
1362
conformance_classes : List [str ],
1271
1363
r_session : Session ,
1272
1364
validate_pagination : bool ,
1365
+ open_assets_urls : bool = True ,
1273
1366
) -> None :
1274
1367
links = root_body .get ("links" )
1275
1368
@@ -1317,7 +1410,14 @@ def validate_item_search(
1317
1410
)
1318
1411
1319
1412
if body :
1320
- stac_validate (search_url , body , errors , Context .ITEM_SEARCH )
1413
+ stac_validate (
1414
+ search_url ,
1415
+ body ,
1416
+ errors ,
1417
+ Context .ITEM_SEARCH ,
1418
+ open_assets_urls ,
1419
+ r_session .headers ,
1420
+ )
1321
1421
1322
1422
validate_item_search_limit (search_url , methods , errors , r_session )
1323
1423
validate_item_search_bbox_xor_intersects (search_url , methods , errors , r_session )
0 commit comments