@@ -130,7 +130,8 @@ class MultipartState(IntEnum):
130
130
PART_DATA_START = 8
131
131
PART_DATA = 9
132
132
PART_DATA_END = 10
133
- END = 11
133
+ END_BOUNDARY = 11
134
+ END = 12
134
135
135
136
136
137
# Flags for the multipart parser.
@@ -1119,7 +1120,10 @@ def data_callback(name: CallbackName, end_i: int, remaining: bool = False) -> No
1119
1120
# Check to ensure that the last 2 characters in our boundary
1120
1121
# are CRLF.
1121
1122
if index == len (boundary ) - 2 :
1122
- if c != CR :
1123
+ if c == HYPHEN :
1124
+ # Potential empty message.
1125
+ state = MultipartState .END_BOUNDARY
1126
+ elif c != CR :
1123
1127
# Error!
1124
1128
msg = "Did not find CR at end of boundary (%d)" % (i ,)
1125
1129
self .logger .warning (msg )
@@ -1396,6 +1400,18 @@ def data_callback(name: CallbackName, end_i: int, remaining: bool = False) -> No
1396
1400
# the start of the boundary itself.
1397
1401
i -= 1
1398
1402
1403
+ elif state == MultipartState .END_BOUNDARY :
1404
+ if index == len (boundary ) - 2 + 1 :
1405
+ if c != HYPHEN :
1406
+ msg = "Did not find - at end of boundary (%d)" % (i ,)
1407
+ self .logger .warning (msg )
1408
+ e = MultipartParseError (msg )
1409
+ e .offset = i
1410
+ raise e
1411
+ index += 1
1412
+ self .callback ("end" )
1413
+ state = MultipartState .END
1414
+
1399
1415
elif state == MultipartState .END :
1400
1416
# Don't do anything if chunk ends with CRLF.
1401
1417
if c == CR and i + 1 < length and data [i + 1 ] == LF :
@@ -1707,8 +1723,8 @@ def on_headers_finished() -> None:
1707
1723
1708
1724
def _on_end () -> None :
1709
1725
nonlocal writer
1710
- assert writer is not None
1711
- writer .finalize ()
1726
+ if writer is not None :
1727
+ writer .finalize ()
1712
1728
if self .on_end is not None :
1713
1729
self .on_end ()
1714
1730
0 commit comments