Skip to content

Commit

Permalink
add HTML output for stac-api
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentsarago committed Jan 18, 2025
1 parent 28e70fa commit f5673d9
Show file tree
Hide file tree
Showing 14 changed files with 1,342 additions and 10 deletions.
130 changes: 121 additions & 9 deletions runtimes/eoapi/stac/eoapi/stac/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
import logging
from contextlib import asynccontextmanager

import attr
import jinja2
from eoapi.auth_utils import OpenIdConnectAuth, OpenIdConnectSettings
from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
from stac_fastapi.api.app import StacApi
from stac_fastapi.api.models import (
CollectionUri,
EmptyRequest,
ItemCollectionUri,
create_get_request_model,
ItemUri,
create_post_request_model,
create_request_model,
)
from stac_fastapi.api.routes import create_async_endpoint
from stac_fastapi.extensions.core import (
FieldsExtension,
FilterExtension,
Expand All @@ -23,21 +27,24 @@
)
from stac_fastapi.extensions.third_party import BulkTransactionExtension
from stac_fastapi.pgstac.config import Settings
from stac_fastapi.pgstac.core import CoreCrudClient
from stac_fastapi.pgstac.db import close_db_connection, connect_to_db
from stac_fastapi.pgstac.extensions import QueryExtension
from stac_fastapi.pgstac.extensions.filter import FiltersClient
from stac_fastapi.pgstac.transactions import BulkTransactionsClient, TransactionsClient
from stac_fastapi.pgstac.types.search import PgstacSearch
from stac_fastapi.types.search import BaseSearchGetRequest
from stac_pydantic import api
from stac_pydantic.shared import MimeTypes
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
from starlette.requests import Request
from starlette.responses import HTMLResponse
from starlette.templating import Jinja2Templates
from starlette_cramjam.middleware import CompressionMiddleware

from .client import PgSTACClient
from .config import ApiSettings
from .extension import TiTilerExtension
from .extension import HTMLorGeoJSONGetRequest, HTMLorJSONGetRequest, TiTilerExtension
from .logs import init_logging

jinja2_env = jinja2.Environment(
Expand Down Expand Up @@ -115,19 +122,121 @@ async def lifespan(app: FastAPI):
)

# Custom Models
items_get_model = ItemCollectionUri
if any(isinstance(ext, TokenPaginationExtension) for ext in extensions):
items_get_model = create_request_model(
model_name="ItemCollectionUri",
base_model=ItemCollectionUri,
mixins=[TokenPaginationExtension().GET],
mixins=[TokenPaginationExtension().GET, HTMLorGeoJSONGetRequest],
request_type="GET",
)
else:
items_get_model = create_request_model(
model_name="ItemCollectionUri",
base_model=ItemCollectionUri,
mixins=[HTMLorGeoJSONGetRequest],
request_type="GET",
)

search_get_model = create_get_request_model(extensions)
search_get_model = create_request_model(
"SearchGetRequest",
base_model=BaseSearchGetRequest,
extensions=extensions,
mixins=[HTMLorGeoJSONGetRequest],
request_type="GET",
)
search_post_model = create_post_request_model(extensions, base_model=PgstacSearch)
collections_get_model = create_request_model(
model_name="CollectionsModel",
base_model=EmptyRequest,
mixins=[HTMLorJSONGetRequest],
request_type="GET",
)
collection_get_model = create_request_model(
model_name="CollectionUri",
base_model=CollectionUri,
mixins=[HTMLorJSONGetRequest],
request_type="GET",
)
item_get_model = create_request_model(
model_name="ItemUri",
base_model=ItemUri,
mixins=[HTMLorGeoJSONGetRequest],
request_type="GET",
)
conformance_get_model = create_request_model(
model_name="ConformanceModel",
base_model=EmptyRequest,
mixins=[HTMLorJSONGetRequest],
request_type="GET",
)
landing_get_model = create_request_model(
model_name="LandingModel",
base_model=EmptyRequest,
mixins=[HTMLorJSONGetRequest],
request_type="GET",
)


@attr.s
class CustomStacApi(StacApi):
def register_landing_page(self):
"""Register landing page (GET /).
Returns:
None
"""
self.router.add_api_route(
name="Landing Page",
path="/",
response_model=(
api.LandingPage if self.settings.enable_response_models else None
),
responses={
200: {
"content": {
MimeTypes.json.value: {},
},
"model": api.LandingPage,
},
},
response_class=self.response_class,
response_model_exclude_unset=False,
response_model_exclude_none=True,
methods=["GET"],
endpoint=create_async_endpoint(self.client.landing_page, landing_get_model),
)

def register_conformance_classes(self):
"""Register conformance classes (GET /conformance).
Returns:
None
"""
self.router.add_api_route(
name="Conformance Classes",
path="/conformance",
response_model=(
api.Conformance if self.settings.enable_response_models else None
),
responses={
200: {
"content": {
MimeTypes.json.value: {},
},
"model": api.Conformance,
},
},
response_class=self.response_class,
response_model_exclude_unset=True,
response_model_exclude_none=True,
methods=["GET"],
endpoint=create_async_endpoint(
self.client.conformance, conformance_get_model
),
)


api = StacApi(
stac_api = CustomStacApi( # type: ignore
app=FastAPI(
title=api_settings.name,
lifespan=lifespan,
Expand All @@ -143,14 +252,17 @@ async def lifespan(app: FastAPI):
description=api_settings.name,
settings=settings,
extensions=extensions,
client=CoreCrudClient(post_request_model=search_post_model),
client=PgSTACClient(post_request_model=search_post_model), # type: ignore
items_get_request_model=items_get_model,
item_get_request_model=item_get_model,
collections_get_request_model=collections_get_model,
collection_get_request_model=collection_get_model,
search_get_request_model=search_get_model,
search_post_request_model=search_post_model,
response_class=ORJSONResponse,
middlewares=middlewares,
)
app = api.app
app = stac_api.app


@app.get("/index.html", response_class=HTMLResponse)
Expand Down
Loading

0 comments on commit f5673d9

Please sign in to comment.