@@ -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
@@ -486,7 +488,7 @@ export default class NextNodeServer extends BaseServer {
486
488
parsedUrl . search = stringifyQuery ( req , query )
487
489
488
490
const target = formatUrl ( parsedUrl )
489
- const proxy = new Proxy ( {
491
+ const proxy = new HttpProxy ( {
490
492
target,
491
493
changeOrigin : true ,
492
494
ignorePath : true ,
@@ -1306,6 +1308,14 @@ export default class NextNodeServer extends BaseServer {
1306
1308
}
1307
1309
}
1308
1310
1311
+ if ( originalBody ) {
1312
+ const noderequest = params . request as NodeNextRequest
1313
+ noderequest . originalRequest = enhanceIncomingMessage (
1314
+ noderequest . originalRequest ,
1315
+ originalBody . original ( )
1316
+ )
1317
+ }
1318
+
1309
1319
return result
1310
1320
}
1311
1321
@@ -1346,9 +1356,7 @@ export default class NextNodeServer extends BaseServer {
1346
1356
/**
1347
1357
* Creates a ReadableStream from a Node.js HTTP request
1348
1358
*/
1349
- function requestToBodyStream (
1350
- request : IncomingMessage
1351
- ) : ReadableStreamPolyfill < Uint8Array > {
1359
+ function requestToBodyStream ( request : IncomingMessage ) : BodyStream {
1352
1360
const transform = new TransformStream < Uint8Array , Uint8Array > ( {
1353
1361
start ( controller ) {
1354
1362
request . on ( 'data' , ( chunk ) => controller . enqueue ( chunk ) )
@@ -1357,21 +1365,61 @@ function requestToBodyStream(
1357
1365
} ,
1358
1366
} )
1359
1367
1360
- return transform . readable
1368
+ return transform . readable as unknown as ReadableStream < Uint8Array >
1361
1369
}
1362
1370
1363
1371
/**
1364
1372
* A simple utility to take an original stream and have
1365
1373
* an API to duplicate it without closing it or mutate any variables
1366
1374
*/
1367
- function teeableStream < T > ( originalStream : ReadableStreamPolyfill < T > ) : {
1368
- duplicate ( ) : ReadableStreamPolyfill < T >
1375
+ function teeableStream < T > ( originalStream : ReadableStream < T > ) : {
1376
+ duplicate ( ) : ReadableStream < T >
1377
+ original ( ) : ReadableStream < T >
1369
1378
} {
1370
1379
return {
1371
1380
duplicate ( ) {
1372
1381
const [ stream1 , stream2 ] = originalStream . tee ( )
1373
1382
originalStream = stream1
1374
1383
return stream2
1375
1384
} ,
1385
+ original ( ) {
1386
+ return originalStream
1387
+ } ,
1376
1388
}
1377
1389
}
1390
+
1391
+ function bodyStreamToNodeStream ( bodyStream : BodyStream ) : NodeStreams . Readable {
1392
+ const reader = bodyStream . getReader ( )
1393
+ return NodeStreams . Readable . from (
1394
+ ( async function * ( ) {
1395
+ while ( true ) {
1396
+ const { done, value } = await reader . read ( )
1397
+ if ( done ) {
1398
+ return
1399
+ }
1400
+ yield value
1401
+ }
1402
+ } ) ( )
1403
+ )
1404
+ }
1405
+
1406
+ function enhanceIncomingMessage < T extends IncomingMessage > (
1407
+ base : T ,
1408
+ body : BodyStream
1409
+ ) : T {
1410
+ const stream = bodyStreamToNodeStream ( body )
1411
+ return new Proxy < T > ( base , {
1412
+ get ( target , name ) {
1413
+ if ( name in stream ) {
1414
+ const v = stream [ name ]
1415
+ if ( typeof v === 'function' ) {
1416
+ return v . bind ( stream )
1417
+ } else {
1418
+ return v
1419
+ }
1420
+ }
1421
+
1422
+ return target [ name ]
1423
+ } ,
1424
+ } )
1425
+ }
0 commit comments