diff --git a/plugin/src/helpers/functions.ts b/plugin/src/helpers/functions.ts index 983fe0c2..840fb895 100644 --- a/plugin/src/helpers/functions.ts +++ b/plugin/src/helpers/functions.ts @@ -78,11 +78,18 @@ export const setupImageCdn = async ({ join(constants.INTERNAL_FUNCTIONS_SRC, '_ipx.ts'), ) - netlifyConfig.redirects.push({ - from: '/_gatsby/image/*', - to: '/.netlify/builders/_ipx', - status: 200, - }) + netlifyConfig.redirects.push( + { + from: '/_gatsby/image/*', + to: '/.netlify/builders/_ipx', + status: 200, + }, + { + from: '/_gatsby/file/*', + to: '/.netlify/functions/_ipx', + status: 200, + }, + ) } export const deleteFunctions = async ({ diff --git a/plugin/src/templates/ipx.ts b/plugin/src/templates/ipx.ts index 45ae4576..92e61aad 100644 --- a/plugin/src/templates/ipx.ts +++ b/plugin/src/templates/ipx.ts @@ -1,7 +1,47 @@ +import { Buffer } from 'buffer' + +import { Handler, HandlerResponse } from '@netlify/functions' import { createIPXHandler } from '@netlify/ipx' -export const handler = createIPXHandler({ +const ipxHandler = createIPXHandler({ propsEncoding: 'base64', basePath: '/_gatsby/image/', bypassDomainCheck: true, }) + +// eslint-disable-next-line require-await +export const handler: Handler = async (event, ...rest) => { + const { pathname, host } = new URL(event.rawUrl) + + const [, , type, encodedUrl] = pathname.split('/') + + if (type === 'image') { + return ipxHandler(event, ...rest) as Promise + } + + try { + const urlString = Buffer.from(encodedUrl, 'base64').toString('utf8') + // Validate it by parsing it + const url = new URL(urlString) + if (url.host === host) { + return { + statusCode: 400, + body: 'File cannot be served from the same host as the original request', + } + } + console.log(`Redirecting to ${urlString}`) + return { + statusCode: 301, + headers: { + Location: url.toString(), + }, + body: '', + } + } catch (error) { + console.error(error) + return { + statusCode: 400, + body: 'Invalid request', + } + } +}