@@ -42,6 +42,41 @@ function collectFromNextUrl(input: Request): NextConfig | undefined {
4242 return config && Object . keys ( config ) . length ? config : undefined ;
4343}
4444
45+ function tryCloneRequest ( input : Request ) : Request | null {
46+ if ( typeof ( input as any ) . clone !== "function" ) {
47+ return null ;
48+ }
49+
50+ try {
51+ return input . clone ( ) ;
52+ } catch {
53+ return null ;
54+ }
55+ }
56+
57+ function getSafeBody ( input : any ) : BodyInit | null | undefined {
58+ if ( ! ( "body" in input ) ) {
59+ return undefined ;
60+ }
61+
62+ const body = input . body ;
63+
64+ if ( body == null ) {
65+ return body ;
66+ }
67+
68+ if ( input . bodyUsed ) {
69+ return undefined ;
70+ }
71+
72+ const locked = ( body as any ) . locked ;
73+ if ( typeof locked === "boolean" && locked ) {
74+ return undefined ;
75+ }
76+
77+ return body as BodyInit ;
78+ }
79+
4580/**
4681 * Normalize a Request or NextRequest to a NextRequest instance.
4782 * Ensures consistent behavior across Next.js 15 (Edge) and 16 (Node Proxy).
@@ -54,18 +89,22 @@ export function toNextRequest(input: Request | NextRequest): NextRequest {
5489
5590 const nextConfig = collectFromNextUrl ( input ) ;
5691
92+ const source =
93+ input instanceof Request ? ( tryCloneRequest ( input ) ?? input ) : input ;
94+ const body = getSafeBody ( source ) ;
95+
5796 const init : any = {
58- method : input . method ,
59- headers : input . headers ,
60- body : input . body as any ,
61- duplex : ( input as any ) . duplex ?? "half"
97+ method : source . method ,
98+ headers : source . headers ,
99+ duplex : ( source as any ) . duplex ?? "half" ,
100+ ... ( body !== undefined ? { body } : { } )
62101 } ;
63102
64103 if ( nextConfig ) {
65104 init . nextConfig = nextConfig ;
66105 }
67106
68- return new NextRequest ( input . url , init ) ;
107+ return new NextRequest ( source . url , init ) ;
69108}
70109
71110/**
0 commit comments