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 Sep 3, 2024
1 parent 61f8b29 commit eb04d8d
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 9 deletions.
40 changes: 32 additions & 8 deletions functions/_common/grapherRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,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 fetchUnparsedGrapherConfig(
slug: string,
identifier: GrapherIdentifier,
env: Env,
etag?: string
) {
Expand All @@ -178,10 +190,15 @@ export async function fetchUnparsedGrapherConfig(
? [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 @@ -197,8 +214,8 @@ export async function fetchUnparsedGrapherConfig(
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 All @@ -211,11 +228,15 @@ export async function fetchUnparsedGrapherConfig(
}

export async function fetchGrapherConfig(
slug: string,
identifier: GrapherIdentifier,
env: Env,
etag?: string
): Promise<FetchGrapherConfigResult> {
const fetchResponse = await fetchUnparsedGrapherConfig(slug, env, etag)
const fetchResponse = await fetchUnparsedGrapherConfig(
identifier,
env,
etag
)

if (fetchResponse.status === 404) {
// we throw 404 errors instad of returning a 404 response so that the router
Expand Down Expand Up @@ -253,7 +274,10 @@ async function fetchAndRenderGrapherToSvg(
): Promise<string> {
const grapherLogger = new TimeLogger("grapher")

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

if (grapherConfigResponse.status === 404) {
// we throw 404 errors instad of returning a 404 response so that the router
Expand Down
6 changes: 5 additions & 1 deletion functions/grapher/[slug].ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,11 @@ async function handleConfigRequest(
const shouldCache = searchParams.get("nocache") === null
console.log("Preparing json response for ", slug)

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

if (grapherPageResp.status === 304) {
console.log("Returning 304 for ", slug)
Expand Down
75 changes: 75 additions & 0 deletions functions/grapher/by-uuid/[uuid].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Env } from "../../_common/env.js"
import { fetchGrapherConfig } from "../../_common/grapherRenderer.js"
import { IRequestStrict, Router, error, StatusError } from "itty-router"

const router = Router<IRequestStrict, [URL, Env, string]>()
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 onRequestOptions: PagesFunction = async (_context) => {
return new Response(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": "*",
},
})
}

export const onRequestGet: PagesFunction = async (context) => {
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) => {
if (e instanceof StatusError) {
return error(e.status, e.message)
}

return 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 eb04d8d

Please sign in to comment.