mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 10:51:07 +00:00
lambda version in ZIP; update readme; improve status code responses
This commit is contained in:
@@ -5,10 +5,12 @@
|
|||||||
|
|
||||||
Upload the resulting `lambda_function.zip` using the Lambda console.
|
Upload the resulting `lambda_function.zip` using the Lambda console.
|
||||||
|
|
||||||
## Restrictions
|
|
||||||
|
|
||||||
1. There is a limit of 1 MB for tiles served through Lambda@Edge.
|
## Configuration
|
||||||
2. Lambda@Edge does not support layers, environment variables, or ARM functions.
|
|
||||||
|
* `BUCKET`: the S3 bucket name.
|
||||||
|
* `PMTILES_PATH`
|
||||||
|
* `TILE_PATH`
|
||||||
|
|
||||||
## AWS Notes
|
## AWS Notes
|
||||||
|
|
||||||
@@ -17,24 +19,6 @@ Upload the resulting `lambda_function.zip` using the Lambda console.
|
|||||||
|
|
||||||
## Test Event
|
## Test Event
|
||||||
|
|
||||||
CloudFront event:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Records": [
|
|
||||||
{
|
|
||||||
"cf": {
|
|
||||||
"request": {
|
|
||||||
"uri": "/my-tileset-name/0/0/0.pbf",
|
|
||||||
"method": "GET",
|
|
||||||
"headers": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
API Gateway V2 / Lambda Function URLs:
|
API Gateway V2 / Lambda Function URLs:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -42,3 +26,12 @@ API Gateway V2 / Lambda Function URLs:
|
|||||||
"rawPath": "/my-tileset-name/0/0/0.pbf"
|
"rawPath": "/my-tileset-name/0/0/0.pbf"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Monitoring
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Lambda@Edge
|
||||||
|
|
||||||
|
Lambda@Edge's multi-region features have little benefit when fetching data from S3 in a single region, and Lambda@Edge [doesn't support](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions-restrictions.html) environment variables or responses over 1 MB. For globally distributed caching, use CloudFront in combination with Lambda Function URLs.
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
import zipfile
|
import zipfile
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
sha = subprocess.check_output(["git", "describe", "--always"]).strip()
|
||||||
|
|
||||||
with zipfile.ZipFile("lambda_function.zip", "w", zipfile.ZIP_DEFLATED) as z:
|
with zipfile.ZipFile("lambda_function.zip", "w", zipfile.ZIP_DEFLATED) as z:
|
||||||
z.write("lambda_function.py")
|
z.write("lambda_function.py")
|
||||||
z.write("../../python/pmtiles/reader.py", "pmtiles/reader.py")
|
z.write("../../python/pmtiles/reader.py", "pmtiles/reader.py")
|
||||||
|
z.writestr("version",sha)
|
||||||
|
|
||||||
print(f"created lambda_function.zip")
|
print(f"created lambda_function.zip")
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import re
|
|||||||
|
|
||||||
# Exists inside all lambda functions
|
# Exists inside all lambda functions
|
||||||
import boto3
|
import boto3
|
||||||
|
from botocore.exceptions import ClientError
|
||||||
|
|
||||||
# create_lambda_function.py will vendor the relevant file
|
# create_lambda_function.py will vendor the relevant file
|
||||||
from pmtiles.reader import Reader
|
from pmtiles.reader import Reader
|
||||||
@@ -16,7 +17,6 @@ Zxy = collections.namedtuple("Zxy", ["z", "x", "y"])
|
|||||||
|
|
||||||
s3 = boto3.client("s3")
|
s3 = boto3.client("s3")
|
||||||
|
|
||||||
|
|
||||||
# Given a 512MB lambda function, use half of the memory for the cache,
|
# Given a 512MB lambda function, use half of the memory for the cache,
|
||||||
# assuming the average root/leaf/tile size is 512 KB
|
# assuming the average root/leaf/tile size is 512 KB
|
||||||
@lru_cache(maxsize=500)
|
@lru_cache(maxsize=500)
|
||||||
@@ -64,7 +64,7 @@ def lambda_handler(event, context):
|
|||||||
name, tile = parse_tile_path(os.environ.get("TILE_PATH"), uri)
|
name, tile = parse_tile_path(os.environ.get("TILE_PATH"), uri)
|
||||||
|
|
||||||
if not tile:
|
if not tile:
|
||||||
return {"statusCode": 400, "body": "Invalid Tile URL"}
|
return {"statusCode": 400, "body": "Invalid tile URL"}
|
||||||
|
|
||||||
def get_bytes(offset, length):
|
def get_bytes(offset, length):
|
||||||
return get_object_bytes(
|
return get_object_bytes(
|
||||||
@@ -72,10 +72,22 @@ def lambda_handler(event, context):
|
|||||||
)
|
)
|
||||||
|
|
||||||
reader = Reader(get_bytes)
|
reader = Reader(get_bytes)
|
||||||
tile_data = reader.get(tile.z, tile.x, tile.y)
|
minzoom = int(reader.header().metadata["minzoom"])
|
||||||
if not tile_data:
|
maxzoom = int(reader.header().metadata["maxzoom"])
|
||||||
|
if tile.z < minzoom or tile.z > maxzoom:
|
||||||
return {"statusCode": 404, "body": "Tile not found"}
|
return {"statusCode": 404, "body": "Tile not found"}
|
||||||
|
|
||||||
|
try:
|
||||||
|
tile_data = reader.get(tile.z, tile.x, tile.y)
|
||||||
|
if not tile_data:
|
||||||
|
return {"statusCode": 204}
|
||||||
|
except ClientError as e:
|
||||||
|
error_code = e.response["Error"]["Code"]
|
||||||
|
if error_code == "AccessDenied":
|
||||||
|
return {"statusCode": 404, "body": "Archive not found"}
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
# CloudFront requires decompressed responses from lambda
|
# CloudFront requires decompressed responses from lambda
|
||||||
# in order to implement the Compressed CacheOptimized policy correctly
|
# in order to implement the Compressed CacheOptimized policy correctly
|
||||||
# as well as Brotli support
|
# as well as Brotli support
|
||||||
|
|||||||
Reference in New Issue
Block a user