Avoid making a second network call from inside Lambda? #1095
-
I did search for a way to do this but maybe it was looking me right in the face and I didn't see it. I'm fairly new to fastAPI so that may be it. Here is a simplified version of my Lambda function. I have removed a lot of functionality so it's easy to talk about: import json
import os
from fastapi import FastAPI, Request
from fastapi.responses import Response
from mangum import Mangum
from titiler.core.factory import TilerFactory
from titiler.application.settings import ApiSettings
from titiler.core.errors import DEFAULT_STATUS_CODES, add_exception_handlers
import httpx
api_settings = ApiSettings()
app = FastAPI(title="Riverscapes COG tiler", description="Cloud Optimized GeoTIFF")
cog = TilerFactory()
app.include_router(cog.router, tags=["Cloud Optimized GeoTIFF"])
add_exception_handlers(app, DEFAULT_STATUS_CODES)
BUCKET_NAME = os.environ.get("BUCKET_NAME", "DUMMY")
@app.get("/{z}/{x}/{y}.png")
async def get_tile(z: int, x: int, y: int, request: Request):
"""_summary_
Args:
z (int): _description_
x (int): _description_
y (int): _description_
request (Request): _description_
Returns:
_type_: _description_
"""
query_params = dict(request.query_params)
rsxpath = query_params.get("file")
# Modify the query parameters as needed to fit Titiler's expected format
query_params = getattr(request.state, "query_params", {})
colormap = {
0: [0, 0, 0, 0],
1: [255, 0, 0, 255],
}
query_params['url'] = f"s3://{BUCKET_NAME}/cogs/{rsxpath}/COG.tiff"
query_params["colormap"] = json.dumps(colormap)
query_params.pop("file", None)
query_params.pop("symbology", None)
# Now that we have our query params set we pass this to Titiler to get the actual tile
async with httpx.AsyncClient() as client:
response = await client.get(f"http://127.0.0.1:8007/tiles/WebMercatorQuad/{z}/{x}/{y}.png", params=query_params)
return Response(content=response.content, media_type=response.headers.get("content-type", "application/octet-stream"))
# Here is the actual Lambda Handler
handler = Mangum(app, api_gateway_base_path=api_settings.root_path, lifespan="auto") My issue is this:On lambda you can't call "127.0.0.1" and it seems to me that making a network call from inside another network call is unnecessary. I can't find a way to call titiler's tile() function directly though and avoid using I have to be missing something obvious like |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
are you using ☝️ just because you want to pass from typing import Annotated
from fastapi import Query
from titiler.core.factory import TilerFactory
def DatasetPathParams(file: Annotated[str, Query(description="File Name")]) -> str:
"""Create dataset path from args"""
return f"s3://{BUCKET_NAME}/cogs/{file}/COG.tiff"
endpoints = TileFactory(path_dependency= DatasetPathParams) If it's to have a default colormap, you could also have a custom colormap dependency import json
from typing import Literal, Optional, Sequence
from fastapi import Query
from rio_tiler.colormap import cmap, parse_color
from titiler.core.factory import TilerFactory
def ColorMapDependency(
colormap_name: Annotated[ # type: ignore
Literal[tuple(cmap.list())],
Query(description="Colormap name"),
] = None,
colormap: Annotated[
Optional[str], Query(description="JSON encoded custom Colormap")
] = None,
):
if colormap_name:
return cmap.get(colormap_name)
elif colormap:
try:
c = json.loads(
colormap,
object_hook=lambda x: {
int(k): parse_color(v) for k, v in x.items()
},
)
# Make sure to match colormap type
if isinstance(c, Sequence):
c = [(tuple(inter), parse_color(v)) for (inter, v) in c]
return c
except json.JSONDecodeError as e:
raise HTTPException(
status_code=400, detail="Could not parse the colormap value."
) from e
return {
0: [0, 0, 0, 0],
1: [255, 0, 0, 255],
}
endpoints = TilerFactory(colormap_dependency=ColorMapDependency) you could also easily copy/paste https://github.com/developmentseed/titiler/blob/main/src/titiler/core/titiler/core/factory.py#L751C1-L838C1 |
Beta Was this translation helpful? Give feedback.
Ok. I think I figured it out. Here's my final pattern. I left out the
qgis_to_titiler_colormap
to keep the example short.