Skip to content

Commit 153f82b

Browse files
committed
work out some changes to stac-api and titiler-pgstac handlers
1 parent 0f7e614 commit 153f82b

File tree

5 files changed

+95
-73
lines changed

5 files changed

+95
-73
lines changed

lib/stac-api/runtime/src/app.py

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,57 @@
22
FastAPI application using PGStac.
33
"""
44

5+
from brotli_asgi import BrotliMiddleware
6+
from fastapi import FastAPI
57
from fastapi.middleware.cors import CORSMiddleware
68
from fastapi.responses import ORJSONResponse
79
from stac_fastapi.api.app import StacApi
10+
from stac_fastapi.api.middleware import ProxyHeaderMiddleware
11+
from stac_fastapi.pgstac.app import (
12+
application_extensions,
13+
collections_get_request_model,
14+
get_request_model,
15+
items_get_request_model,
16+
post_request_model,
17+
)
818
from stac_fastapi.pgstac.core import CoreCrudClient
919
from stac_fastapi.pgstac.db import close_db_connection, connect_to_db
10-
from starlette_cramjam.middleware import CompressionMiddleware
20+
from starlette.middleware import Middleware
1121

1222
from .config import ApiSettings
13-
from .config import extensions as PgStacExtensions
14-
from .config import get_request_model as GETModel
15-
from .config import post_request_model as POSTModel
1623

17-
api_settings = ApiSettings()
24+
settings = ApiSettings()
1825

1926
api = StacApi(
20-
title=api_settings.name,
21-
api_version=api_settings.version,
22-
description=api_settings.description or api_settings.name,
23-
settings=api_settings.load_postgres_settings(),
24-
extensions=PgStacExtensions,
25-
client=CoreCrudClient(post_request_model=POSTModel),
26-
search_get_request_model=GETModel,
27-
search_post_request_model=POSTModel,
27+
app=FastAPI(
28+
openapi_url=settings.openapi_url,
29+
docs_url=settings.docs_url,
30+
redoc_url=None,
31+
root_path=settings.root_path,
32+
title=settings.stac_fastapi_title,
33+
version=settings.stac_fastapi_version,
34+
description=settings.stac_fastapi_description,
35+
),
36+
settings=settings,
37+
extensions=application_extensions,
38+
client=CoreCrudClient(pgstac_search_model=post_request_model),
2839
response_class=ORJSONResponse,
29-
middlewares=[CompressionMiddleware],
40+
items_get_request_model=items_get_request_model,
41+
search_get_request_model=get_request_model,
42+
search_post_request_model=post_request_model,
43+
collections_get_request_model=collections_get_request_model,
44+
middlewares=[
45+
Middleware(BrotliMiddleware),
46+
Middleware(ProxyHeaderMiddleware),
47+
],
3048
)
31-
3249
app = api.app
3350

3451
# Set all CORS enabled origins
35-
if api_settings.cors_origins:
52+
if settings.cors_origins:
3653
app.add_middleware(
3754
CORSMiddleware,
38-
allow_origins=api_settings.cors_origins,
55+
allow_origins=settings.cors_origins,
3956
allow_credentials=True,
4057
allow_methods=["GET", "POST", "OPTIONS"],
4158
allow_headers=["*"],

lib/stac-api/runtime/src/config.py

Lines changed: 20 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,21 @@
33

44
import base64
55
import json
6-
from typing import Optional
6+
from typing import Any, Optional
77

88
import boto3
9-
import pydantic
10-
from stac_fastapi.api.models import create_get_request_model, create_post_request_model
119

1210
# from stac_fastapi.pgstac.extensions import QueryExtension
13-
from stac_fastapi.extensions.core import (
14-
ContextExtension,
15-
FieldsExtension,
16-
FilterExtension,
17-
QueryExtension,
18-
SortExtension,
19-
TokenPaginationExtension,
20-
)
11+
from pydantic import model_validator
2112
from stac_fastapi.pgstac.config import Settings
22-
from stac_fastapi.pgstac.types.search import PgstacSearch
13+
from stac_fastapi.pgstac.version import __version__ as stac_fastapi_pgstac_version
2314

2415

2516
def get_secret_dict(secret_name: str):
2617
"""Retrieve secrets from AWS Secrets Manager
2718
2819
Args:
2920
secret_name (str): name of aws secrets manager secret containing database connection secrets
30-
profile_name (str, optional): optional name of aws profile for use in debugger only
3121
3222
Returns:
3323
secrets (dict): decrypted secrets in dict
@@ -45,53 +35,30 @@ def get_secret_dict(secret_name: str):
4535
return json.loads(base64.b64decode(get_secret_value_response["SecretBinary"]))
4636

4737

48-
class ApiSettings(pydantic.BaseSettings):
38+
class ApiSettings(Settings):
4939
"""API settings"""
5040

51-
name: str = "asdi-stac-api"
52-
version: str = "0.1"
41+
name: str = "stac-fastapi-pgstac"
42+
version: str = stac_fastapi_pgstac_version
5343
description: Optional[str] = None
54-
cors_origins: str = "*"
5544
cachecontrol: str = "public, max-age=3600"
5645
debug: bool = False
5746

5847
pgstac_secret_arn: Optional[str]
5948

60-
@pydantic.validator("cors_origins")
61-
def parse_cors_origin(cls, v):
62-
"""Parse CORS origins."""
63-
return [origin.strip() for origin in v.split(",")]
64-
65-
def load_postgres_settings(self) -> "Settings":
66-
"""Load postgres connection params from AWS secret"""
67-
68-
if self.pgstac_secret_arn:
69-
secret = get_secret_dict(self.pgstac_secret_arn)
70-
71-
return Settings(
72-
postgres_host_reader=secret["host"],
73-
postgres_host_writer=secret["host"],
74-
postgres_dbname=secret["dbname"],
75-
postgres_user=secret["username"],
76-
postgres_pass=secret["password"],
77-
postgres_port=secret["port"],
49+
@model_validator(mode="before")
50+
def get_postgres_setting(cls, data: Any) -> Any:
51+
if arn := data.get("pgstac_secret_arn"):
52+
secret = get_secret_dict(arn)
53+
data.update(
54+
{
55+
"postgres_host_reader": secret["host"],
56+
"postgres_host_writer": secret["host"],
57+
"postgres_dbname": secret["dbname"],
58+
"postgres_user": secret["username"],
59+
"postgres_pass": secret["password"],
60+
"postgres_port": secret["port"],
61+
}
7862
)
79-
else:
80-
return Settings()
81-
82-
class Config:
83-
"""model config"""
84-
85-
env_file = ".env"
86-
8763

88-
extensions = [
89-
FilterExtension(),
90-
QueryExtension(),
91-
SortExtension(),
92-
FieldsExtension(),
93-
TokenPaginationExtension(),
94-
ContextExtension(),
95-
]
96-
post_request_model = create_post_request_model(extensions, base_model=PgstacSearch)
97-
get_request_model = create_get_request_model(extensions)
64+
return data

lib/stac-api/runtime/src/handler.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,22 @@
77

88
from mangum import Mangum
99

10+
from .config import get_secret_dict
11+
12+
pgstac_secret_arn = os.environ["PGSTAC_SECRET_ARN"]
13+
14+
secret = get_secret_dict(pgstac_secret_arn)
15+
os.environ.update(
16+
{
17+
"postgres_host_reader": secret["host"],
18+
"postgres_host_writer": secret["host"],
19+
"postgres_dbname": secret["dbname"],
20+
"postgres_user": secret["username"],
21+
"postgres_pass": secret["password"],
22+
"postgres_port": str(secret["port"]),
23+
}
24+
)
25+
1026
from .app import app
1127

1228
handler = Mangum(app, lifespan="off")

lib/titiler-pgstac-api/runtime/Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ RUN find /asset -type f -name '*.py' -print0 | xargs -0 rm -f
2020
RUN find /asset -type d -name 'tests' -print0 | xargs -0 rm -rf
2121
RUN rm -rdf /asset/numpy/doc/ /asset/boto3* /asset/botocore* /asset/bin /asset/geos_license /asset/Misc
2222

23+
# Strip debug symbols from compiled C/C++ code (except for numpy.libs!)
24+
RUN cd /asset && \
25+
find . -type f -name '*.so*' \
26+
-not -path "./numpy.libs/*" \
27+
-exec strip --strip-unneeded {} \;
28+
2329
COPY runtime/src/*.py /asset/
2430

2531
CMD ["echo", "hello world"]

lib/titiler-pgstac-api/runtime/src/handler.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
import asyncio
66
import os
77

8-
from mangum import Mangum
9-
from utils import get_secret_dict
8+
from .utils import get_secret_dict
109

1110
pgstac_secret_arn = os.environ["PGSTAC_SECRET_ARN"]
1211

@@ -21,14 +20,31 @@
2120
}
2221
)
2322

23+
from mangum import Mangum
2424
from titiler.pgstac.db import connect_to_db # noqa: E402
2525
from titiler.pgstac.main import app # noqa: E402
26+
from titiler.pgstac.settings import PostgresSettings
27+
from utils import get_secret_dict
2628

2729

2830
@app.on_event("startup")
2931
async def startup_event() -> None:
3032
"""Connect to database on startup."""
31-
await connect_to_db(app)
33+
pgstac_secret_arn = os.getenv("PGSTAC_SECRET_ARN")
34+
if not pgstac_secret_arn:
35+
raise ValueError("PGSTAC_SECRET_ARN is not set!")
36+
37+
secret = get_secret_dict(pgstac_secret_arn)
38+
await connect_to_db(
39+
app,
40+
settings=PostgresSettings(
41+
postgres_user=secret["username"],
42+
postgres_pass=secret["password"],
43+
postgres_host=secret["host"],
44+
postgres_port=secret["port"],
45+
postgres_dbname=secret["dbname"],
46+
),
47+
)
3248

3349

3450
handler = Mangum(app, lifespan="off")

0 commit comments

Comments
 (0)