From a89d3c3d7b5234f1f19610fc7855306be7bc6559 Mon Sep 17 00:00:00 2001 From: SpicyGarlicAlbacoreRoll Date: Mon, 7 Jul 2025 11:09:22 -0800 Subject: [PATCH 1/5] change: bump query limit to 3000, raise error if expected output exceeds results --- CHANGELOG.md | 1 + src/SearchAPI/application/asf_opts.py | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74ef5ec..4b9b835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Aria stacking uses aria frame id instead of frame number for stacking - asf_search uses `SearchAPISession` by default for search queries - bump asf-search to v9.0.4 +- increase search query limit to 3000, raise error if expected output is over that number ------ ## [1.0.4](https://github.com/asfadmin/Discovery-SearchAPI-v3/compare/v1.0.3...v1.0.4) diff --git a/src/SearchAPI/application/asf_opts.py b/src/SearchAPI/application/asf_opts.py index 158d042..9ee5027 100644 --- a/src/SearchAPI/application/asf_opts.py +++ b/src/SearchAPI/application/asf_opts.py @@ -177,13 +177,20 @@ async def process_search_request(request: Request) -> SearchOptsModel: try: # we are no longer allowing unbounded searches - if query_opts.granule_list is None and query_opts.product_list is None: + if query_opts.granule_list is None and query_opts.product_list is None and output != 'python': if query_opts.maxResults is None: - query_opts.maxResults = asf.search_count(opts=query_opts) + maxResults = asf.search_count(opts=query_opts) + if maxResults > 3000: + raise ValueError( + ( + 'SearchAPI no longer supports unbounded searches with expected results over 3000, ' + 'please use the asf-search python module for long-lived searches or set `maxResults` to 3000 or less.' + '\nTo have SearchAPI automatically generate a python script for the equivalent search to your SearchAPI query ' + 'set `output=python`' + ) + ) elif query_opts.maxResults <= 0: - raise ValueError(f'Search keyword "maxResults" must be greater than 0') - - query_opts.maxResults = min(1500, query_opts.maxResults) + raise ValueError('Search keyword "maxResults" must be greater than 0') searchOpts = SearchOptsModel(opts=query_opts, output=output, merged_args=merged_args, request_method=request.method) except (ValueError, ValidationError) as exc: From d9a8900c460ce65b4b6901353366a6582701c0e5 Mon Sep 17 00:00:00 2001 From: SpicyGarlicAlbacoreRoll Date: Mon, 7 Jul 2025 11:14:14 -0800 Subject: [PATCH 2/5] fix: decrease max allowed results to 2000 --- CHANGELOG.md | 2 +- src/SearchAPI/application/asf_opts.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b9b835..67ec2c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,7 +35,7 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Aria stacking uses aria frame id instead of frame number for stacking - asf_search uses `SearchAPISession` by default for search queries - bump asf-search to v9.0.4 -- increase search query limit to 3000, raise error if expected output is over that number +- increase search query limit to 2000, raise error if expected output is over that number ------ ## [1.0.4](https://github.com/asfadmin/Discovery-SearchAPI-v3/compare/v1.0.3...v1.0.4) diff --git a/src/SearchAPI/application/asf_opts.py b/src/SearchAPI/application/asf_opts.py index 9ee5027..7ee1a25 100644 --- a/src/SearchAPI/application/asf_opts.py +++ b/src/SearchAPI/application/asf_opts.py @@ -180,11 +180,11 @@ async def process_search_request(request: Request) -> SearchOptsModel: if query_opts.granule_list is None and query_opts.product_list is None and output != 'python': if query_opts.maxResults is None: maxResults = asf.search_count(opts=query_opts) - if maxResults > 3000: + if maxResults > 2000: raise ValueError( ( - 'SearchAPI no longer supports unbounded searches with expected results over 3000, ' - 'please use the asf-search python module for long-lived searches or set `maxResults` to 3000 or less.' + 'SearchAPI no longer supports unbounded searches with expected results over 2000, ' + 'please use the asf-search python module for long-lived searches or set `maxResults` to 2000 or less.' '\nTo have SearchAPI automatically generate a python script for the equivalent search to your SearchAPI query ' 'set `output=python`' ) From 3ce8032550157221b1a2928623f66cca29213943 Mon Sep 17 00:00:00 2001 From: SpicyGarlicAlbacoreRoll Date: Mon, 7 Jul 2025 11:19:48 -0800 Subject: [PATCH 3/5] fix: remove newline from error message --- src/SearchAPI/application/asf_opts.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SearchAPI/application/asf_opts.py b/src/SearchAPI/application/asf_opts.py index 7ee1a25..ab81ee1 100644 --- a/src/SearchAPI/application/asf_opts.py +++ b/src/SearchAPI/application/asf_opts.py @@ -184,8 +184,8 @@ async def process_search_request(request: Request) -> SearchOptsModel: raise ValueError( ( 'SearchAPI no longer supports unbounded searches with expected results over 2000, ' - 'please use the asf-search python module for long-lived searches or set `maxResults` to 2000 or less.' - '\nTo have SearchAPI automatically generate a python script for the equivalent search to your SearchAPI query ' + 'please use the asf-search python module for long-lived searches or set `maxResults` to 2000 or less. ' + 'To have SearchAPI automatically generate a python script for the equivalent search to your SearchAPI query ' 'set `output=python`' ) ) From 8038795af6bc427be9c801fcc4c0a7e36ada6fb7 Mon Sep 17 00:00:00 2001 From: SpicyGarlicAlbacoreRoll Date: Mon, 7 Jul 2025 11:26:28 -0800 Subject: [PATCH 4/5] fix: support count with unbounded results --- src/SearchAPI/application/asf_opts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SearchAPI/application/asf_opts.py b/src/SearchAPI/application/asf_opts.py index ab81ee1..6b27e3d 100644 --- a/src/SearchAPI/application/asf_opts.py +++ b/src/SearchAPI/application/asf_opts.py @@ -177,7 +177,7 @@ async def process_search_request(request: Request) -> SearchOptsModel: try: # we are no longer allowing unbounded searches - if query_opts.granule_list is None and query_opts.product_list is None and output != 'python': + if query_opts.granule_list is None and query_opts.product_list is None and output not in ['python', 'count']: if query_opts.maxResults is None: maxResults = asf.search_count(opts=query_opts) if maxResults > 2000: From 0a49ea25cf86d242d90ddb41082d186a4a6c2cba Mon Sep 17 00:00:00 2001 From: SpicyGarlicAlbacoreRoll Date: Mon, 7 Jul 2025 13:44:39 -0800 Subject: [PATCH 5/5] fix: baseline works again with search request size limit --- src/SearchAPI/application/asf_opts.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/SearchAPI/application/asf_opts.py b/src/SearchAPI/application/asf_opts.py index 6b27e3d..ccf7313 100644 --- a/src/SearchAPI/application/asf_opts.py +++ b/src/SearchAPI/application/asf_opts.py @@ -147,7 +147,7 @@ async def get_body(request: Request): return {} -async def process_search_request(request: Request) -> SearchOptsModel: +async def process_search_request(request: Request, is_baseline: bool = False) -> SearchOptsModel: """ Extracts the request's query+body params, returns ASFSearchOptions, request method, output format, and a dictionary of the merged request args wrapped in a pydantic model (SearchOptsModel) @@ -177,7 +177,12 @@ async def process_search_request(request: Request) -> SearchOptsModel: try: # we are no longer allowing unbounded searches - if query_opts.granule_list is None and query_opts.product_list is None and output not in ['python', 'count']: + if ( + query_opts.granule_list is None + and query_opts.product_list is None + and output not in ['python', 'count'] + and not is_baseline + ): if query_opts.maxResults is None: maxResults = asf.search_count(opts=query_opts) if maxResults > 2000: @@ -201,7 +206,7 @@ async def process_search_request(request: Request) -> SearchOptsModel: async def process_baseline_request(request: Request) -> BaselineSearchOptsModel: """Processes request to baseline endpoint""" - searchOpts = await process_search_request(request=request) + searchOpts = await process_search_request(request=request, is_baseline=True) reference = searchOpts.merged_args.get('reference') try: baselineSearchOpts = BaselineSearchOptsModel(**searchOpts.model_dump(), reference=reference)