import escape from "escape-html"; import { Context, Next } from "koa"; /** * Resize observer script that sends a message to the parent window when content is resized. Inject * this script into the iframe to receive resize events. */ const resizeObserverScript = ( ctx: Context ) => ``; /** * Script that checks if the iframe is being loaded in an iframe. If it is not, it redirects to the * origin URL. */ const iframeCheckScript = ( ctx: Context ) => ``; /** * Render an embed for a GitLab or GitHub snippet, injecting the necessary scripts to handle resizing * and iframe checks. * * @param ctx The koa context * @param next The next middleware in the stack * @returns The response body */ export const renderEmbed = async (ctx: Context, next: Next) => { const url = escape(String(ctx.query.url)); if (!url) { ctx.throw(400, "url is required"); } let parsed; try { parsed = new URL(url); } catch (err) { ctx.throw(400, "Invalid URL provided"); } if ( parsed.host === "gitlab.com" && parsed.protocol === "https:" && ctx.path === "/embeds/gitlab" ) { const snippetLink = `${url}.js`; const csp = ctx.response.get("Content-Security-Policy"); // Inject gitlab.com into the script-src and style-src directives ctx.set( "Content-Security-Policy", csp .replace("script-src", "script-src gitlab.com") .replace("style-src", "style-src gitlab.com") ); ctx.set("X-Frame-Options", "sameorigin"); ctx.type = "html"; ctx.body = ` ${iframeCheckScript(ctx)} ${resizeObserverScript(ctx)} `; return; } if ( parsed.host === "gist.github.com" && parsed.protocol === "https:" && ctx.path === "/embeds/github" ) { const id = parsed.pathname.split("/")[2]; const gistLink = `https://gist.github.com/${id}.js`; const csp = ctx.response.get("Content-Security-Policy"); // Inject GitHub domains into the script-src and style-src directives ctx.set( "Content-Security-Policy", csp .replace("script-src", "script-src gist.github.com") .replace("style-src", "style-src github.githubassets.com") ); ctx.set("X-Frame-Options", "sameorigin"); ctx.type = "html"; ctx.body = ` ${iframeCheckScript(ctx)} ${resizeObserverScript(ctx)} `; return; } return next(); };