Implement ETag logic for AWS and Cloudflare [#90] (#354)

This commit is contained in:
Brandon Liu
2024-02-07 11:46:05 +08:00
committed by GitHub
parent e86dd554be
commit 5b8627b0d8
2 changed files with 34 additions and 11 deletions

View File

@@ -5,6 +5,7 @@ import {
} from "aws-lambda";
import {
Compression,
EtagMismatch,
PMTiles,
RangeResponse,
ResolvedValueCache,
@@ -16,7 +17,11 @@ import { pmtiles_path, tileJSON, tile_path } from "../../shared/index";
import { createHash } from "crypto";
import zlib from "zlib";
import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
import {
GetObjectCommand,
GetObjectCommandOutput,
S3Client,
} from "@aws-sdk/client-s3";
import { NodeHttpHandler } from "@aws-sdk/node-http-handler";
// the region should default to the same one as the function
@@ -60,16 +65,26 @@ class S3Source implements Source {
signal?: AbortSignal,
etag?: string
): Promise<RangeResponse> {
const resp = await s3client.send(
new GetObjectCommand({
// biome-ignore lint: aws api
Bucket: process.env.BUCKET!,
// biome-ignore lint: aws api
Key: pmtiles_path(this.archiveName, process.env.PMTILES_PATH),
// biome-ignore lint: aws api
Range: "bytes=" + offset + "-" + (offset + length - 1),
})
);
let resp: GetObjectCommandOutput;
try {
resp = await s3client.send(
new GetObjectCommand({
// biome-ignore lint: aws api
Bucket: process.env.BUCKET!,
// biome-ignore lint: aws api
Key: pmtiles_path(this.archiveName, process.env.PMTILES_PATH),
// biome-ignore lint: aws api
Range: "bytes=" + offset + "-" + (offset + length - 1),
// biome-ignore lint: aws api
IfMatch: etag,
})
);
} catch (e: unknown) {
if (e instanceof Error && (e as Error).name === "PreconditionFailed") {
throw new EtagMismatch();
}
throw e;
}
const arr = await resp.Body?.transformToByteArray();

View File

@@ -1,5 +1,6 @@
import {
Compression,
EtagMismatch,
PMTiles,
RangeResponse,
ResolvedValueCache,
@@ -63,12 +64,19 @@ class R2Source implements Source {
pmtiles_path(this.archiveName, this.env.PMTILES_PATH),
{
range: { offset: offset, length: length },
onlyIf: { etagMatches: etag },
}
);
if (!resp) {
throw new KeyNotFoundError("Archive not found");
}
const o = resp as R2ObjectBody;
if (!o.body) {
throw new EtagMismatch();
}
const a = await o.arrayBuffer();
return {
data: a,