Skip to content

Commit

Permalink
feat(cloud-function): ad bsa support
Browse files Browse the repository at this point in the history
this refactors the pong lib:
- bundle click.js, get.js, viewed.js in pong.js
- add pong2.js based on bsa's api
- remove fallback
  • Loading branch information
fiji-flo committed Oct 6, 2023
1 parent 62fd1f7 commit c2e9bc2
Show file tree
Hide file tree
Showing 20 changed files with 422 additions and 316 deletions.
8 changes: 4 additions & 4 deletions cloud-function/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ The placement handler uses the following environment variables:
- `KEVEL_SITE_ID` (default: `0`) - Required for serving placements via Kevel.
- `KEVEL_NETWORK_ID` (default: `0`) - Required for serving placements via Kevel.
- `SIGN_SECRET` (default: `""`) - Required for serving placements.
- `CARBON_ZONE_KEY` (default: `""`) - Required for serving placements via
Carbon.
- `CARBON_FALLBACK_ENABLED` (default: `"false"`) - Whether fallback placements
should be served via Carbon.
- `BSA_ZONE_KEYS` (default: `""`) - Required for serving placements via BSA.
- `BSA_URL_PREFIX`(default: "https://localhost") - Where to show BSA placements
if enabled.
- `BSA_ENABLED` (default: `"false"`) - Whether to use placements via BSA.

You can override the defaults by adding a `.env` file with `KEY=value` lines.
6 changes: 3 additions & 3 deletions cloud-function/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { ANY_ATTACHMENT_EXT } from "./internal/constants/index.js";

import { Origin } from "./env.js";
import { proxyContent } from "./handlers/proxy-content.js";
import { proxyKevel } from "./handlers/proxy-kevel.js";
import { proxyApi } from "./handlers/proxy-api.js";
import { handleStripePlans } from "./handlers/handle-stripe-plans.js";
import { proxyTelemetry } from "./handlers/proxy-telemetry.js";
Expand All @@ -22,6 +21,7 @@ import { notFound } from "./middlewares/not-found.js";
import { resolveRunnerHtml } from "./middlewares/resolve-runner-html.js";
import { proxyRunner } from "./handlers/proxy-runner.js";
import { stripForwardedHostHeaders } from "./middlewares/stripForwardedHostHeaders.js";
import { proxyPong } from "./handlers/proxy-pong.js";

const router = Router();
router.use(stripForwardedHostHeaders);
Expand All @@ -37,8 +37,8 @@ router.all(
proxyApi
);
router.all("/submit/mdn-yari/*", requireOrigin(Origin.main), proxyTelemetry);
router.all("/pong/*", requireOrigin(Origin.main), express.json(), proxyKevel);
router.all("/pimg/*", requireOrigin(Origin.main), proxyKevel);
router.all("/pong/*", requireOrigin(Origin.main), express.json(), proxyPong);
router.all("/pimg/*", requireOrigin(Origin.main), proxyPong);
router.get(
["/[^/]+/docs/*/runner.html", "/[^/]+/blog/*/runner.html", "/runner.html"],
requireOrigin(Origin.play),
Expand Down
10 changes: 7 additions & 3 deletions cloud-function/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,13 @@ export function sourceUri(source: Source): string {
export const KEVEL_SITE_ID = Number(process.env["KEVEL_SITE_ID"] ?? 0);
export const KEVEL_NETWORK_ID = Number(process.env["KEVEL_NETWORK_ID"] ?? 0);
export const SIGN_SECRET = process.env["SIGN_SECRET"] ?? "";
export const CARBON_ZONE_KEY = process.env["CARBON_ZONE_KEY"] ?? "";
export const CARBON_FALLBACK_ENABLED = Boolean(
JSON.parse(process.env["CARBON_FALLBACK_ENABLED"] || "false")
export const BSA_ZONE_KEYS = Object.fromEntries(
(process.env["BSA_ZONE_KEYS"] ?? "").split(";").map((k) => k.split(":"))
);
export const BSA_URL_PREFIX =
process.env["BSA_URL_PREFIX"] ?? "https://localhost/en-US/play";
export const BSA_ENABLED = Boolean(
JSON.parse(process.env["BSA_ENABLED"] || "false")
);

// HTTPS.
Expand Down
94 changes: 94 additions & 0 deletions cloud-function/src/handlers/proxy-bsa.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import * as url from "node:url";

import type { Request, Response } from "express";

import { Coder } from "../internal/pong/index.js";
import {
createPong2GetHandler,
createPong2ClickHandler,
createPong2ViewedHandler,
fetchImage,
} from "../internal/pong/index.js";

import * as env from "../env.js";

import { getRequestCountry } from "../utils.js";

const { SIGN_SECRET, BSA_ZONE_KEYS } = env;

const coder = new Coder(SIGN_SECRET);
const handleGet = createPong2GetHandler(BSA_ZONE_KEYS, coder, env);
const handleClick = createPong2ClickHandler(coder);
const handleViewed = createPong2ViewedHandler(coder);

export async function proxyBSA(req: Request, res: Response) {
const countryCode = getRequestCountry(req);

const userAgent = req.headers["user-agent"] ?? "";

const parsedUrl = url.parse(req.url);
const pathname = parsedUrl.pathname ?? "";
const search = parsedUrl.search ?? "";

if (pathname === "/pong/get") {
if (req.method !== "POST") {
return res.sendStatus(405).end();
}

const { body } = req;
const { statusCode: status, payload } = await handleGet(
body,
countryCode,
userAgent
);

return res
.status(status)
.setHeader("cache-control", "no-store")
.setHeader("content-type", "application/json")
.end(JSON.stringify(payload));
} else if (req.path === "/pong/click") {
if (req.method !== "GET") {
return res.sendStatus(405).end();
}
const params = new URLSearchParams(search);
try {
const { status, location } = await handleClick(params);
if (location && (status === 301 || status === 302)) {
return res.redirect(location);
} else {
return res.sendStatus(502).end();
}
} catch (e) {
console.error(e);
}
} else if (pathname === "/pong/viewed") {
if (req.method !== "POST") {
return res.sendStatus(405).end();
}
const params = new URLSearchParams(search);
try {
await handleViewed(params);
return res.sendStatus(201).end();
} catch (e) {
console.error(e);
}
} else if (pathname.startsWith("/pimg/")) {
const src = coder.decodeAndVerify(
decodeURIComponent(pathname.substring("/pimg/".length))
);
if (!src) {
return res.sendStatus(400).end();
}
const { buf, contentType } = await fetchImage(src);
return res
.status(200)
.set({
"cache-control": "max-age=86400",
"content-type": contentType,
})
.end(Buffer.from(buf));
}

return res.status(204).end();
}
16 changes: 16 additions & 0 deletions cloud-function/src/handlers/proxy-pong.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { BSA_ENABLED, BSA_URL_PREFIX } from "../env.js";
import { proxyBSA } from "./proxy-bsa.js";
import { proxyKevel } from "./proxy-kevel.js";

import type { Request, Response } from "express";

export async function proxyPong(req: Request, res: Response) {
console.log(BSA_ENABLED, BSA_URL_PREFIX, req.get("referrer"));
if (BSA_ENABLED) {
const referrer = req.get("referrer") || "";
if (referrer.startsWith(BSA_URL_PREFIX)) {
return proxyBSA(req, res);
}
}
return proxyKevel(req, res);
}
Loading

0 comments on commit c2e9bc2

Please sign in to comment.