Misleading IO Exceptions When MultiPart Boundary Marker Contains Capital Letters
inex0rable opened this issue ยท 3 comments
I have edited this post to remove verbose code and include a test project I have created to better illustrate the problem. First bug report - please forgive my lack of finnesse :)
My current suspicion is that there is an important bug somewhere in the MultipartReader.ReadNextSectionAsync() chain that results in a misleading System.IO exception if the form data has a capital letter in its boundary marker.
For instance, server code that succeeds when called from IE and Firefox fails using Chrome (results in the exception: "IOException: Unexpected end of Stream, the content may have already been read by another component") - I suspect this is because the webkit boundary marker contains the string "WebKit" and thus contains capital letters.
I have switched to testing with Fiddler to illiminate client software and can consistently succeed or fail with the only change being the format of the boundary marker.
Because this is middleware intercepting the request I don't think model binding is an issue as no controller is being invoked to manage the request (so the latest core 2 file upload changes shouldn't be an issue?).
Test app to hopefully illustrate the problem.
Run the app and then use Fiddler or Postman to create raw posts containing the data found in the ReadMe.txt. A small 10x10 gif should appear in the uploads directory upon success.
Note that the ONLY change betwen successful and failed posts is the inclusion of a capital letter somewhere in the boundary marker (capital A at the end of the marker in this example).
Thank you for your time.
@JunTaoLuo Could you take a look at the test app?
@inex0rable This is because you are passing in the lower case version of the boundary to the MultipartReader in your middleware.
in UploadMiddleware.cs L49:
var requestContentType = httpContext.Request.ContentType.ToLower();
this converts Content-Type: multipart/form-data; boundary=--1234A in the request to content-type: multipart/form-data; boundary=--1234a which then parses the boundary as --1234a. This does not match the actual boundary --1234A in the body. Your repro works if you remove the call to .ToLower().
I can't tell you how many times I checked that code!
if (oops && muppet == true) {
_apologiseForWastedTime();
_sayThanks();
_hide();
}