@@ -8,8 +8,8 @@ import type { ParsedNextUrl } from '../shared/lib/router/utils/parse-next-url'
8
8
import type { PrerenderManifest } from '../build'
9
9
import type { Rewrite } from '../lib/load-custom-routes'
10
10
import type { BaseNextRequest , BaseNextResponse } from './base-http'
11
- import type { ReadableStream as ReadableStreamPolyfill } from 'next/dist/compiled/web-streams-polyfill/ponyfill'
12
11
import { TransformStream } from 'next/dist/compiled/web-streams-polyfill/ponyfill'
12
+ import NodeStreams from 'stream'
13
13
14
14
import { execOnce } from '../shared/lib/utils'
15
15
import {
@@ -40,7 +40,7 @@ import { PagesManifest } from '../build/webpack/plugins/pages-manifest-plugin'
40
40
import { recursiveReadDirSync } from './lib/recursive-readdir-sync'
41
41
import { format as formatUrl , UrlWithParsedQuery } from 'url'
42
42
import compression from 'next/dist/compiled/compression'
43
- import Proxy from 'next/dist/compiled/http-proxy'
43
+ import HttpProxy from 'next/dist/compiled/http-proxy'
44
44
import { route } from './router'
45
45
import { run } from './web/sandbox'
46
46
@@ -92,6 +92,8 @@ export interface NodeRequestHandler {
92
92
) : Promise < void >
93
93
}
94
94
95
+ type BodyStream = ReadableStream < Uint8Array >
96
+
95
97
export default class NextNodeServer extends BaseServer {
96
98
private imageResponseCache ?: ResponseCache
97
99
@@ -490,7 +492,7 @@ export default class NextNodeServer extends BaseServer {
490
492
parsedUrl . search = stringifyQuery ( req , query )
491
493
492
494
const target = formatUrl ( parsedUrl )
493
- const proxy = new Proxy ( {
495
+ const proxy = new HttpProxy ( {
494
496
target,
495
497
changeOrigin : true ,
496
498
ignorePath : true ,
@@ -1310,6 +1312,14 @@ export default class NextNodeServer extends BaseServer {
1310
1312
}
1311
1313
}
1312
1314
1315
+ if ( originalBody ) {
1316
+ const noderequest = params . request as NodeNextRequest
1317
+ noderequest . originalRequest = enhanceIncomingMessage (
1318
+ noderequest . originalRequest ,
1319
+ originalBody . original ( )
1320
+ )
1321
+ }
1322
+
1313
1323
return result
1314
1324
}
1315
1325
@@ -1350,9 +1360,7 @@ export default class NextNodeServer extends BaseServer {
1350
1360
/**
1351
1361
* Creates a ReadableStream from a Node.js HTTP request
1352
1362
*/
1353
- function requestToBodyStream (
1354
- request : IncomingMessage
1355
- ) : ReadableStreamPolyfill < Uint8Array > {
1363
+ function requestToBodyStream ( request : IncomingMessage ) : BodyStream {
1356
1364
const transform = new TransformStream < Uint8Array , Uint8Array > ( {
1357
1365
start ( controller ) {
1358
1366
request . on ( 'data' , ( chunk ) => controller . enqueue ( chunk ) )
@@ -1361,21 +1369,61 @@ function requestToBodyStream(
1361
1369
} ,
1362
1370
} )
1363
1371
1364
- return transform . readable
1372
+ return transform . readable as unknown as ReadableStream < Uint8Array >
1365
1373
}
1366
1374
1367
1375
/**
1368
1376
* A simple utility to take an original stream and have
1369
1377
* an API to duplicate it without closing it or mutate any variables
1370
1378
*/
1371
- function teeableStream < T > ( originalStream : ReadableStreamPolyfill < T > ) : {
1372
- duplicate ( ) : ReadableStreamPolyfill < T >
1379
+ function teeableStream < T > ( originalStream : ReadableStream < T > ) : {
1380
+ duplicate ( ) : ReadableStream < T >
1381
+ original ( ) : ReadableStream < T >
1373
1382
} {
1374
1383
return {
1375
1384
duplicate ( ) {
1376
1385
const [ stream1 , stream2 ] = originalStream . tee ( )
1377
1386
originalStream = stream1
1378
1387
return stream2
1379
1388
} ,
1389
+ original ( ) {
1390
+ return originalStream
1391
+ } ,
1380
1392
}
1381
1393
}
1394
+
1395
+ function bodyStreamToNodeStream ( bodyStream : BodyStream ) : NodeStreams . Readable {
1396
+ const reader = bodyStream . getReader ( )
1397
+ return NodeStreams . Readable . from (
1398
+ ( async function * ( ) {
1399
+ while ( true ) {
1400
+ const { done, value } = await reader . read ( )
1401
+ if ( done ) {
1402
+ return
1403
+ }
1404
+ yield value
1405
+ }
1406
+ } ) ( )
1407
+ )
1408
+ }
1409
+
1410
+ function enhanceIncomingMessage < T extends IncomingMessage > (
1411
+ base : T ,
1412
+ body : BodyStream
1413
+ ) : T {
1414
+ const stream = bodyStreamToNodeStream ( body )
1415
+ return new Proxy < T > ( base , {
1416
+ get ( target , name ) {
1417
+ if ( name in stream ) {
1418
+ const v = stream [ name ]
1419
+ if ( typeof v === 'function' ) {
1420
+ return v . bind ( stream )
1421
+ } else {
1422
+ return v
1423
+ }
1424
+ }
1425
+
1426
+ return target [ name ]
1427
+ } ,
1428
+ } )
1429
+ }
0 commit comments