@@ -285,6 +285,57 @@ class MultipartTest {
285285 assertEquals(" epilogue" , epilogue.body.readText())
286286 }
287287
288+ @OptIn(DelicateCoroutinesApi ::class )
289+ @Test
290+ fun testEmptyPart () = runBlocking {
291+ val body = """
292+ POST /send-message.html HTTP/1.1
293+ Host: webmail.example.com
294+ Referer: http://webmail.example.com/send-message.html
295+ User-Agent: BrowserForDummies/4.67b
296+ Content-Type: multipart/form-data; boundary=Asrf456BGe4h
297+ Connection: close
298+ Keep-Alive: 300
299+
300+ preamble
301+ --Asrf456BGe4h
302+ Content-Disposition: form-data; name="DestAddress"
303+
304+ recipient@example.com
305+ --Asrf456BGe4h
306+ --Asrf456BGe4h
307+ Content-Disposition: form-data; name="MessageText"
308+
309+ See attachments...
310+ --Asrf456BGe4h
311+ --Asrf456BGe4h--
312+ epilogue
313+ """ .trimIndent()
314+ .lines()
315+ .joinToString(" \r\n " )
316+
317+ val ch = ByteReadChannel (body.toByteArray())
318+ val request = parseRequest(ch)!!
319+ val mp = parseMultipart(ch, request.headers)
320+
321+ val allEvents = ArrayList <MultipartEvent >()
322+ mp.consumeEach { allEvents.add(it) }
323+
324+ assertEquals(4 , allEvents.size)
325+
326+ val preamble = allEvents[0 ] as MultipartEvent .Preamble
327+ assertEquals(" preamble\r\n " , preamble.body.readText())
328+
329+ val recipient = allEvents[1 ] as MultipartEvent .MultipartPart
330+ assertEquals(" recipient@example.com" , recipient.body.readRemaining().readText())
331+
332+ val text = allEvents[2 ] as MultipartEvent .MultipartPart
333+ assertEquals(" See attachments..." , text.body.readRemaining().readText())
334+
335+ val epilogue = allEvents[3 ] as MultipartEvent .Epilogue
336+ assertEquals(" epilogue" , epilogue.body.readText())
337+ }
338+
288339 @Test
289340 fun testParseBoundary () {
290341 testBoundary(" \r\n --A" , " multipart/mixed;boundary=A" )
0 commit comments