diff --git a/package.json b/package.json index 932008e..9f880f6 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "axios": "^0.27.2", "cheerio": "1.0.0-rc.12", "next": "12.2.5", + "node-fetch": "^3.2.10", "react": "18.2.0", "react-dom": "18.2.0", "sharp": "^0.31.0" @@ -33,4 +34,4 @@ "node": ">=16.5.0", "pnpm": ">=7.0.0" } -} \ No newline at end of file +} diff --git a/src/pages/api/media_proxy.ts b/src/pages/api/media_proxy.ts new file mode 100644 index 0000000..98b9c93 --- /dev/null +++ b/src/pages/api/media_proxy.ts @@ -0,0 +1,83 @@ +import { NextApiRequest, NextApiResponse } from 'next' +import fetch from 'node-fetch' + +const acceptableExtensions = ['.jpg', '.png', '.gif', '.webp'] + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + // get query param + const mediaUrl = (req.query as { url: string }).url + + if (!mediaUrl) { + res.status(400) + res.send(null) + return + } + + let mediaUrlParsed: URL + + try { + mediaUrlParsed = new URL(mediaUrl) + } catch { + res.status(400) + res.send(null) + return + } + + // get media domain + const mediaDomain = mediaUrlParsed.hostname + + if (!mediaDomain.endsWith('media-amazon.com')) { + res.status(400) + res.send(null) + return + } + + if (mediaUrlParsed.protocol !== 'https:') { + res.status(400) + res.send(null) + return + } + + let validExtension = false + + for (const acceptableExtension of acceptableExtensions) { + if (mediaUrlParsed.pathname.endsWith(acceptableExtension)) { + validExtension = true + break + } + } + + if (!validExtension) { + res.status(400) + res.send(null) + return + } + + // download media + const mediaRes = await fetch(mediaUrl) + + if (!mediaRes.ok) { + res.status(mediaRes.status) + return + } + + // get media type + const mediaType = mediaRes.headers.get('content-type') + + if (!mediaType) { + res.status(500) + res.send(null) + return + } + + // set media type + res.setHeader('content-type', mediaType) + + const mediaBuffer = await mediaRes.arrayBuffer() + + // send media + res.send(Buffer.from(mediaBuffer)) +}