Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions apps/koa-esm/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,45 @@ router.get('/fetch', async (ctx) => {
ctx.body = data
})

// Test case 1: text/plain + JSON body
router.get('/post-text-plain', async (ctx) => {
const res = await axios.post(
'https://jsonplaceholder.typicode.com/posts',
JSON.stringify({ title: 'foo', body: 'bar', userId: 1 }),
{ headers: { 'Content-Type': 'text/plain' } }
)
ctx.body = res.data
})

// Test case 2: application/x-www-form-urlencoded
router.get('/post-form', async (ctx) => {
const res = await axios.post(
'https://jsonplaceholder.typicode.com/posts',
'title=foo&body=bar&userId=1',
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
)
ctx.body = res.data
})

// Test case 3: pure text body
router.get('/post-pure-text', async (ctx) => {
const res = await axios.post(
'https://jsonplaceholder.typicode.com/posts',
'This is a plain text message',
{ headers: { 'Content-Type': 'text/plain' } }
)
ctx.body = res.data
})

// Test case 4: Buffer body
router.get('/post-buffer', async (ctx) => {
const buffer = Buffer.from(JSON.stringify({ title: 'buffer', body: 'test', userId: 1 }))
const res = await axios.post('https://jsonplaceholder.typicode.com/posts', buffer, {
headers: { 'Content-Type': 'application/json' }
})
ctx.body = res.data
})

// SSE test endpoint - server side
router.get('/sse-server', async (ctx) => {
ctx.set('Content-Type', 'text/event-stream')
Expand All @@ -90,7 +129,9 @@ router.get('/sse-server', async (ctx) => {
let count = 0
const interval = setInterval(() => {
count++
res.write(`event: message\nid: ${count}\ndata: {"count": ${count}, "time": "${new Date().toISOString()}"}\n\n`)
res.write(
`event: message\nid: ${count}\ndata: {"count": ${count}, "time": "${new Date().toISOString()}"}\n\n`
)
if (count >= 5) {
clearInterval(interval)
res.end()
Expand All @@ -102,18 +143,18 @@ router.get('/sse-server', async (ctx) => {
router.get('/sse-fetch', async (ctx) => {
// Fetch SSE from our own server
const response = await fetch('http://localhost:3001/sse-server')

// Consume the stream to capture events
const reader = response.body.getReader()
const decoder = new TextDecoder()
let result = ''

while (true) {
const { done, value } = await reader.read()
if (done) break
result += decoder.decode(value, { stream: true })
}

ctx.body = { message: 'SSE stream consumed', data: result }
})

Expand Down
21 changes: 17 additions & 4 deletions packages/network-debugger/src/core/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,23 @@ function proxyClientRequestFactory(
) {
const actualFn = actualRequest.write
actualRequest.write = (data: any) => {
try {
requestDetail.requestData = JSON.parse(data.toString())
} catch (err) {
requestDetail.requestData = data
// Convert to string at source to avoid IPC serialization issues
// Accumulate multiple writes (e.g., multipart/form-data)
let chunk: string
if (Buffer.isBuffer(data)) {
chunk = data.toString('utf-8')
} else if (typeof data === 'string') {
chunk = data
} else if (data != null) {
chunk = JSON.stringify(data)
} else {
chunk = ''
}

if (requestDetail.requestData) {
requestDetail.requestData += chunk
} else {
requestDetail.requestData = chunk
}

return actualFn.bind(actualRequest)(data)
Expand Down
8 changes: 1 addition & 7 deletions packages/network-debugger/src/fork/module/network/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,7 @@ export const networkPlugin = createPlugin('network', ({ devtool, core }) => {
headers: headerPipe.getData(),
initialPriority: 'High',
mixedContentType: 'none',
...(request.requestData
? {
postData: contentType?.includes('application/json')
? JSON.stringify(request.requestData)
: request.requestData
}
: {})
...(request.requestData ? { postData: request.requestData.toString() } : {})
},
timestamp: devtool.timestamp,
wallTime: request.requestStartTime,
Expand Down