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_colormapto keep the example short.