Skip to content

Commit a9c05bb

Browse files
committed
test: add node.js runtime specific middleware tests checking availability of crypto, path and http(s) node.js builtins
1 parent 0eae894 commit a9c05bb

File tree

9 files changed

+102
-13
lines changed

9 files changed

+102
-13
lines changed

tests/e2e/edge-middleware.test.ts renamed to tests/e2e/middleware.test.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@ type ExtendedFixtures = {
1616
edgeOrNodeMiddlewareStaticAssetMatcher: Fixture
1717
}
1818

19-
console.log({ hasNodeMiddlewareSupport: hasNodeMiddlewareSupport() })
20-
21-
for (const { expectedRuntime, label, testWithSwitchableMiddlewareRuntime } of [
19+
for (const { expectedRuntime, isNodeMiddleware, label, testWithSwitchableMiddlewareRuntime } of [
2220
{
2321
expectedRuntime: 'edge-runtime',
22+
isNodeMiddleware: false,
2423
label: 'Edge runtime middleware',
2524
testWithSwitchableMiddlewareRuntime: test.extend<{}, ExtendedFixtures>({
2625
edgeOrNodeMiddleware: [
@@ -68,6 +67,7 @@ for (const { expectedRuntime, label, testWithSwitchableMiddlewareRuntime } of [
6867
hasNodeMiddlewareSupport()
6968
? {
7069
expectedRuntime: 'node',
70+
isNodeMiddleware: true,
7171
label: 'Node.js runtime middleware',
7272
testWithSwitchableMiddlewareRuntime: test.extend<{}, ExtendedFixtures>({
7373
edgeOrNodeMiddleware: [
@@ -565,6 +565,40 @@ for (const { expectedRuntime, label, testWithSwitchableMiddlewareRuntime } of [
565565
)
566566
})
567567
})
568+
569+
if (isNodeMiddleware) {
570+
// Node.js Middleware specific tests to test features not available in Edge Runtime
571+
test.describe('Node.js Middleware specific', () => {
572+
test('node:crypto module', async ({ middlewareNodeRuntimeSpecific }) => {
573+
const response = await fetch(`${middlewareNodeRuntimeSpecific.url}/test/crypto`)
574+
expect(response.status).toBe(200)
575+
const body = await response.json()
576+
expect(
577+
body.random,
578+
'random should have 16 random bytes generated with `randomBytes` function from node:crypto in hex format',
579+
).toMatch(/[0-9a-f]{32}/)
580+
})
581+
582+
test('node:http(s) module', async ({ middlewareNodeRuntimeSpecific }) => {
583+
const response = await fetch(`${middlewareNodeRuntimeSpecific.url}/test/http`)
584+
expect(response.status).toBe(200)
585+
const body = await response.json()
586+
expect(
587+
body.proxiedWithHttpRequest,
588+
'proxiedWithHttpRequest should be the result of `http.request` from node:http fetching static asset',
589+
).toStrictEqual({ hello: 'world' })
590+
})
591+
592+
test('node:path module', async ({ middlewareNodeRuntimeSpecific }) => {
593+
const response = await fetch(`${middlewareNodeRuntimeSpecific.url}/test/path`)
594+
expect(response.status).toBe(200)
595+
const body = await response.json()
596+
expect(body.joined, 'joined should be the result of `join` function from node:path').toBe(
597+
'a/b',
598+
)
599+
})
600+
})
601+
}
568602
})
569603
}
570604

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { randomBytes } from 'node:crypto'
2+
import { request as httpRequest } from 'node:http'
3+
import { request as httpsRequest } from 'node:https'
4+
import { join } from 'node:path'
5+
6+
import { NextResponse } from 'next/server'
7+
import type { NextRequest } from 'next/server'
8+
9+
export async function middleware(request: NextRequest) {
10+
// this middleware is using Node.js APIs that are not available in Edge Runtime in very simple way to assert support for them
11+
if (request.nextUrl.pathname === '/test/crypto') {
12+
return NextResponse.json({ random: randomBytes(16).toString('hex') })
13+
}
14+
15+
if (request.nextUrl.pathname === '/test/http') {
16+
const body = await new Promise((resolve, reject) => {
17+
const origin =
18+
typeof Netlify !== 'undefined'
19+
? `https://${Netlify.context.deploy.id}--${Netlify.context.site.name}.netlify.app`
20+
: `http://localhost:3000`
21+
22+
const target = new URL('/http-test-target.json', origin)
23+
24+
const httpOrHttpsRequest = target.protocol === 'https:' ? httpsRequest : httpRequest
25+
26+
const req = httpOrHttpsRequest(target, (res) => {
27+
if (res.statusCode !== 200) {
28+
reject(new Error(`Failed to fetch ${target}: ${res.statusCode}`))
29+
// Consume response data to free up memory
30+
res.resume()
31+
return
32+
}
33+
34+
res.setEncoding('utf8')
35+
let rawData = ''
36+
res.on('data', (chunk) => {
37+
rawData += chunk
38+
})
39+
res.on('end', () => {
40+
try {
41+
resolve(JSON.parse(rawData))
42+
} catch (e) {
43+
reject(e)
44+
}
45+
})
46+
})
47+
req.end()
48+
console.log({ target })
49+
})
50+
return NextResponse.json({ proxiedWithHttpRequest: body })
51+
}
52+
53+
if (request.nextUrl.pathname === '/test/path') {
54+
return NextResponse.json({ joined: join('a', 'b') })
55+
}
56+
}
57+
58+
export const config = {
59+
runtime: 'nodejs',
60+
}

tests/fixtures/middleware-node/package.json renamed to tests/fixtures/middleware-node-runtime-specific/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "middleware-node",
2+
"name": "middleware-node-runtime-specific",
33
"version": "0.1.0",
44
"private": true,
55
"scripts": {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"hello": "world"
3+
}

tests/fixtures/middleware-node/middleware.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

tests/utils/create-e2e-fixture.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ export const fixtureFactories = {
346346
buildCommand: getBuildFixtureVariantCommand('node-middleware'),
347347
publishDirectory: '.next-node-middleware',
348348
}),
349+
middlewareNodeRuntimeSpecific: () => createE2EFixture('middleware-node-runtime-specific'),
349350
middlewareI18n: () => createE2EFixture('middleware-i18n'),
350351
middlewareI18nNode: () =>
351352
createE2EFixture('middleware-i18n', {

0 commit comments

Comments
 (0)