From fdebf7795d68853469ba2b512f4550e9c4099925 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 23 Oct 2020 16:10:18 -0500 Subject: [PATCH] Add domains check --- packages/next/build/webpack-config.ts | 6 +++++ packages/next/client/image.tsx | 10 ++++++++ .../{missing-width.js => invalid-src.js} | 6 ++++- .../default/test/index.test.js | 24 ++++++++++++++++++- 4 files changed, 44 insertions(+), 2 deletions(-) rename test/integration/image-component/default/pages/{missing-width.js => invalid-src.js} (65%) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 272ff411f253..d174521b7ad9 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -994,6 +994,12 @@ export default async function getBaseWebpackConfig( sizes: config.images.sizes, path: config.images.path, loader: config.images.loader, + ...(dev + ? { + // pass domains in development to allow validating on the client + domains: config.images.domains, + } + : {}), }), 'process.env.__NEXT_ROUTER_BASEPATH': JSON.stringify(config.basePath), 'process.env.__NEXT_HAS_REWRITES': JSON.stringify(hasRewrites), diff --git a/packages/next/client/image.tsx b/packages/next/client/image.tsx index 7ccdda73167b..3143d6a32ba9 100644 --- a/packages/next/client/image.tsx +++ b/packages/next/client/image.tsx @@ -358,6 +358,16 @@ function defaultLoader({ root, src, width, quality }: LoaderProps): string { )}` ) } + + if (src && !src.startsWith('/') && imageData.domains) { + const parsedSrc = new URL(src) + + if (!imageData.domains.includes(parsedSrc.hostname)) { + throw new Error( + `Invalid src prop (${src}) on \`next/image\`, hostname is not configured under images in your \`next.config.js\`` + ) + } + } } return `${root}?url=${encodeURIComponent(src)}&w=${width}&q=${ diff --git a/test/integration/image-component/default/pages/missing-width.js b/test/integration/image-component/default/pages/invalid-src.js similarity index 65% rename from test/integration/image-component/default/pages/missing-width.js rename to test/integration/image-component/default/pages/invalid-src.js index 6463d5b59b04..d77b883b6abd 100644 --- a/test/integration/image-component/default/pages/missing-width.js +++ b/test/integration/image-component/default/pages/invalid-src.js @@ -5,7 +5,11 @@ const Page = () => { return (

Hello World

- +

This is the index page

) diff --git a/test/integration/image-component/default/test/index.test.js b/test/integration/image-component/default/test/index.test.js index f698189e3b4f..66f0ed9c70f6 100644 --- a/test/integration/image-component/default/test/index.test.js +++ b/test/integration/image-component/default/test/index.test.js @@ -8,6 +8,8 @@ import { nextStart, nextBuild, check, + hasRedbox, + getRedboxHeader, } from 'next-test-utils' import webdriver from 'next-webdriver' import fs from 'fs-extra' @@ -20,7 +22,7 @@ const nextConfig = join(appDir, 'next.config.js') let appPort let app -function runTests() { +function runTests(mode) { it('should load the images', async () => { let browser try { @@ -73,6 +75,26 @@ function runTests() { } } }) + + if (mode === 'dev') { + it('should show missing src error', async () => { + const browser = await webdriver(appPort, '/missing-src') + + await hasRedbox(browser) + expect(await getRedboxHeader(browser)).toContain( + 'Next Image optimizer requires src to be provided. Make sure you pass them as props to the `next/image` component. Received: {"width":1200}' + ) + }) + + it('should show invalid src error', async () => { + const browser = await webdriver(appPort, '/invalid-src') + + await hasRedbox(browser) + expect(await getRedboxHeader(browser)).toContain( + 'Invalid src prop (https://google.com/test.png) on `next/image`, hostname is not configured under images in your `next.config.js`' + ) + }) + } } describe('Image Component Tests', () => {