diff --git a/serverless/aws/README.md b/serverless/aws/README.md index 06f1e06..184157b 100644 --- a/serverless/aws/README.md +++ b/serverless/aws/README.md @@ -24,7 +24,6 @@ Configure these Lambda environment variables: * `PMTILES_PATH`: optional, define how a tileset name is translated into an S3 key. Default `{name}.pmtiles` * Example path setting for objects in a directory: `my_folder/{name}/file.pmtiles` * `TILE_PATH`: optional, define the URL route of the tiles API. Default `/{name}/{z}/{x}/{y}.pbf` -* `CORS`: optional, the exact value of the `Access-Control-Allow-Origin` header in the Lambda response. Note that this header will be cached by CloudFront; if you need dynamic multiple-origin support with CloudFront you should use [CloudFront Functions](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html) instead. For API Gateway integration, your Lambda Proxy Integration route will need to specify a greedy capturing parameter called `proxy` e.g. `/{proxy+}` (the default). API Gateway responses will always be GZIP-encoded. diff --git a/serverless/aws/src/index.ts b/serverless/aws/src/index.ts index 4827336..608a28d 100644 --- a/serverless/aws/src/index.ts +++ b/serverless/aws/src/index.ts @@ -10,6 +10,7 @@ import { RangeResponse, Source, Compression, + TileType, } from "../../../js"; // @ts-ignore @@ -69,7 +70,6 @@ export const tile_path = ( return { ok: false, name: "", tile: [0, 0, 0], ext: "" }; }; - class S3Source implements Source { archive_name: string; @@ -143,19 +143,47 @@ export const handler = async ( } var headers: Headers = {}; - if (process.env.CORS) { - headers["Access-Control-Allow-Origin"] = process.env.CORS; - } - // TODO: extension enforcement and MIME types, metadata and TileJSON + // TODO: metadata and TileJSON const source = new S3Source(name); const p = new PMTiles(source, CACHE); try { const header = await p.getHeader(); - // TODO optimize by checking min/max zoom, return 404 + if (tile[0] < header.minZoom || tile[0] > header.maxZoom) { + return apiResp(404, ""); + } - // part of the list of Cloudfront compressible types. - headers["Content-Type"] = "application/vnd.mapbox-vector-tile"; + for (const pair of [ + [TileType.Mvt, "mvt"], + [TileType.Png, "png"], + [TileType.Jpeg, "jpg"], + [TileType.Webp, "webp"], + ]) { + if (header.tileType === pair[0] && ext !== pair[1]) { + return apiResp( + 400, + "Bad request: archive has type ." + pair[1], + false, + headers + ); + } + } + + switch (header.tileType) { + case TileType.Mvt: + // part of the list of Cloudfront compressible types. + headers["Content-Type"] = "application/vnd.mapbox-vector-tile"; + break; + case TileType.Png: + headers["Content-Type"] = "image/png"; + break; + case TileType.Jpeg: + headers["Content-Type"] = "image/jpeg"; + break; + case TileType.Webp: + headers["Content-Type"] = "image/webp"; + break; + } const tile_result = await p.getZxy(tile[0], tile[1], tile[2]); if (tile_result) {