Skip to content

Commit

Permalink
✨ add fetching grapher configs by UUID
Browse files Browse the repository at this point in the history
  • Loading branch information
danyx23 committed Aug 21, 2024
1 parent f18b0d2 commit 8d270f1
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 7 deletions.
33 changes: 27 additions & 6 deletions functions/_common/grapherRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,20 @@ interface FetchGrapherConfigResult {
etag: string | undefined
}

interface GrapherSlug {
type: "slug"
id: string
}

interface GrapherUuid {
type: "uuid"
id: string
}

type GrapherIdentifier = GrapherSlug | GrapherUuid

export async function fetchGrapherConfig(
slug: string,
identifier: GrapherIdentifier,
env: Env,
etag: string

Check warning on line 182 in functions/_common/grapherRenderer.ts

View workflow job for this annotation

GitHub Actions / eslint

'etag' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 182 in functions/_common/grapherRenderer.ts

View workflow job for this annotation

GitHub Actions / eslint

'etag' is defined but never used. Allowed unused args must match /^_/u
): Promise<FetchGrapherConfigResult> {
Expand All @@ -176,10 +188,15 @@ export async function fetchGrapherConfig(
? [env.GRAPHER_CONFIG_R2_BUCKET_PATH]
: ["by-branch", env.CF_PAGES_BRANCH]

const directory =
identifier.type === "slug"
? R2GrapherConfigDirectory.publishedGrapherBySlug
: R2GrapherConfigDirectory.byUUID

const key = excludeUndefined([
...topLevelDirectory,
R2GrapherConfigDirectory.publishedGrapherBySlug,
`${slug}.json`,
directory,
`${identifier.id}.json`,
]).join("/")

console.log("fetching grapher config from this key", key)
Expand All @@ -195,8 +212,8 @@ export async function fetchGrapherConfig(
const topLevelDirectory = env.GRAPHER_CONFIG_R2_BUCKET_FALLBACK_PATH
const fallbackKey = excludeUndefined([
topLevelDirectory,
R2GrapherConfigDirectory.publishedGrapherBySlug,
`${slug}.json`,
directory,
`${identifier.id}.json`,
]).join("/")
fallbackUrl = new URL(
fallbackKey,
Expand Down Expand Up @@ -232,7 +249,11 @@ async function fetchAndRenderGrapherToSvg(
) {
const grapherLogger = new TimeLogger("grapher")

const grapherConfigResponse = await fetchGrapherConfig(slug, env, etag)
const grapherConfigResponse = await fetchGrapherConfig(
{ type: "slug", id: slug },
env,
undefined
)

if (grapherConfigResponse.status !== 200) {
return null
Expand Down
6 changes: 5 additions & 1 deletion functions/grapher/[slug].ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,11 @@ async function handleConfigRequest(
)
}

const grapherPageResp = await fetchGrapherConfig(slug, env, etag)
const grapherPageResp = await fetchGrapherConfig(
{ type: "slug", id: slug },
env,
etag
)

if (grapherPageResp.status === 304) {
return new Response(null, { status: 304 })
Expand Down
69 changes: 69 additions & 0 deletions functions/grapher/by-uuid/[uuid].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Env } from "../thumbnail/[slug].js"
import { fetchGrapherConfig } from "../../_common/grapherRenderer.js"
import { IRequestStrict, Router, error, cors } from "itty-router"
const { preflight, corsify } = cors({
allowMethods: "GET",
})

const router = Router<IRequestStrict, [URL, Env, string]>({
before: [preflight],
finally: [corsify],
})
router
.get(
"/grapher/by-uuid/:uuid.config.json",
async ({ params: { uuid } }, { searchParams }, env, etag) =>
handleConfigRequest(uuid, searchParams, env, etag)
)
.all("*", () => error(404, "Route not defined"))

export const onRequestGet: PagesFunction = async (context) => {
// Makes it so that if there's an error, we will just deliver the original page before the HTML rewrite.
// Only caveat is that redirects will not be taken into account for some reason; but on the other hand the worker is so simple that it's unlikely to fail.
context.passThroughOnException()
const { request, env } = context
const url = new URL(request.url)

return router
.fetch(
request,
url,
{ ...env, url },
request.headers.get("if-none-match")
)
.catch((e) => error(500, e))
}

async function handleConfigRequest(
uuid: string,
searchParams: URLSearchParams,
env: Env,
etag: string | undefined
) {
const shouldCache = searchParams.get("nocache") === null
console.log("Preparing json response for uuid ", uuid)

const grapherPageResp = await fetchGrapherConfig(
{ type: "uuid", id: uuid },
env,
etag
)

if (grapherPageResp.status === 304) {
return new Response(null, { status: 304 })
}

console.log("Grapher page response", grapherPageResp.grapherConfig.title)

const cacheControl = shouldCache
? "public, s-maxage=3600, max-age=0, must-revalidate"
: "public, s-maxage=0, max-age=0, must-revalidate"

return new Response(JSON.stringify(grapherPageResp.grapherConfig), {
headers: {
"content-type": "application/json",
"Cache-Control": cacheControl,
ETag: grapherPageResp.etag,
},
})
}

0 comments on commit 8d270f1

Please sign in to comment.