Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/runtime/src/helpers/edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ export const loadPrerenderManifest = (netlifyConfig: NetlifyConfig): Promise<Pre
*/
const sanitizeName = (name: string) => `next_${name.replace(/\W/g, '_')}`

/**
* Convert the images path to strip the origin (until domain-level Edge functions are supported)
*/
export const sanitizeEdgePath = (imagesPath: string) => new URL(imagesPath, process.env.URL || 'http://n').pathname

// Slightly different spacing in different versions!
const IMPORT_UNSUPPORTED = [
`Object.defineProperty(globalThis,"__import_unsupported"`,
Expand Down Expand Up @@ -485,10 +490,11 @@ export const writeEdgeFunctions = async ({
join('.netlify', 'functions-internal', IMAGE_FUNCTION_NAME, 'imageconfig.json'),
join(edgeFunctionDir, 'imageconfig.json'),
)

manifest.functions.push({
function: 'ipx',
name: 'next/image handler',
path: nextConfig.images.path || '/_next/image',
path: nextConfig.images.path ? sanitizeEdgePath(nextConfig.images.path) : '/_next/image',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be good to either have a unit test checking that it gets sanitized when needed or we could update a demo site with a full images path in a Next config to validate the fix.

generator,
})

Expand Down
23 changes: 22 additions & 1 deletion test/helpers/matchers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getEdgeFunctionPatternForPage } from '../../packages/runtime/src/helpers/edge'
import { getEdgeFunctionPatternForPage, sanitizeEdgePath } from '../../packages/runtime/src/helpers/edge'
import { makeLocaleOptional, stripLookahead } from '../../packages/runtime/src/helpers/matchers'

const makeDataPath = (path: string) => `/_next/data/build-id${path === '/' ? '/index' : path}.json`
Expand Down Expand Up @@ -183,3 +183,24 @@ describe('the edge function matcher helpers', () => {
expect('/edge/1/').toMatch(new RegExp(regex))
})
})

describe('the images path is sanitized', () => {
it('passes through a path', () => {
expect(sanitizeEdgePath('/_next/image')).toBe('/_next/image')
})

it('strips domains', () => {
expect(sanitizeEdgePath('http://example.com/_next/image')).toBe('/_next/image')
expect(sanitizeEdgePath('https://example.com/_next/image')).toBe('/_next/image')
})

it('strips domains with globs', () => {
expect(sanitizeEdgePath('http://example.com/_next/image/*')).toBe('/_next/image/*')
expect(sanitizeEdgePath('https://example.com/_next/image/*')).toBe('/_next/image/*')
})

it('strips domains with tokens', () => {
expect(sanitizeEdgePath('http://example.com/_next/image/:slug/')).toBe('/_next/image/:slug/')
expect(sanitizeEdgePath('https://example.com/_next/image/:slug/')).toBe('/_next/image/:slug/')
})
})