diff --git a/infrastructure/app.py b/infrastructure/app.py index 27ce1d6..986071d 100644 --- a/infrastructure/app.py +++ b/infrastructure/app.py @@ -175,12 +175,12 @@ def __init__( path=os.path.abspath(context_dir), file="infrastructure/dockerfiles/Dockerfile.raster", build_args={ - "PYTHON_VERSION": "3.11", + "PYTHON_VERSION": "3.12", }, platform="linux/amd64", ), "handler": "handler.handler", - "runtime": aws_lambda.Runtime.PYTHON_3_11, + "runtime": aws_lambda.Runtime.PYTHON_3_12, }, ) @@ -224,12 +224,12 @@ def __init__( path=os.path.abspath(context_dir), file="infrastructure/dockerfiles/Dockerfile.stac", build_args={ - "PYTHON_VERSION": "3.11", + "PYTHON_VERSION": "3.12", }, platform="linux/amd64", ), "handler": "handler.handler", - "runtime": aws_lambda.Runtime.PYTHON_3_11, + "runtime": aws_lambda.Runtime.PYTHON_3_12, }, ) @@ -271,12 +271,12 @@ def __init__( path=os.path.abspath(context_dir), file="infrastructure/dockerfiles/Dockerfile.vector", build_args={ - "PYTHON_VERSION": "3.11", + "PYTHON_VERSION": "3.12", }, platform="linux/amd64", ), "handler": "handler.handler", - "runtime": aws_lambda.Runtime.PYTHON_3_11, + "runtime": aws_lambda.Runtime.PYTHON_3_12, }, ) diff --git a/infrastructure/dockerfiles/Dockerfile.raster b/infrastructure/dockerfiles/Dockerfile.raster index 16c16c2..1611a4f 100644 --- a/infrastructure/dockerfiles/Dockerfile.raster +++ b/infrastructure/dockerfiles/Dockerfile.raster @@ -1,4 +1,4 @@ -ARG PYTHON_VERSION=3.11 +ARG PYTHON_VERSION=3.12 FROM public.ecr.aws/lambda/python:${PYTHON_VERSION} diff --git a/infrastructure/dockerfiles/Dockerfile.stac b/infrastructure/dockerfiles/Dockerfile.stac index def8886..c219abc 100644 --- a/infrastructure/dockerfiles/Dockerfile.stac +++ b/infrastructure/dockerfiles/Dockerfile.stac @@ -1,4 +1,4 @@ -ARG PYTHON_VERSION=3.11 +ARG PYTHON_VERSION=3.12 FROM public.ecr.aws/lambda/python:${PYTHON_VERSION} diff --git a/infrastructure/dockerfiles/Dockerfile.vector b/infrastructure/dockerfiles/Dockerfile.vector index 176d37f..1e1ee18 100644 --- a/infrastructure/dockerfiles/Dockerfile.vector +++ b/infrastructure/dockerfiles/Dockerfile.vector @@ -1,4 +1,4 @@ -ARG PYTHON_VERSION=3.11 +ARG PYTHON_VERSION=3.12 FROM public.ecr.aws/lambda/python:${PYTHON_VERSION} diff --git a/infrastructure/handlers/stac_handler.py b/infrastructure/handlers/stac_handler.py index fd6245d..b7f763e 100644 --- a/infrastructure/handlers/stac_handler.py +++ b/infrastructure/handlers/stac_handler.py @@ -5,18 +5,24 @@ import os from eoapi.stac.app import app -from eoapi.stac.config import PostgresSettings +from eoapi.stac.config import PostgresSettings, Settings from mangum import Mangum from stac_fastapi.pgstac.db import connect_to_db logging.getLogger("mangum.lifespan").setLevel(logging.ERROR) logging.getLogger("mangum.http").setLevel(logging.ERROR) +settings = Settings() + @app.on_event("startup") async def startup_event() -> None: """Connect to database on startup.""" - await connect_to_db(app, postgres_settings=PostgresSettings()) + await connect_to_db( + app, + postgres_settings=PostgresSettings(), + add_write_connection_pool=settings.enable_transaction, + ) handler = Mangum(app, lifespan="off") diff --git a/runtimes/eoapi/raster/eoapi/raster/app.py b/runtimes/eoapi/raster/eoapi/raster/app.py index 95acc00..40e66c0 100644 --- a/runtimes/eoapi/raster/eoapi/raster/app.py +++ b/runtimes/eoapi/raster/eoapi/raster/app.py @@ -1,9 +1,8 @@ """eoAPI Raster application.""" import logging -import re from contextlib import asynccontextmanager -from typing import Dict +from typing import Annotated, Dict, Literal, Optional import jinja2 import pystac @@ -28,6 +27,9 @@ TMSFactory, ) from titiler.core.middleware import CacheControlMiddleware +from titiler.core.models.OGC import Conformance, Landing +from titiler.core.resources.enums import MediaType +from titiler.core.utils import accept_media_type, create_html_response, update_openapi from titiler.extensions import cogViewerExtension from titiler.mosaic.errors import MOSAIC_STATUS_CODES from titiler.pgstac import __version__ as titiler_pgstac_version @@ -77,11 +79,13 @@ logger.debug("Loading jinja2 templates...") jinja2_env = jinja2.Environment( + autoescape=jinja2.select_autoescape(["html", "xml"]), loader=jinja2.ChoiceLoader( [ jinja2.PackageLoader(__package__, "templates"), + jinja2.PackageLoader("titiler.core", "templates"), ] - ) + ), ) templates = Jinja2Templates(env=jinja2_env) @@ -112,6 +116,10 @@ async def lifespan(app: FastAPI): "usePkceWithAuthorizationCodeGrant": auth_settings.use_pkce, }, ) + +# Fix OpenAPI response header for OGC Common compatibility +update_openapi(app) + add_exception_handlers(app, DEFAULT_STATUS_CODES) add_exception_handlers(app, MOSAIC_STATUS_CODES) @@ -140,6 +148,14 @@ async def lifespan(app: FastAPI): }, ) +TITILER_CONFORMS_TO = { + "http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/core", + "http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/landing-page", + "http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/oas30", + "http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/html", + "http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/json", +} + ############################################################################### # `Secret` endpoint for mosaic builder. Do not need to be public (in the OpenAPI docs) @@ -164,6 +180,7 @@ async def list_collection(request: Request): extensions=[ searchInfoExtension(), ], + templates=templates, ) app.include_router( searches.router, tags=["STAC Search"], prefix="/searches/{search_id}" @@ -176,16 +193,16 @@ async def list_collection(request: Request): searches.layer_dependency, searches.dataset_dependency, searches.pixel_selection_dependency, - searches.tile_dependency, searches.process_dependency, searches.render_dependency, - searches.pgstac_dependency, + searches.assets_accessor_dependency, searches.reader_dependency, searches.backend_dependency, ], tags=["STAC Search"], ) add_search_list_route(app, prefix="/searches", tags=["STAC Search"]) +TITILER_CONFORMS_TO.update(searches.conforms_to) @app.get("/searches/builder", response_class=HTMLResponse, tags=["STAC Search"]) @@ -218,11 +235,12 @@ async def virtual_mosaic_builder(request: Request): extensions=[ searchInfoExtension(), ], + templates=templates, ) app.include_router( collection.router, tags=["STAC Collection"], prefix="/collections/{collection_id}" ) - +TITILER_CONFORMS_TO.update(collection.conforms_to) ############################################################################### # STAC Item Endpoints @@ -231,11 +249,7 @@ async def virtual_mosaic_builder(request: Request): path_dependency=ItemIdParams, router_prefix="/collections/{collection_id}/items/{item_id}", add_viewer=True, -) -app.include_router( - stac.router, - tags=["STAC Item"], - prefix="/collections/{collection_id}/items/{item_id}", + templates=templates, ) @@ -260,6 +274,7 @@ def viewer(request: Request, item: pystac.Item = Depends(stac.path_dependency)): tags=["STAC Item"], prefix="/collections/{collection_id}/items/{item_id}", ) +TITILER_CONFORMS_TO.update(stac.conforms_to) ############################################################################### @@ -268,12 +283,15 @@ def viewer(request: Request, item: pystac.Item = Depends(stac.path_dependency)): path_dependency=AssetIdParams, router_prefix="/collections/{collection_id}/items/{item_id}/assets/{asset_id}", add_viewer=True, + templates=templates, ) app.include_router( asset.router, tags=["STAC Asset"], prefix="/collections/{collection_id}/items/{item_id}/assets/{asset_id}", ) +TITILER_CONFORMS_TO.update(asset.conforms_to) + ############################################################################### # External Dataset Endpoints @@ -282,30 +300,32 @@ def viewer(request: Request, item: pystac.Item = Depends(stac.path_dependency)): extensions=[ cogViewerExtension(), ], + templates=templates, ) app.include_router( external_cog.router, tags=["External Dataset"], prefix="/external", ) +TITILER_CONFORMS_TO.update(external_cog.conforms_to) ############################################################################### # Tiling Schemes Endpoints -tms = TMSFactory() +tms = TMSFactory(templates=templates) app.include_router(tms.router, tags=["Tiling Schemes"]) +TITILER_CONFORMS_TO.update(tms.conforms_to) ############################################################################### # Algorithms Endpoints -algorithms = AlgorithmFactory() +algorithms = AlgorithmFactory(templates=templates) app.include_router(algorithms.router, tags=["Algorithms"]) +TITILER_CONFORMS_TO.update(algorithms.conforms_to) ############################################################################### # Colormaps endpoints -cmaps = ColorMapFactory() -app.include_router( - cmaps.router, - tags=["ColorMaps"], -) +cmaps = ColorMapFactory(templates=templates) +app.include_router(cmaps.router, tags=["ColorMaps"]) +TITILER_CONFORMS_TO.update(cmaps.conforms_to) ############################################################################### @@ -341,13 +361,30 @@ def ping( # Landing page Endpoint @app.get( "/", - response_class=HTMLResponse, - tags=["Landing"], + response_model=Landing, + response_model_exclude_none=True, + responses={ + 200: { + "content": { + "text/html": {}, + "application/json": {}, + } + }, + }, + tags=["OGC Common"], ) -def landing(request: Request): - """Get landing page.""" +def landing( + request: Request, + f: Annotated[ + Optional[Literal["html", "json"]], + Query( + description="Response MediaType. Defaults to endpoint's default or value defined in `accept` header." + ), + ] = None, +): + """TiTiler landing page.""" data = { - "title": settings.name or "eoAPI-raster", + "title": settings.name or "eoAPI-Raster", "links": [ { "title": "Landing page", @@ -367,6 +404,12 @@ def landing(request: Request): "type": "text/html", "rel": "service-doc", }, + { + "title": "Conformance Declaration", + "href": str(request.url_for("conformance")), + "type": "text/html", + "rel": "http://www.opengis.net/def/rel/ogc/1.0/conformance", + }, { "title": "eoAPI Virtual Mosaic list (JSON)", "href": str(app.url_path_for("list_searches")), @@ -419,42 +462,112 @@ def landing(request: Request): "rel": "data", "templated": True, }, + { + "title": "List of Available TileMatrixSets", + "href": str(request.url_for("tilematrixsets")), + "type": "application/json", + "rel": "http://www.opengis.net/def/rel/ogc/1.0/tiling-schemes", + }, + { + "title": "List of Available Algorithms", + "href": str(request.url_for("available_algorithms")), + "type": "application/json", + "rel": "data", + }, + { + "title": "List of Available ColorMaps", + "href": str(request.url_for("available_colormaps")), + "type": "application/json", + "rel": "data", + }, + { + "title": "TiTiler-PgSTAC Documentation (external link)", + "href": "https://stac-utils.github.io/titiler-pgstac/", + "type": "text/html", + "rel": "doc", + }, + { + "title": "TiTiler-PgSTAC source code (external link)", + "href": "https://github.com/stac-utils/titiler-pgstac", + "type": "text/html", + "rel": "doc", + }, ], } - urlpath = request.url.path - if root_path := request.app.root_path: - urlpath = re.sub(r"^" + root_path, "", urlpath) - crumbs = [] - baseurl = str(request.base_url).rstrip("/") - - crumbpath = str(baseurl) - for crumb in urlpath.split("/"): - crumbpath = crumbpath.rstrip("/") - part = crumb - if part is None or part == "": - part = "Home" - crumbpath += f"/{crumb}" - crumbs.append({"url": crumbpath.rstrip("/"), "part": part.capitalize()}) + if f: + output_type = MediaType[f] + else: + accepted_media = [MediaType.html, MediaType.json] + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MediaType.json + ) - return templates.TemplateResponse( - request, - name="landing.html", - context={ - "request": request, - "response": data, - "template": { - "api_root": baseurl, - "params": request.query_params, - "title": "TiTiler-PgSTAC", - }, - "crumbs": crumbs, - "url": str(request.url), - "baseurl": baseurl, - "urlpath": str(request.url.path), - "urlparams": str(request.url.query), + if output_type == MediaType.html: + return create_html_response( + request, + data, + "landing", + title="eoAPI-raster", + templates=templates, + ) + + return data + + +@app.get( + "/conformance", + response_model=Conformance, + response_model_exclude_none=True, + responses={ + 200: { + "content": { + "text/html": {}, + "application/json": {}, + } }, - ) + }, + tags=["OGC Common"], +) +def conformance( + request: Request, + f: Annotated[ + Optional[Literal["html", "json"]], + Query( + description="Response MediaType. Defaults to endpoint's default or value defined in `accept` header." + ), + ] = None, +): + """Conformance classes. + + Called with `GET /conformance`. + + Returns: + Conformance classes which the server conforms to. + + """ + data = {"conformsTo": sorted(TITILER_CONFORMS_TO)} + + if f: + output_type = MediaType[f] + else: + accepted_media = [MediaType.html, MediaType.json] + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MediaType.json + ) + + if output_type == MediaType.html: + return create_html_response( + request, + data, + "conformance", + title="Conformance", + templates=templates, + ) + + return data # Add dependencies to routes diff --git a/runtimes/eoapi/raster/eoapi/raster/templates/conformance.html b/runtimes/eoapi/raster/eoapi/raster/templates/conformance.html new file mode 100644 index 0000000..0471b36 --- /dev/null +++ b/runtimes/eoapi/raster/eoapi/raster/templates/conformance.html @@ -0,0 +1,32 @@ +{% include "header.html" %} +{% if params %} + {% set urlq = url + '?' + params + '&' %} + {% else %} + {% set urlq = url + '?' %} +{% endif %} + + + +

{{ template.title }}

+ +

This API implements the conformance classes from standards and community specifications that are listed below.

+ +

Links

+ + +{% include "footer.html" %} diff --git a/runtimes/eoapi/raster/eoapi/raster/templates/footer.html b/runtimes/eoapi/raster/eoapi/raster/templates/footer.html new file mode 100644 index 0000000..0519bcd --- /dev/null +++ b/runtimes/eoapi/raster/eoapi/raster/templates/footer.html @@ -0,0 +1,16 @@ + {% include "debug.html" %} + + + +
+
+ Created by +
+ + Development Seed + +
+
+ + diff --git a/runtimes/eoapi/raster/eoapi/raster/templates/header.html b/runtimes/eoapi/raster/eoapi/raster/templates/header.html new file mode 100644 index 0000000..6d1dbec --- /dev/null +++ b/runtimes/eoapi/raster/eoapi/raster/templates/header.html @@ -0,0 +1,43 @@ + + + + {{ template.title }} + + + + + + + + + + + + +
diff --git a/runtimes/eoapi/raster/eoapi/raster/templates/landing.html b/runtimes/eoapi/raster/eoapi/raster/templates/landing.html index a71d3fa..6458ea0 100644 --- a/runtimes/eoapi/raster/eoapi/raster/templates/landing.html +++ b/runtimes/eoapi/raster/eoapi/raster/templates/landing.html @@ -1,46 +1,9 @@ - - - - {{ template.title }} - - - - - - - - - - - - -
+{% include "header.html" %} +{% if params %} + {% set urlq = url + '?' + params + '&' %} + {% else %} + {% set urlq = url + '?' %} +{% endif %} @@ -61,12 +26,8 @@

{{ response.title }}

Links

- -
- - - +{% include "footer.html" %} diff --git a/runtimes/eoapi/raster/eoapi/raster/templates/map.html b/runtimes/eoapi/raster/eoapi/raster/templates/map.html new file mode 100644 index 0000000..c765bf0 --- /dev/null +++ b/runtimes/eoapi/raster/eoapi/raster/templates/map.html @@ -0,0 +1,305 @@ + + + + + eoAPI Raster - Map Viewer + + + + + + + + +
+
+
+
+ + Development Seed + +
+
+ + + diff --git a/runtimes/eoapi/raster/pyproject.toml b/runtimes/eoapi/raster/pyproject.toml index faae65d..bfb7720 100644 --- a/runtimes/eoapi/raster/pyproject.toml +++ b/runtimes/eoapi/raster/pyproject.toml @@ -2,7 +2,7 @@ name = "eoapi.raster" description = "Raster service for eoAPI." readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" authors = [ {name = "Vincent Sarago", email = "vincent@developmentseed.com"}, ] @@ -11,7 +11,6 @@ classifiers = [ "Intended Audience :: Information Technology", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -20,10 +19,9 @@ classifiers = [ ] dynamic = ["version"] dependencies = [ - "titiler.pgstac==1.7.1", - "titiler.extensions", - "starlette-cramjam>=0.4,<0.5", - "importlib_resources>=1.1.0;python_version<'3.9'", + "titiler.pgstac==1.9.0", + "titiler.extensions==0.24.0", + "starlette-cramjam>=0.4,<0.6", "boto3", "eoapi.auth-utils>=0.2.0", ] diff --git a/runtimes/eoapi/stac/eoapi/stac/app.py b/runtimes/eoapi/stac/eoapi/stac/app.py index 49f3010..35a0b64 100644 --- a/runtimes/eoapi/stac/eoapi/stac/app.py +++ b/runtimes/eoapi/stac/eoapi/stac/app.py @@ -5,7 +5,7 @@ import jinja2 from eoapi.auth_utils import OpenIdConnectAuth, OpenIdConnectSettings -from fastapi import FastAPI +from fastapi import APIRouter, FastAPI from stac_fastapi.api.models import ( CollectionUri, ItemCollectionUri, @@ -173,7 +173,11 @@ @asynccontextmanager async def lifespan(app: FastAPI): """FastAPI Lifespan.""" - await connect_to_db(app, postgres_settings=pg_settings) + await connect_to_db( + app, + postgres_settings=pg_settings, + add_write_connection_pool=settings.enable_transaction, + ) yield await close_db_connection(app) @@ -197,6 +201,7 @@ async def lifespan(app: FastAPI): description=settings.stac_fastapi_description, version=eoapi_devseed_version, lifespan=lifespan, + root_path=settings.root_path, openapi_url=settings.openapi_url, docs_url=settings.docs_url, redoc_url=None, @@ -205,6 +210,7 @@ async def lifespan(app: FastAPI): "usePkceWithAuthorizationCodeGrant": auth_settings.use_pkce, }, ), + router=APIRouter(prefix=settings.prefix_path), api_version=eoapi_devseed_version, settings=settings, extensions=application_extensions, diff --git a/runtimes/eoapi/stac/eoapi/stac/client.py b/runtimes/eoapi/stac/eoapi/stac/client.py index 9d4b719..f9e31b7 100644 --- a/runtimes/eoapi/stac/eoapi/stac/client.py +++ b/runtimes/eoapi/stac/eoapi/stac/client.py @@ -221,13 +221,13 @@ async def get_queryables( request, collection_id, *args, **kwargs ) - output_type: Optional[MimeTypes] if f: output_type = MimeTypes[f] else: accepted_media = [MimeTypes[v] for v in get_args(QueryablesResponseType)] - output_type = accept_media_type( - request.headers.get("accept", ""), accepted_media + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MimeTypes.jsonschema ) if output_type == MimeTypes.html: @@ -252,7 +252,7 @@ def add_render_links(collection: Collection, titiler_endpoint: str) -> Collectio "rel": Relations.preview.value, "title": f"{render} interactive map", "type": MimeTypes.html.value, - "href": f"{base_url}/map?{query_params}", + "href": f"{base_url}/map.html?{query_params}", } ) collection["links"].append( @@ -288,13 +288,13 @@ async def landing_page( landing = await super().landing_page(**kwargs) - output_type: Optional[MimeTypes] if f: output_type = MimeTypes[f] else: accepted_media = [MimeTypes[v] for v in get_args(ResponseType)] - output_type = accept_media_type( - request.headers.get("accept", ""), accepted_media + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MimeTypes.json ) if output_type == MimeTypes.html: @@ -322,13 +322,13 @@ async def conformance( """ conforms_to = Conformance(conformsTo=self.conformance_classes()) - output_type: Optional[MimeTypes] if f: output_type = MimeTypes[f] else: accepted_media = [MimeTypes[v] for v in get_args(ResponseType)] - output_type = accept_media_type( - request.headers.get("accept", ""), accepted_media + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MimeTypes.json ) if output_type == MimeTypes.html: @@ -352,13 +352,13 @@ async def all_collections( for collection in collections["collections"]: collection = add_render_links(collection, titiler_endpoint) - output_type: Optional[MimeTypes] if f: output_type = MimeTypes[f] else: accepted_media = [MimeTypes[v] for v in get_args(ResponseType)] - output_type = accept_media_type( - request.headers.get("accept", ""), accepted_media + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MimeTypes.json ) if output_type == MimeTypes.html: @@ -386,13 +386,13 @@ async def get_collection( if titiler_endpoint := request.app.state.settings.titiler_endpoint: collection = add_render_links(collection, titiler_endpoint) - output_type: Optional[MimeTypes] if f: output_type = MimeTypes[f] else: accepted_media = [MimeTypes[v] for v in get_args(ResponseType)] - output_type = accept_media_type( - request.headers.get("accept", ""), accepted_media + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MimeTypes.json ) if output_type == MimeTypes.html: @@ -415,13 +415,13 @@ async def get_item( ) -> Item: item = await super().get_item(item_id, collection_id, request, **kwargs) - output_type: Optional[MimeTypes] if f: output_type = MimeTypes[f] else: accepted_media = [MimeTypes[v] for v in get_args(GeoResponseType)] - output_type = accept_media_type( - request.headers.get("accept", ""), accepted_media + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MimeTypes.geojson ) if output_type == MimeTypes.html: @@ -469,6 +469,7 @@ async def item_collection( filter_lang=filter_lang, fields=fields, sortby=sortby, + **kwargs, ) try: @@ -486,13 +487,13 @@ async def item_collection( ####################################################################### # Custom Responses ####################################################################### - output_type: Optional[MimeTypes] if f: output_type = MimeTypes[f] else: accepted_media = [MimeTypes[v] for v in get_args(GeoMultiResponseType)] - output_type = accept_media_type( - request.headers.get("accept", ""), accepted_media + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MimeTypes.geojson ) # Additional Headers for StreamingResponse @@ -587,6 +588,7 @@ async def get_search( sortby=sortby, filter_query=filter_expr, filter_lang=filter_lang, + **kwargs, ) try: @@ -601,13 +603,13 @@ async def get_search( ####################################################################### # Custom Responses ####################################################################### - output_type: Optional[MimeTypes] if f: output_type = MimeTypes[f] else: accepted_media = [MimeTypes[v] for v in get_args(GeoMultiResponseType)] - output_type = accept_media_type( - request.headers.get("accept", ""), accepted_media + output_type = ( + accept_media_type(request.headers.get("accept", ""), accepted_media) + or MimeTypes.geojson ) # Additional Headers for StreamingResponse diff --git a/runtimes/eoapi/stac/eoapi/stac/config.py b/runtimes/eoapi/stac/eoapi/stac/config.py index 8d521af..63dbc18 100644 --- a/runtimes/eoapi/stac/eoapi/stac/config.py +++ b/runtimes/eoapi/stac/eoapi/stac/config.py @@ -58,12 +58,11 @@ def get_postgres_setting(cls, data: Any) -> Any: secret = get_secret_dict(arn) data.update( { - "postgres_host_reader": secret["host"], - "postgres_host_writer": secret["host"], - "postgres_dbname": secret["dbname"], - "postgres_user": secret["username"], - "postgres_pass": secret["password"], - "postgres_port": secret["port"], + "pghost": secret["host"], + "pgdatabase": secret["dbname"], + "pguser": secret["username"], + "pgpassword": secret["password"], + "pgport": secret["port"], } ) diff --git a/runtimes/eoapi/stac/eoapi/stac/templates/footer.html b/runtimes/eoapi/stac/eoapi/stac/templates/footer.html index d0c3e00..0519bcd 100644 --- a/runtimes/eoapi/stac/eoapi/stac/templates/footer.html +++ b/runtimes/eoapi/stac/eoapi/stac/templates/footer.html @@ -1,5 +1,16 @@ {% include "debug.html" %}
+ +
+
+ Created by +
+ + Development Seed + +
+
diff --git a/runtimes/eoapi/stac/eoapi/stac/templates/header.html b/runtimes/eoapi/stac/eoapi/stac/templates/header.html index 0d9706b..85ff443 100644 --- a/runtimes/eoapi/stac/eoapi/stac/templates/header.html +++ b/runtimes/eoapi/stac/eoapi/stac/templates/header.html @@ -42,4 +42,3 @@
-
diff --git a/runtimes/eoapi/stac/eoapi/stac/templates/landing.html b/runtimes/eoapi/stac/eoapi/stac/templates/landing.html index 6458ea0..83bdcb5 100644 --- a/runtimes/eoapi/stac/eoapi/stac/templates/landing.html +++ b/runtimes/eoapi/stac/eoapi/stac/templates/landing.html @@ -19,9 +19,6 @@

{{ response.title }}

-

- {{ response.description }} -

Links

+
+ +
+
+ Created by +
+ + Development Seed + +
+
+ + diff --git a/runtimes/eoapi/vector/eoapi/vector/templates/map.html b/runtimes/eoapi/vector/eoapi/vector/templates/map.html new file mode 100644 index 0000000..38afc3f --- /dev/null +++ b/runtimes/eoapi/vector/eoapi/vector/templates/map.html @@ -0,0 +1,153 @@ + + + + eoAPI Vector - Map Viewer + + + + + + + + + + + + + + + +
+ + +

Collection {{ response.title }}

+
+ + + +{% include "footer.html" %} diff --git a/runtimes/eoapi/vector/pyproject.toml b/runtimes/eoapi/vector/pyproject.toml index 3b2aa02..9bd0707 100644 --- a/runtimes/eoapi/vector/pyproject.toml +++ b/runtimes/eoapi/vector/pyproject.toml @@ -2,7 +2,7 @@ name = "eoapi.vector" description = "Vector Features and Tiles for eoAPI." readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" authors = [ {name = "Vincent Sarago", email = "vincent@developmentseed.com"}, ] @@ -11,7 +11,6 @@ classifiers = [ "Intended Audience :: Information Technology", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -20,7 +19,7 @@ classifiers = [ ] dynamic = ["version"] dependencies = [ - "tipg==1.0.1", + "tipg==1.2.1", "eoapi.auth-utils>=0.2.0", "boto3" ]