Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
})

expect(event.node.res.setHeader).toHaveBeenCalledWith('Content-Type', 'text/html')
expect(result).toBe('<html></html>')
expect(String(result)).toBe('<html></html>')
})
})

Expand Down Expand Up @@ -166,7 +166,25 @@
})

expect(event.node.res.setHeader).toHaveBeenCalledWith('Content-Type', contentType)
expect(result).toBe(fileContent)
expect(String(result)).toBe(fileContent)
})
})

test('serves binary files as a Buffer without UTF-8 corruption', async () => {
await inTemporaryDirectory(async (tmpDir: string) => {
// Bytes that are invalid as UTF-8 input (0x89, 0xFF, 0xFE) — if the
// middleware decoded these as UTF-8 they'd collapse to U+FFFD and the
// image would be corrupt. Includes the real PNG magic header.
const pngBytes = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0xff, 0xfe, 0x00, 0x42])
await mkdir(joinPath(tmpDir, 'img'))
await writeFile(joinPath(tmpDir, 'img', 'logo.png'), pngBytes)

const event = getMockEvent()
const result = await fileServerMiddleware(event, {filePath: joinPath(tmpDir, 'img', 'logo.png')})

expect(event.node.res.setHeader).toHaveBeenCalledWith('Content-Type', 'image/png')
expect(Buffer.isBuffer(result)).toBe(true)
expect(Buffer.compare(result as Buffer, pngBytes)).toBe(0)
})
})

Expand All @@ -183,7 +201,7 @@
})

expect(event.node.res.setHeader).toHaveBeenCalledWith('Content-Type', 'text/plain')
expect(result).toBe('Content for bar.foo')
expect(String(result)).toBe('Content for bar.foo')
})
})
})
Expand Down Expand Up @@ -244,7 +262,7 @@
const result = await getExtensionAssetMiddleware(options)(event)

expect(event.node.res.setHeader).toHaveBeenCalledWith('Content-Type', 'application/json')
expect(result).toBe('{"tools": []}')

Check failure on line 265 in packages/app/src/cli/services/dev/extension/server/middlewares.test.ts

View workflow job for this annotation

GitHub Actions / Unit tests with Node 24.1.0 in macos-latest

src/cli/services/dev/extension/server/middlewares.test.ts > getExtensionAssetMiddleware() > returns static asset from extension source directory

AssertionError: expected Buffer[ 123, 34, 116, 111, 111, …(-94) ] to be '{"tools": []}' // Object.is equality - Expected: "{\"tools\": []}" + Received: Buffer [ 123, 34, 116, 111, 111, 108, 115, 34, 58, 32, 91, 93, 125, ] ❯ src/cli/services/dev/extension/server/middlewares.test.ts:265:22 ❯ Module.inTemporaryDirectory ../cli-kit/src/public/node/fs.ts:81:12 ❯ src/cli/services/dev/extension/server/middlewares.test.ts:242:5

Check failure on line 265 in packages/app/src/cli/services/dev/extension/server/middlewares.test.ts

View workflow job for this annotation

GitHub Actions / Unit tests with Node 22.2.0 in macos-latest

src/cli/services/dev/extension/server/middlewares.test.ts > getExtensionAssetMiddleware() > returns static asset from extension source directory

AssertionError: expected Buffer[ 123, 34, 116, 111, 111, …(-94) ] to be '{"tools": []}' // Object.is equality - Expected: "{\"tools\": []}" + Received: Buffer [ 123, 34, 116, 111, 111, 108, 115, 34, 58, 32, 91, 93, 125, ] ❯ src/cli/services/dev/extension/server/middlewares.test.ts:265:22 ❯ Module.inTemporaryDirectory ../cli-kit/src/public/node/fs.ts:81:12 ❯ src/cli/services/dev/extension/server/middlewares.test.ts:242:5
})
})

Expand Down Expand Up @@ -275,7 +293,7 @@
const result = await getExtensionAssetMiddleware(options)(event)

expect(event.node.res.setHeader).toHaveBeenCalledWith('Content-Type', 'text/javascript')
expect(result).toBe('compiled bundle content')
expect(String(result)).toBe('compiled bundle content')
})
})

Expand Down Expand Up @@ -306,7 +324,7 @@
const result = await getExtensionAssetMiddleware(options)(event)

// Built asset takes priority
expect(result).toBe('built content')

Check failure on line 327 in packages/app/src/cli/services/dev/extension/server/middlewares.test.ts

View workflow job for this annotation

GitHub Actions / Unit tests with Node 24.1.0 in macos-latest

src/cli/services/dev/extension/server/middlewares.test.ts > getExtensionAssetMiddleware() > serves built asset over source file when both exist

AssertionError: expected Buffer[ 98, 117, 105, 108, 116, …(-18) ] to be 'built content' // Object.is equality - Expected: "built content" + Received: Buffer [ 98, 117, 105, 108, 116, 32, 99, 111, 110, 116, 101, 110, 116, ] ❯ src/cli/services/dev/extension/server/middlewares.test.ts:327:22 ❯ Module.inTemporaryDirectory ../cli-kit/src/public/node/fs.ts:81:12 ❯ src/cli/services/dev/extension/server/middlewares.test.ts:301:5

Check failure on line 327 in packages/app/src/cli/services/dev/extension/server/middlewares.test.ts

View workflow job for this annotation

GitHub Actions / Unit tests with Node 22.2.0 in macos-latest

src/cli/services/dev/extension/server/middlewares.test.ts > getExtensionAssetMiddleware() > serves built asset over source file when both exist

AssertionError: expected Buffer[ 98, 117, 105, 108, 116, …(-18) ] to be 'built content' // Object.is equality - Expected: "built content" + Received: Buffer [ 98, 117, 105, 108, 116, 32, 99, 111, 110, 116, 101, 110, 116, ] ❯ src/cli/services/dev/extension/server/middlewares.test.ts:327:22 ❯ Module.inTemporaryDirectory ../cli-kit/src/public/node/fs.ts:81:12 ❯ src/cli/services/dev/extension/server/middlewares.test.ts:301:5
})
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ export async function fileServerMiddleware(event: H3Event, options: {filePath: s
return sendError(event, {statusCode: 404, statusMessage: `Not Found: ${filePath}`})
}

const fileContent = await readFile(filePath)
// Pass `{}` to opt out of cli-kit's `{encoding: 'utf8'}` default — binary
// files (png, jpeg, pdf, wasm, …) must come back as a Buffer or their bytes
// get mangled into U+FFFD replacement chars by the UTF-8 decode. h3 sends
// Buffers as-is and the browser decodes per Content-Type for text types.
const fileContent = await readFile(filePath, {})
const extensionToContent = {
'.ico': 'image/x-icon',
'.html': 'text/html',
Expand Down
Loading