multipart-parser v0.10.0
This release represents a major refactoring and simplification of this library from a async/promise-based architecture to a generator that suspends the parser as parts are found.
This is a reversion to the generator-based interface used before v0.8 when I switched to a promise interface to get around deadlock issues with consuming part streams inside a yield suspension point. The deadlock occurred when trying to read part.body inside a yield, because the parser was suspended and wouldn't emit any more bytes to the stream while the consumer was waiting for the stream to complete.
With this release, I realized that instead of getting rid of the generator, which is actually a fantastic interface for a streaming parser, I should've gotten rid of the part.body stream instead and replaced it with a part.content property that contains all the content for that part. This gives us a better parser interface and also makes error handling simpler when e.g. the parser's maxFileSize is exceeded. This also makes the parser easier to use because you don't have to e.g. await part.text() anymore, and you have access to part.size up front.
- BREAKING CHANGE:
parseMultipartandparseMultipartRequestare now generators thatyieldMultipartPartobjects as they are parsed - BREAKING CHANGE:
parseMultipartno longer parses streams, useparseMultipartStreaminstead - BREAKING CHANGE:
parser.parse()is removed - BREAKING CHANGE:
part.body,part.bodyUsedare removed - BREAKING CHANGE:
part.arrayBuffer,part.bytes,part.textare now sync getters instead ofasyncmethods - BREAKING CHANGE: Default
maxFileSizeis now 2MiB, same as PHP's defaultupload_max_filesize
New APIs:
parseMultipartStream(stream, options)is a generator that parses a stream of dataparser.write(chunk)andparser.finish()are low-level APIs for running the parser directlypart.contentis aUint8Array[]of all content in that partpart.isTextistrueif the part originates from a text fieldpart.sizeis the total size of the content in bytes
If you're upgrading, check the README for current usage recommendations. Here's a high-level taste of the before/after of this release.
import { parseMultipartRequest } from '@mjackson/multipart-parser';
// before
await parseMultipartRequest(request, async (part) => {
let buffer = await part.arrayBuffer();
// ...
});
// after
for await (let part of parseMultipartRequest(request)) {
let buffer = part.arrayBuffer;
// ...
}