Open nbevans opened 5 years ago
https://github.com/Vodurden/Http-Multipart-Data-Parser/issues/29
It seems this fix hasn’t been merged into WebSharper.
It seems that HttpMultipartParser lib may be ripe for replacement with say MimeKitLite. This is a far better tested and production grade lib that can easily handle multipart parsing.
Thanks for digging into this. I agree, HMP looks a bit outdated - replacing would come with no extra dependencies and would remove the need for custom code in this repo. Would you like to give it a go and submit a PR?
Hi @granicz
I needed to fix it on our production app super urgently so I imported the WebSharper.Owin (really it is just one .fs file) code to our repo, and tweaked it to use the latest NuGet of HttpMultipartParser. This seemed to all go very well and we've deployed this now so will see if it fixes the immediate problem we were having.
It seems the original reason HMP was imported into the WebSharper.Owin repo was because it needed to add the "leaveOpen" support to the Stream. I worked around this by using my NonClosingStream (see below) wrapper/decorator - which means I didn't need to make any tweaks to HMP's source code. I'm not sure why WebSharper.Owin didn't just do this originally? Bleh...
I still think HMP needs replacing though. With no offence intended to the original author of it, it hasn't had a commit/release for a couple years now, and there are alternative libraries nowadays like MimeKitLite which are better maintained and more suitable for use on production grade systems - particularly because of better edge case handling thus reducing possible attack vectors.
I am investigating what needs doing to rip out HMP and replace with MimeKitLite.
/// Stream decorator that swallows Dispose() calls.
/// Optionally, can reset the position of a seekable stream to the start when disposed.
type NonClosingStream(stream:Stream, ?resetPositionOnDispose) =
inherit Stream()
override __.CanRead = stream.CanRead
override __.CanSeek = stream.CanSeek
override __.CanWrite = stream.CanWrite
override __.Length = stream.Length
override __.Position with get() = stream.Position and set(v) = stream.Position <- v
override __.Flush() = stream.Flush()
override __.Seek(offset, origin) = stream.Seek(offset, origin)
override __.SetLength(v) = stream.SetLength(v)
override __.Read(buffer, offset, count) = stream.Read(buffer, offset, count)
override __.Write(buffer, offset, count) = stream.Write(buffer, offset, count)
override __.Dispose _ = if defaultArg resetPositionOnDispose false && stream.CanSeek then stream.Position <- 0L
Sounds good, thanks!
https://gist.github.com/nbevans/219a65ed04cc8c401a390e4acef70bdd
I forgot to come back and post this. My fixes went a bit above & beyond just the MIME parsing.
Anyone ever seen this before? The HttpMultipartParser is hanging on multiple threads (presumably requests that came in) and is spinning the CPU. I managed to pull the following stack trace from our prod server process using Sysinternals Process Explorer.