Skip to content

Watermarks

Draw a watermark from KV on an image from R2

Last updated View as MarkdownAgent setup

Enable Workers Cache so repeat requests for the same watermarked image are served from cache without re-running the Worker or re-transforming the image:

{
	"cache": {
		"enabled": true,
	},
}
[cache]
enabled = true

Then set Cache-Control headers on your response to control the cache lifetime:

export default {
	async fetch(request, env) {
		const watermarkKey = "my-watermark";
		const sourceKey = "my-source-image";

		const watermark = await env.NAMESPACE.get(watermarkKey, "stream");
		const source = await env.BUCKET.get(sourceKey);

		if (!watermark || !source) {
			return new Response("Not found", { status: 404 });
		}

		const result = await env.IMAGES.input(source.body)
			.draw(watermark)
			.output({ format: "image/jpeg" });

		const response = result.response();

		return new Response(response.body, {
			headers: {
				...Object.fromEntries(response.headers),
				"Cache-Control": "public, max-age=3600, stale-while-revalidate=86400",
			},
		});
	},
};
interface Env {
	BUCKET: R2Bucket;
	NAMESPACE: KVNamespace;
	IMAGES: ImagesBinding;
}
export default {
	async fetch(request, env): Promise<Response> {
		const watermarkKey = "my-watermark";
		const sourceKey = "my-source-image";

		const watermark = await env.NAMESPACE.get(watermarkKey, "stream");
		const source = await env.BUCKET.get(sourceKey);

		if (!watermark || !source) {
			return new Response("Not found", { status: 404 });
		}

		const result = await env.IMAGES.input(source.body)
			.draw(watermark)
			.output({ format: "image/jpeg" });

		const response = result.response();

		return new Response(response.body, {
			headers: {
				...Object.fromEntries(response.headers),
				"Cache-Control": "public, max-age=3600, stale-while-revalidate=86400",
			},
		});
	},
} satisfies ExportedHandler<Env>;

Was this helpful?