diff --git a/package-lock.json b/package-lock.json index 84ebea260c..4e2ab75221 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4553,11 +4553,11 @@ } }, "node_modules/@netlify/ipx": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@netlify/ipx/-/ipx-1.2.5.tgz", - "integrity": "sha512-zBPRsLHlFkN8uYAFbbTMZr6oTnVWUdME8i+FfeOY9D5qBbbSFxSH/ZPECif0ojkhtRnutq9+cN0mnnCTaYRjQw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@netlify/ipx/-/ipx-1.3.0.tgz", + "integrity": "sha512-lBM50f1sgbwCl3hWFKS9VI4W2PjrNf9Rzg5eoazB6+VAHqy2181Uis2hT/rfqG1qWjgakj+Ei/h2Nr8Sg7U9eQ==", "dependencies": { - "@netlify/functions": "^1.2.0", + "@netlify/functions": "^1.3.0", "etag": "^1.8.1", "fs-extra": "^10.0.0", "ipx": "^0.9.11", @@ -5556,13 +5556,13 @@ "version": "15.7.5", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "devOptional": true + "dev": true }, "node_modules/@types/react": { "version": "17.0.50", "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.50.tgz", "integrity": "sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==", - "devOptional": true, + "dev": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -5588,7 +5588,7 @@ "version": "0.16.2", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "devOptional": true + "dev": true }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.1", @@ -9128,7 +9128,7 @@ "version": "3.0.11", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "devOptional": true + "dev": true }, "node_modules/custom-routes": { "resolved": "demos/custom-routes", @@ -13154,7 +13154,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", - "devOptional": true + "dev": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -20324,7 +20324,7 @@ "version": "1.50.1", "resolved": "https://registry.npmjs.org/sass/-/sass-1.50.1.tgz", "integrity": "sha512-noTnY41KnlW2A9P8sdwESpDmo+KBNkukI1i8+hOK3footBUcohNHtdOJbckp46XO95nuvcHDDZ+4tmOnpK3hjw==", - "devOptional": true, + "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -23326,12 +23326,12 @@ }, "packages/runtime": { "name": "@netlify/plugin-nextjs", - "version": "4.24.0", + "version": "4.24.1", "license": "MIT", "dependencies": { "@netlify/esbuild": "0.14.39", "@netlify/functions": "^1.3.0", - "@netlify/ipx": "^1.2.5", + "@netlify/ipx": "^1.3.0", "@vercel/node-bridge": "^2.1.0", "chalk": "^4.1.2", "destr": "^1.1.1", @@ -25834,8 +25834,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", - "dev": true, - "requires": {} + "dev": true }, "chalk": { "version": "5.0.1", @@ -26186,8 +26185,7 @@ "version": "17.0.0", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", - "dev": true, - "requires": {} + "dev": true }, "eslint-import-resolver-typescript": { "version": "3.3.0", @@ -26264,11 +26262,11 @@ } }, "@netlify/ipx": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@netlify/ipx/-/ipx-1.2.5.tgz", - "integrity": "sha512-zBPRsLHlFkN8uYAFbbTMZr6oTnVWUdME8i+FfeOY9D5qBbbSFxSH/ZPECif0ojkhtRnutq9+cN0mnnCTaYRjQw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@netlify/ipx/-/ipx-1.3.0.tgz", + "integrity": "sha512-lBM50f1sgbwCl3hWFKS9VI4W2PjrNf9Rzg5eoazB6+VAHqy2181Uis2hT/rfqG1qWjgakj+Ei/h2Nr8Sg7U9eQ==", "requires": { - "@netlify/functions": "^1.2.0", + "@netlify/functions": "^1.3.0", "etag": "^1.8.1", "fs-extra": "^10.0.0", "ipx": "^0.9.11", @@ -26309,7 +26307,7 @@ "@netlify/build": "^27.20.1", "@netlify/esbuild": "0.14.39", "@netlify/functions": "^1.3.0", - "@netlify/ipx": "^1.2.5", + "@netlify/ipx": "^1.3.0", "@types/fs-extra": "^9.0.13", "@types/jest": "^27.4.1", "@types/merge-stream": "^1.1.2", @@ -27101,13 +27099,13 @@ "version": "15.7.5", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "devOptional": true + "dev": true }, "@types/react": { "version": "17.0.50", "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.50.tgz", "integrity": "sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==", - "devOptional": true, + "dev": true, "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -27133,7 +27131,7 @@ "version": "0.16.2", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "devOptional": true + "dev": true }, "@types/sinonjs__fake-timers": { "version": "8.1.1", @@ -27441,8 +27439,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "acorn-walk": { "version": "7.2.0", @@ -29803,7 +29800,7 @@ "version": "3.0.11", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "devOptional": true + "dev": true }, "custom-routes": { "version": "file:demos/custom-routes", @@ -30933,8 +30930,7 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} + "dev": true }, "eslint-formatter-codeframe": { "version": "7.32.1", @@ -31379,8 +31375,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz", "integrity": "sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw==", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-react": { "version": "7.29.4", @@ -31428,8 +31423,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.5.0.tgz", "integrity": "sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw==", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-unicorn": { "version": "43.0.2", @@ -32902,7 +32896,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", - "devOptional": true + "dev": true }, "import-fresh": { "version": "3.3.0", @@ -33964,8 +33958,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "requires": {} + "dev": true }, "jest-regex-util": { "version": "27.5.1", @@ -38387,7 +38380,7 @@ "version": "1.50.1", "resolved": "https://registry.npmjs.org/sass/-/sass-1.50.1.tgz", "integrity": "sha512-noTnY41KnlW2A9P8sdwESpDmo+KBNkukI1i8+hOK3footBUcohNHtdOJbckp46XO95nuvcHDDZ+4tmOnpK3hjw==", - "devOptional": true, + "dev": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -38648,14 +38641,12 @@ "styled-jsx": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.2.tgz", - "integrity": "sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==", - "requires": {} + "integrity": "sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==" }, "use-sync-external-store": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.1.0.tgz", - "integrity": "sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==", - "requires": {} + "integrity": "sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==" } } }, @@ -39467,8 +39458,7 @@ "styled-jsx": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.6.tgz", - "integrity": "sha512-xOeROtkK5MGMDimBQ3J6iPId8q0t/BDoG5XN6oKkZClVz9ISF/hihN8OCn2LggMU6N32aXnrXBdn3auSqNS9fA==", - "requires": {} + "integrity": "sha512-xOeROtkK5MGMDimBQ3J6iPId8q0t/BDoG5XN6oKkZClVz9ISF/hihN8OCn2LggMU6N32aXnrXBdn3auSqNS9fA==" }, "supports-color": { "version": "9.2.2", @@ -40190,8 +40180,7 @@ "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "requires": {} + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" } } }, @@ -40299,8 +40288,7 @@ "use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "requires": {} + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==" }, "util-deprecate": { "version": "1.0.2", @@ -40705,8 +40693,7 @@ "version": "7.5.7", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "requires": {} + "dev": true }, "xdg-basedir": { "version": "4.0.0", diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 5f2bb454d7..ed47a00bc4 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -12,7 +12,7 @@ "dependencies": { "@netlify/esbuild": "0.14.39", "@netlify/functions": "^1.3.0", - "@netlify/ipx": "^1.2.5", + "@netlify/ipx": "^1.3.0", "@vercel/node-bridge": "^2.1.0", "chalk": "^4.1.2", "destr": "^1.1.1", diff --git a/packages/runtime/src/templates/edge/ipx.ts b/packages/runtime/src/templates/edge/ipx.ts index 9f8313a6d8..7c3f5c010e 100644 --- a/packages/runtime/src/templates/edge/ipx.ts +++ b/packages/runtime/src/templates/edge/ipx.ts @@ -9,6 +9,9 @@ interface ImageConfig extends Record { formats?: string[] } +// Checks if a URL param is numeric +const isNumeric = (value: string | null) => Number(value).toString() === value + /** * Implement content negotiation for images */ @@ -28,10 +31,28 @@ const handler = async (req: Request, context: Context) => { const source = searchParams.get('url') const width = searchParams.get('w') - const quality = searchParams.get('q') ?? 75 + const quality = searchParams.get('q') ?? '75' + + const errors: Array = [] + + if (!source) { + errors.push('Missing "url" parameter') + } else if (!source.startsWith('http') && !source.startsWith('/')) { + errors.push('The "url" parameter must be a valid URL or path') + } + + if (!width) { + errors.push('Missing "w" parameter') + } else if (!isNumeric(width)) { + errors.push('Invalid "w" parameter') + } + + if (!isNumeric(quality)) { + errors.push('Invalid "q" parameter') + } - if (!source || !width) { - return new Response('Invalid request', { + if (!source || errors.length > 0) { + return new Response(`Invalid request: \n${errors.join('\n')}`, { status: 400, }) } diff --git a/packages/runtime/src/templates/ipx.ts b/packages/runtime/src/templates/ipx.ts index fe385290c1..dcf145fa1b 100644 --- a/packages/runtime/src/templates/ipx.ts +++ b/packages/runtime/src/templates/ipx.ts @@ -10,5 +10,6 @@ export const handler: Handler = createIPXHandler({ domains, remotePatterns, responseHeaders, + localPrefix: '/_next/static/media/', }) as Handler /* eslint-enable n/no-missing-import, import/no-unresolved, @typescript-eslint/ban-ts-comment */