@@ -32,16 +32,35 @@ export function formatContentLength(
32
32
const len = headers [ "content-length" ] ;
33
33
if ( len && typeof len === "string" ) {
34
34
const bytes = parseInt ( len , 10 ) ;
35
- return isNaN ( bytes ) ? "(?b )" : `(${ prettyBytes ( bytes ) } )` ;
35
+ return isNaN ( bytes ) ? "(?B )" : `(${ prettyBytes ( bytes ) } )` ;
36
36
}
37
37
38
38
// Estimate from data if no header
39
- if ( data !== undefined && data !== null ) {
40
- const estimated = Buffer . byteLength ( JSON . stringify ( data ) , "utf8" ) ;
41
- return `(~${ prettyBytes ( estimated ) } )` ;
39
+
40
+ if ( data === undefined || data === null ) {
41
+ return `(${ prettyBytes ( 0 ) } )` ;
42
+ }
43
+
44
+ if ( Buffer . isBuffer ( data ) ) {
45
+ return `(${ prettyBytes ( data . byteLength ) } )` ;
46
+ }
47
+ if ( typeof data === "string" || typeof data === "bigint" ) {
48
+ const bytes = Buffer . byteLength ( data . toString ( ) , "utf8" ) ;
49
+ return `(${ prettyBytes ( bytes ) } )` ;
50
+ }
51
+ if ( typeof data === "number" || typeof data === "boolean" ) {
52
+ return `(~${ prettyBytes ( 8 ) } )` ;
53
+ }
54
+
55
+ if ( typeof data === "object" ) {
56
+ const stringified = safeStringify ( data ) ;
57
+ if ( stringified !== null ) {
58
+ const bytes = Buffer . byteLength ( stringified , "utf8" ) ;
59
+ return `(~${ prettyBytes ( bytes ) } )` ;
60
+ }
42
61
}
43
62
44
- return `( ${ prettyBytes ( 0 ) } )` ;
63
+ return "(?B)" ;
45
64
}
46
65
47
66
export function formatUri (
@@ -66,8 +85,38 @@ export function formatHeaders(headers: Record<string, unknown>): string {
66
85
67
86
export function formatBody ( body : unknown ) : string {
68
87
if ( body ) {
69
- return JSON . stringify ( body ) ;
88
+ return safeStringify ( body ) ?? "<invalid body>" ;
70
89
} else {
71
90
return "<no body>" ;
72
91
}
73
92
}
93
+
94
+ function safeStringify ( data : unknown ) : string | null {
95
+ try {
96
+ const seen = new WeakSet ( ) ;
97
+ return JSON . stringify ( data , ( _key , value ) => {
98
+ // Handle circular references
99
+ if ( typeof value === "object" && value !== null ) {
100
+ if ( seen . has ( value ) ) {
101
+ return "[Circular]" ;
102
+ }
103
+ seen . add ( value ) ;
104
+ }
105
+
106
+ // Handle special types that might slip through
107
+ if ( typeof value === "function" ) {
108
+ return "[Function]" ;
109
+ }
110
+ if ( typeof value === "symbol" ) {
111
+ return "[Symbol]" ;
112
+ }
113
+ if ( typeof value === "bigint" ) {
114
+ return value . toString ( ) ;
115
+ }
116
+
117
+ return value ;
118
+ } ) ;
119
+ } catch {
120
+ return null ;
121
+ }
122
+ }
0 commit comments