eodag 3.10.0__py3-none-any.whl → 4.0.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. eodag/api/core.py +378 -419
  2. eodag/api/product/__init__.py +3 -3
  3. eodag/api/product/_product.py +68 -40
  4. eodag/api/product/drivers/__init__.py +3 -5
  5. eodag/api/product/drivers/base.py +1 -18
  6. eodag/api/product/metadata_mapping.py +151 -215
  7. eodag/api/search_result.py +13 -7
  8. eodag/cli.py +72 -395
  9. eodag/config.py +46 -50
  10. eodag/plugins/apis/base.py +2 -2
  11. eodag/plugins/apis/ecmwf.py +20 -21
  12. eodag/plugins/apis/usgs.py +37 -33
  13. eodag/plugins/authentication/base.py +1 -3
  14. eodag/plugins/crunch/filter_date.py +3 -3
  15. eodag/plugins/crunch/filter_latest_intersect.py +2 -2
  16. eodag/plugins/crunch/filter_latest_tpl_name.py +1 -1
  17. eodag/plugins/download/aws.py +45 -41
  18. eodag/plugins/download/base.py +13 -14
  19. eodag/plugins/download/http.py +65 -65
  20. eodag/plugins/manager.py +28 -29
  21. eodag/plugins/search/__init__.py +3 -4
  22. eodag/plugins/search/base.py +128 -77
  23. eodag/plugins/search/build_search_result.py +105 -107
  24. eodag/plugins/search/cop_marine.py +44 -47
  25. eodag/plugins/search/csw.py +33 -33
  26. eodag/plugins/search/qssearch.py +335 -354
  27. eodag/plugins/search/stac_list_assets.py +1 -1
  28. eodag/plugins/search/static_stac_search.py +31 -31
  29. eodag/resources/{product_types.yml → collections.yml} +2353 -2429
  30. eodag/resources/ext_collections.json +1 -1
  31. eodag/resources/providers.yml +2427 -2719
  32. eodag/resources/stac_provider.yml +46 -90
  33. eodag/types/queryables.py +55 -91
  34. eodag/types/search_args.py +1 -1
  35. eodag/utils/__init__.py +94 -21
  36. eodag/utils/exceptions.py +6 -6
  37. eodag/utils/free_text_search.py +3 -3
  38. {eodag-3.10.0.dist-info → eodag-4.0.0a1.dist-info}/METADATA +10 -87
  39. eodag-4.0.0a1.dist-info/RECORD +92 -0
  40. {eodag-3.10.0.dist-info → eodag-4.0.0a1.dist-info}/entry_points.txt +0 -4
  41. eodag/plugins/authentication/oauth.py +0 -60
  42. eodag/plugins/download/creodias_s3.py +0 -71
  43. eodag/plugins/download/s3rest.py +0 -351
  44. eodag/plugins/search/data_request_search.py +0 -565
  45. eodag/resources/stac.yml +0 -294
  46. eodag/resources/stac_api.yml +0 -2105
  47. eodag/rest/__init__.py +0 -24
  48. eodag/rest/cache.py +0 -70
  49. eodag/rest/config.py +0 -67
  50. eodag/rest/constants.py +0 -26
  51. eodag/rest/core.py +0 -764
  52. eodag/rest/errors.py +0 -210
  53. eodag/rest/server.py +0 -604
  54. eodag/rest/server.wsgi +0 -6
  55. eodag/rest/stac.py +0 -1032
  56. eodag/rest/templates/README +0 -1
  57. eodag/rest/types/__init__.py +0 -18
  58. eodag/rest/types/collections_search.py +0 -44
  59. eodag/rest/types/eodag_search.py +0 -386
  60. eodag/rest/types/queryables.py +0 -174
  61. eodag/rest/types/stac_search.py +0 -272
  62. eodag/rest/utils/__init__.py +0 -207
  63. eodag/rest/utils/cql_evaluate.py +0 -119
  64. eodag/rest/utils/rfc3339.py +0 -64
  65. eodag-3.10.0.dist-info/RECORD +0 -116
  66. {eodag-3.10.0.dist-info → eodag-4.0.0a1.dist-info}/WHEEL +0 -0
  67. {eodag-3.10.0.dist-info → eodag-4.0.0a1.dist-info}/licenses/LICENSE +0 -0
  68. {eodag-3.10.0.dist-info → eodag-4.0.0a1.dist-info}/top_level.txt +0 -0
eodag/rest/server.py DELETED
@@ -1,604 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # Copyright 2018, CS GROUP - France, https://www.csgroup.eu/
3
- #
4
- # This file is part of EODAG project
5
- # https://www.github.com/CS-SI/EODAG
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
- from __future__ import annotations
19
-
20
- import logging
21
- import os
22
- import re
23
- import warnings
24
- from contextlib import asynccontextmanager
25
- from importlib.metadata import version
26
- from json import JSONDecodeError
27
- from typing import TYPE_CHECKING, Any, AsyncGenerator, Awaitable, Callable, Optional
28
-
29
- from fastapi import APIRouter as FastAPIRouter
30
- from fastapi import FastAPI, HTTPException, Request
31
- from fastapi.concurrency import run_in_threadpool
32
- from fastapi.middleware.cors import CORSMiddleware
33
- from fastapi.openapi.utils import get_openapi
34
- from fastapi.responses import ORJSONResponse
35
- from pydantic import ValidationError as pydanticValidationError
36
- from pygeofilter.backends.cql2_json import to_cql2
37
- from pygeofilter.parsers.cql2_text import parse as parse_cql2_text
38
-
39
- from eodag.config import load_stac_api_config
40
- from eodag.rest.cache import init_cache
41
- from eodag.rest.core import (
42
- all_collections,
43
- download_stac_item,
44
- eodag_api_init,
45
- get_collection,
46
- get_detailled_collections_list,
47
- get_queryables,
48
- get_stac_api_version,
49
- get_stac_catalogs,
50
- get_stac_conformance,
51
- get_stac_extension_oseo,
52
- search_stac_items,
53
- )
54
- from eodag.rest.errors import add_exception_handlers
55
- from eodag.rest.types.queryables import QueryablesGetParams
56
- from eodag.rest.types.stac_search import SearchPostRequest, sortby2list
57
- from eodag.rest.utils import (
58
- LIVENESS_PROBE_PATH,
59
- format_pydantic_error,
60
- str2json,
61
- str2list,
62
- )
63
- from eodag.utils import parse_header, update_nested_dict
64
-
65
- if TYPE_CHECKING:
66
- from fastapi.types import DecoratedCallable
67
- from requests import Response
68
-
69
- from starlette.responses import Response as StarletteResponse
70
-
71
- warnings.warn(
72
- "The module `eodag.rest.server` is deprecated since v3.9.0 and will be removed in a future version. "
73
- "The STAC server has moved to https://github.com/CS-SI/stac-fastapi-eodag",
74
- category=DeprecationWarning,
75
- stacklevel=2,
76
- )
77
-
78
- logger = logging.getLogger("eodag.rest.server")
79
-
80
-
81
- class APIRouter(FastAPIRouter):
82
- """API router"""
83
-
84
- def api_route(
85
- self, path: str, *, include_in_schema: bool = True, **kwargs: Any
86
- ) -> Callable[[DecoratedCallable], DecoratedCallable]:
87
- """Creates API route decorator"""
88
- if path == "/":
89
- return super().api_route(
90
- path, include_in_schema=include_in_schema, **kwargs
91
- )
92
-
93
- if path.endswith("/"):
94
- path = path[:-1]
95
- add_path = super().api_route(
96
- path, include_in_schema=include_in_schema, **kwargs
97
- )
98
-
99
- alternate_path = path + "/"
100
- add_alternate_path = super().api_route(
101
- alternate_path, include_in_schema=False, **kwargs
102
- )
103
-
104
- def decorator(func: DecoratedCallable) -> DecoratedCallable:
105
- add_alternate_path(func)
106
- return add_path(func)
107
-
108
- return decorator
109
-
110
-
111
- router = APIRouter()
112
-
113
-
114
- @asynccontextmanager
115
- async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
116
- """API init and tear-down"""
117
- eodag_api_init()
118
- init_cache(app)
119
- yield
120
-
121
-
122
- app = FastAPI(lifespan=lifespan, title="EODAG", docs_url="/api.html")
123
-
124
- # conf from resources/stac_api.yml
125
- stac_api_config = load_stac_api_config()
126
-
127
-
128
- @router.api_route(
129
- methods=["GET", "HEAD"],
130
- path=LIVENESS_PROBE_PATH,
131
- include_in_schema=False,
132
- status_code=200,
133
- )
134
- async def liveness_probe(request: Request) -> dict[str, bool]:
135
- "Endpoint meant to be used as liveness probe by deployment platforms"
136
- return {"success": True}
137
-
138
-
139
- @router.api_route(
140
- methods=["GET", "HEAD"], path="/api", tags=["Capabilities"], include_in_schema=False
141
- )
142
- async def eodag_openapi(request: Request) -> dict[str, Any]:
143
- """Customized openapi"""
144
- logger.debug("URL: /api")
145
- if app.openapi_schema:
146
- return app.openapi_schema
147
-
148
- root_catalog = await get_stac_catalogs(request=request, url="")
149
- stac_api_version = get_stac_api_version()
150
-
151
- openapi_schema = get_openapi(
152
- title=f"{root_catalog['title']} / eodag",
153
- version=version("eodag"),
154
- routes=app.routes,
155
- )
156
-
157
- # stac_api_config
158
- update_nested_dict(openapi_schema["paths"], stac_api_config["paths"])
159
- try:
160
- update_nested_dict(openapi_schema["components"], stac_api_config["components"])
161
- except KeyError:
162
- openapi_schema["components"] = stac_api_config["components"]
163
- openapi_schema["tags"] = stac_api_config["tags"]
164
-
165
- detailled_collections_list = get_detailled_collections_list()
166
-
167
- openapi_schema["info"]["description"] = (
168
- root_catalog["description"]
169
- + f" (stac-api-spec {stac_api_version})"
170
- + "<details><summary>Available collections / product types</summary>"
171
- + "".join(
172
- [
173
- f"[{pt['ID']}](/collections/{pt['ID']} '{pt['title']}') - "
174
- for pt in detailled_collections_list
175
- ]
176
- )[:-2]
177
- + "</details>"
178
- )
179
-
180
- app.openapi_schema = openapi_schema
181
- return app.openapi_schema
182
-
183
-
184
- app.__setattr__("openapi", eodag_openapi)
185
-
186
- # Cross-Origin Resource Sharing
187
- allowed_origins = os.getenv("EODAG_CORS_ALLOWED_ORIGINS")
188
- allowed_origins_list = allowed_origins.split(",") if allowed_origins else []
189
- app.add_middleware(
190
- CORSMiddleware,
191
- allow_origins=allowed_origins_list,
192
- allow_credentials=True,
193
- allow_methods=["*"],
194
- allow_headers=["*"],
195
- )
196
-
197
- add_exception_handlers(app)
198
-
199
-
200
- @app.middleware("http")
201
- async def forward_middleware(
202
- request: Request, call_next: Callable[[Request], Awaitable[Response]]
203
- ) -> Response:
204
- """Middleware that handles forward headers and sets request.state.url*"""
205
-
206
- forwarded_host = request.headers.get("x-forwarded-host")
207
- forwarded_proto = request.headers.get("x-forwarded-proto")
208
-
209
- if "forwarded" in request.headers:
210
- header_forwarded = parse_header(request.headers["forwarded"])
211
- forwarded_host = str(header_forwarded.get_param("host", None)) or forwarded_host
212
- forwarded_proto = (
213
- str(header_forwarded.get_param("proto", None)) or forwarded_proto
214
- )
215
-
216
- request.state.url_root = f"{forwarded_proto or request.url.scheme}://{forwarded_host or request.url.netloc}"
217
- request.state.url = f"{request.state.url_root}{request.url.path}"
218
-
219
- response = await call_next(request)
220
- return response
221
-
222
-
223
- @router.api_route(methods=["GET", "HEAD"], path="/", tags=["Capabilities"])
224
- async def catalogs_root(request: Request) -> ORJSONResponse:
225
- """STAC catalogs root"""
226
- logger.info(f"{request.method} {request.state.url}")
227
-
228
- response = await get_stac_catalogs(
229
- request=request,
230
- url=request.state.url,
231
- provider=request.query_params.get("provider"),
232
- )
233
-
234
- return ORJSONResponse(response)
235
-
236
-
237
- @router.api_route(methods=["GET", "HEAD"], path="/conformance", tags=["Capabilities"])
238
- def conformance(request: Request) -> ORJSONResponse:
239
- """STAC conformance"""
240
- logger.info(f"{request.method} {request.state.url}")
241
- response = get_stac_conformance()
242
-
243
- return ORJSONResponse(response)
244
-
245
-
246
- @router.api_route(
247
- methods=["GET", "HEAD"],
248
- path="/extensions/oseo/json-schema/schema.json",
249
- include_in_schema=False,
250
- )
251
- def stac_extension_oseo(request: Request) -> ORJSONResponse:
252
- """STAC OGC / OpenSearch extension for EO"""
253
- logger.info(f"{request.method} {request.state.url}")
254
- response = get_stac_extension_oseo(url=request.state.url)
255
-
256
- return ORJSONResponse(response)
257
-
258
-
259
- @router.api_route(
260
- methods=["GET", "HEAD"],
261
- path="/collections/{collection_id}/items/{item_id}/download",
262
- tags=["Data"],
263
- include_in_schema=False,
264
- )
265
- def stac_collections_item_download(
266
- collection_id: str, item_id: str, request: Request
267
- ) -> StarletteResponse:
268
- """STAC collection item download"""
269
- logger.info(f"{request.method} {request.state.url}")
270
-
271
- arguments = dict(request.query_params)
272
- provider = arguments.pop("provider", None)
273
-
274
- return download_stac_item(
275
- request=request,
276
- collection_id=collection_id,
277
- item_id=item_id,
278
- provider=provider,
279
- **arguments,
280
- )
281
-
282
-
283
- @router.api_route(
284
- methods=["GET", "HEAD"],
285
- path="/collections/{collection_id}/items/{item_id}/download/{asset}",
286
- tags=["Data"],
287
- include_in_schema=False,
288
- )
289
- def stac_collections_item_download_asset(
290
- collection_id: str, item_id: str, asset: str, request: Request
291
- ):
292
- """STAC collection item asset download"""
293
- logger.info(f"{request.method} {request.state.url}")
294
-
295
- arguments = dict(request.query_params)
296
- provider = arguments.pop("provider", None)
297
-
298
- return download_stac_item(
299
- request=request,
300
- collection_id=collection_id,
301
- item_id=item_id,
302
- provider=provider,
303
- asset=asset,
304
- )
305
-
306
-
307
- @router.api_route(
308
- methods=["GET", "HEAD"],
309
- path="/collections/{collection_id}/items/{item_id}",
310
- tags=["Data"],
311
- include_in_schema=False,
312
- )
313
- def stac_collections_item(
314
- collection_id: str, item_id: str, request: Request, provider: Optional[str] = None
315
- ) -> ORJSONResponse:
316
- """STAC collection item by id"""
317
- logger.info(f"{request.method} {request.state.url}")
318
-
319
- search_request = SearchPostRequest(
320
- provider=provider, ids=[item_id], collections=[collection_id], limit=1
321
- )
322
-
323
- item_collection = search_stac_items(request, search_request)
324
-
325
- if not item_collection["features"]:
326
- raise HTTPException(
327
- status_code=404,
328
- detail=f"Item {item_id} in Collection {collection_id} does not exist.",
329
- )
330
-
331
- return ORJSONResponse(item_collection["features"][0])
332
-
333
-
334
- @router.api_route(
335
- methods=["GET", "HEAD"],
336
- path="/collections/{collection_id}/items",
337
- tags=["Data"],
338
- include_in_schema=False,
339
- )
340
- def stac_collections_items(
341
- collection_id: str,
342
- request: Request,
343
- provider: Optional[str] = None,
344
- bbox: Optional[str] = None,
345
- datetime: Optional[str] = None,
346
- limit: Optional[int] = None,
347
- query: Optional[str] = None,
348
- page: Optional[int] = None,
349
- sortby: Optional[str] = None,
350
- filter: Optional[str] = None,
351
- filter_lang: Optional[str] = "cql2-text",
352
- crunch: Optional[str] = None,
353
- ) -> ORJSONResponse:
354
- """Fetch collection's features"""
355
-
356
- return get_search(
357
- request=request,
358
- provider=provider,
359
- collections=collection_id,
360
- bbox=bbox,
361
- datetime=datetime,
362
- limit=limit,
363
- query=query,
364
- page=page,
365
- sortby=sortby,
366
- filter=filter,
367
- filter_lang=filter_lang,
368
- crunch=crunch,
369
- )
370
-
371
-
372
- @router.api_route(
373
- methods=["GET", "HEAD"],
374
- path="/collections/{collection_id}/queryables",
375
- tags=["Capabilities"],
376
- include_in_schema=False,
377
- response_model_exclude_none=True,
378
- )
379
- async def list_collection_queryables(
380
- request: Request,
381
- collection_id: str,
382
- ) -> ORJSONResponse:
383
- """Returns the list of queryable properties for a specific collection.
384
-
385
- This endpoint provides a list of properties that can be used as filters when querying
386
- the specified collection. These properties correspond to characteristics of the data
387
- that can be filtered using comparison operators.
388
-
389
- :param request: The incoming request object.
390
- :param collection_id: The identifier of the collection for which to retrieve queryable properties.
391
- :returns: A json object containing the list of available queryable properties for the specified collection.
392
- """
393
- logger.info(f"{request.method} {request.state.url}")
394
-
395
- params: dict[str, list[Any]] = {}
396
- for k, v in request.query_params.multi_items():
397
- params.setdefault(k, []).append(v)
398
-
399
- provider = params.pop("provider", [None])[0]
400
- datetime = params.pop("datetime", [None])[0]
401
-
402
- queryables = await get_queryables(
403
- request,
404
- QueryablesGetParams.model_validate(
405
- {
406
- **params,
407
- **{
408
- "collection": collection_id,
409
- "datetime": datetime,
410
- },
411
- }
412
- ),
413
- provider=provider,
414
- )
415
-
416
- return ORJSONResponse(queryables)
417
-
418
-
419
- @router.api_route(
420
- methods=["GET", "HEAD"],
421
- path="/collections/{collection_id}",
422
- tags=["Capabilities"],
423
- include_in_schema=False,
424
- )
425
- async def collection_by_id(
426
- collection_id: str, request: Request, provider: Optional[str] = None
427
- ) -> ORJSONResponse:
428
- """STAC collection by id"""
429
- logger.info(f"{request.method} {request.state.url}")
430
-
431
- response = await get_collection(
432
- request=request,
433
- collection_id=collection_id,
434
- provider=provider,
435
- )
436
-
437
- return ORJSONResponse(response)
438
-
439
-
440
- @router.api_route(
441
- methods=["GET", "HEAD"],
442
- path="/collections",
443
- tags=["Capabilities"],
444
- include_in_schema=False,
445
- )
446
- async def collections(
447
- request: Request,
448
- provider: Optional[str] = None,
449
- q: Optional[str] = None,
450
- bbox: Optional[str] = None,
451
- platform: Optional[str] = None,
452
- instrument: Optional[str] = None,
453
- constellation: Optional[str] = None,
454
- datetime: Optional[str] = None,
455
- ) -> ORJSONResponse:
456
- """STAC collections
457
-
458
- Can be filtered using parameters: instrument, platform, platformSerialIdentifier, sensorType,
459
- processingLevel
460
- """
461
- logger.info(f"{request.method} {request.state.url}")
462
-
463
- collections = await all_collections(
464
- request, provider, q, platform, instrument, constellation, datetime, bbox
465
- )
466
-
467
- return ORJSONResponse(collections)
468
-
469
-
470
- @router.api_route(
471
- methods=["GET", "HEAD"],
472
- path="/queryables",
473
- tags=["Capabilities"],
474
- response_model_exclude_none=True,
475
- include_in_schema=False,
476
- )
477
- async def list_queryables(request: Request) -> ORJSONResponse:
478
- """Returns the list of terms available for use when writing filter expressions.
479
-
480
- This endpoint provides a list of terms that can be used as filters when querying
481
- the data. These terms correspond to properties that can be filtered using comparison
482
- operators.
483
-
484
- :param request: The incoming request object.
485
- :returns: A json object containing the list of available queryable terms.
486
- """
487
- logger.info(f"{request.method} {request.state.url}")
488
- additional_params = dict(request.query_params.items())
489
- provider = additional_params.pop("provider", None)
490
- queryables = await get_queryables(
491
- request, QueryablesGetParams(**additional_params), provider=provider
492
- )
493
-
494
- return ORJSONResponse(queryables)
495
-
496
-
497
- @router.api_route(
498
- methods=["GET", "HEAD"],
499
- path="/search",
500
- tags=["STAC"],
501
- include_in_schema=False,
502
- )
503
- def get_search(
504
- request: Request,
505
- provider: Optional[str] = None,
506
- collections: Optional[str] = None,
507
- ids: Optional[str] = None,
508
- bbox: Optional[str] = None,
509
- datetime: Optional[str] = None,
510
- intersects: Optional[str] = None,
511
- limit: Optional[int] = None,
512
- query: Optional[str] = None,
513
- page: Optional[int] = None,
514
- sortby: Optional[str] = None,
515
- filter: Optional[str] = None, # pylint: disable=redefined-builtin
516
- filter_lang: Optional[str] = "cql2-text",
517
- crunch: Optional[str] = None,
518
- ) -> ORJSONResponse:
519
- """Handler for GET /search"""
520
- logger.info(f"{request.method} {request.state.url}")
521
-
522
- query_params = str(request.query_params)
523
-
524
- # Kludgy fix because using factory does not allow alias for filter-lang
525
- if filter_lang is None:
526
- match = re.search(r"filter-lang=([a-z0-9-]+)", query_params, re.IGNORECASE)
527
- if match:
528
- filter_lang = match.group(1)
529
-
530
- base_args = {
531
- "provider": provider,
532
- "collections": str2list(collections),
533
- "ids": str2list(ids),
534
- "datetime": datetime,
535
- "bbox": str2list(bbox),
536
- "intersects": str2json("intersects", intersects),
537
- "limit": limit,
538
- "query": str2json("query", query),
539
- "page": page,
540
- "sortby": sortby2list(sortby),
541
- "crunch": crunch,
542
- }
543
-
544
- if filter:
545
- if filter_lang == "cql2-text":
546
- ast = parse_cql2_text(filter)
547
- base_args["filter"] = str2json("filter", to_cql2(ast)) # type: ignore
548
- base_args["filter-lang"] = "cql2-json"
549
- elif filter_lang == "cql-json":
550
- base_args["filter"] = str2json(filter)
551
-
552
- clean = {k: v for k, v in base_args.items() if v is not None and v != []}
553
-
554
- try:
555
- search_request = SearchPostRequest.model_validate(clean)
556
- except pydanticValidationError as e:
557
- raise HTTPException(status_code=400, detail=format_pydantic_error(e)) from e
558
-
559
- response = search_stac_items(
560
- request=request,
561
- search_request=search_request,
562
- )
563
- return ORJSONResponse(content=response, media_type="application/json")
564
-
565
-
566
- @router.api_route(
567
- methods=["POST", "HEAD"],
568
- path="/search",
569
- tags=["STAC"],
570
- include_in_schema=False,
571
- )
572
- async def post_search(request: Request) -> ORJSONResponse:
573
- """STAC post search"""
574
- logger.info(f"{request.method} {request.state.url}")
575
-
576
- content_type = request.headers.get("Content-Type")
577
-
578
- if content_type is None:
579
- raise HTTPException(status_code=400, detail="No Content-Type provided")
580
- if content_type != "application/json":
581
- raise HTTPException(status_code=400, detail="Content-Type not supported")
582
-
583
- try:
584
- payload = await request.json()
585
- except JSONDecodeError as e:
586
- raise HTTPException(status_code=400, detail="Invalid JSON data") from e
587
-
588
- try:
589
- search_request = SearchPostRequest.model_validate(payload)
590
- except pydanticValidationError as e:
591
- raise HTTPException(status_code=400, detail=format_pydantic_error(e)) from e
592
-
593
- logger.debug("Body: %s", search_request.model_dump(exclude_none=True))
594
-
595
- response = await run_in_threadpool(
596
- search_stac_items,
597
- request,
598
- search_request,
599
- )
600
-
601
- return ORJSONResponse(content=response, media_type="application/json")
602
-
603
-
604
- app.include_router(router)
eodag/rest/server.wsgi DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env python
2
-
3
- from eodag.rest.server import app as application # noqa
4
- from eodag.utils.logging import setup_logging
5
-
6
- setup_logging(verbose=3)