{"id":13067,"library":"dicer","title":"Dicer Streaming Multipart Parser","description":"Dicer is a high-performance streaming multipart parser specifically designed for Node.js environments. It excels at efficiently processing `multipart/form-data` streams, making it suitable for handling HTTP file uploads and other multipart-encoded data with a focus on speed and low memory usage. The current stable version, 0.3.1, indicates a mature but not aggressively changing codebase. While it doesn't adhere to a rapid release cadence, its stability and proven performance make it a reliable choice for its specialized task. A key differentiator is its low-level, event-driven streaming API, providing developers with fine-grained control over the parsing process and part handling, contrasting with higher-level form parsing libraries that might buffer entire data sets. This design choice contributes to its reported efficiency and minimal memory footprint, especially beneficial for high-throughput applications where large file uploads are common. Benchmarks highlight its speed against alternatives, positioning it as a performant solution in the Node.js ecosystem.","status":"active","version":"0.3.1","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/mscdex/dicer","tags":["javascript","parser","parse","parsing","multipart","form-data","streaming"],"install":[{"cmd":"npm install dicer","lang":"bash","label":"npm"},{"cmd":"yarn add dicer","lang":"bash","label":"yarn"},{"cmd":"pnpm add dicer","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The primary constructor for creating a Dicer instance, typically used in CommonJS environments within Node.js applications.","symbol":"Dicer (CommonJS constructor)","correct":"const Dicer = require('dicer');"},{"note":"While Dicer is primarily a CommonJS module, Node.js's interoperability allows it to be imported as a default in ESM contexts. However, direct `import Dicer from 'dicer'` might require specific `type: module` configurations or a transpiler to work reliably across all Node.js versions. For maximum compatibility in ESM, consider `import Dicer_module from 'dicer'; const Dicer = Dicer_module.default || Dicer_module;`.","wrong":"const Dicer = require('dicer'); // In an ESM file","symbol":"Dicer (ESM default import)","correct":"import Dicer from 'dicer';"},{"note":"Dicer is exported as a CommonJS module and does not provide named exports. Attempting to use a named import like `import { Dicer } from 'dicer';` will result in an error in ESM environments. Only default imports (with CJS interoperability) or `require()` are applicable.","wrong":"import { Dicer } from 'dicer';","symbol":"Dicer (ESM named import)"}],"quickstart":{"code":"const { inspect } = require('util');\nconst http = require('http');\n\nconst Dicer = require('dicer');\n\n// Quick and dirty way to parse multipart boundary\nconst RE_BOUNDARY =\n  /^multipart\\/.+?(?:; boundary=(?:(?:\"(.+)\")|(?:([^\\s]+))))$/i;\nconst HTML = Buffer.from(`\n  <html><head></head><body>\n    <form method=\"POST\" enctype=\"multipart/form-data\">\n      <input type=\"text\" name=\"textfield\"><br />\n      <input type=\"file\" name=\"filefield\"><br />\n      <input type=\"submit\">\n    </form>\n  </body></html>\n`);\nconst PORT = 8080;\n\nhttp.createServer((req, res) => {\n  let m;\n  if (req.method === 'POST'\n      && req.headers['content-type']\n      && (m = RE_BOUNDARY.exec(req.headers['content-type']))) {\n    const d = new Dicer({ boundary: m[1] || m[2] });\n\n    d.on('part', (p) => {\n      console.log('New part!');\n      p.on('header', (header) => {\n        for (const h in header) {\n          console.log(\n            `Part header: k: ${inspect(h)}, v: ${inspect(header[h])}`\n          );\n        }\n      });\n      p.on('data', (data) => {\n        console.log(`Part data: ${inspect(data.toString())}`);\n      });\n      p.on('end', () => {\n        console.log('End of part\\n');\n      });\n    });\n    d.on('finish', () => {\n      console.log('End of parts');\n      res.writeHead(200);\n      res.end('Form submission successful!');\n    });\n    req.pipe(d);\n  } else if (req.method === 'GET' && req.url === '/') {\n    res.writeHead(200);\n    res.end(HTML);\n  } else {\n    res.writeHead(404);\n    res.end();\n  }\n}).listen(PORT, () => {\n  console.log(`Listening for requests on port ${PORT}`);\n});","lang":"javascript","description":"Demonstrates how to set up an HTTP server to receive multipart/form-data POST requests, manually extract the boundary from the `Content-Type` header, and use Dicer to parse individual parts, logging their headers and data."},"warnings":[{"fix":"Implement robust `Content-Type` header parsing (e.g., using a regex) to extract the `boundary` parameter, and pass it to the `Dicer` constructor: `new Dicer({ boundary: extractedBoundary })`.","message":"Dicer requires the multipart boundary to be explicitly passed during instantiation. It does not automatically parse the `Content-Type` header. Incorrectly extracting or providing the boundary will lead to parsing errors or an inability to process the stream.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"If expecting many headers per part, explicitly set `maxHeaderPairs` to a higher value in the `Dicer` constructor: `new Dicer({ boundary: '...', maxHeaderPairs: 5000 })`.","message":"The `maxHeaderPairs` option defaults to 2000, limiting the maximum number of header key-value pairs parsed for each part. Forms with an unusually large number of fields (e.g., many checkboxes with unique names) could exceed this limit, leading to truncated header parsing.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Always attach a 'data' listener or pipe `PartStream` instances to another Writable stream. If you only need headers, ensure you call `p.resume()` on the `PartStream` to discard data and prevent backpressure buildup.","message":"Dicer is a low-level streaming parser. Neglecting to consume or properly handle backpressure on `PartStream` instances (emitted by the 'part' event) can lead to memory issues or stream blockage. Each `PartStream` is a Readable stream and must be drained.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `Dicer` is correctly imported as a CommonJS module: `const Dicer = require('dicer');` or handled with appropriate ESM interoperability for a CJS module.","cause":"Attempting to instantiate `Dicer` using an incorrect `require` or `import` syntax that doesn't correctly resolve the constructor, or trying to use `Dicer` before it's been properly assigned.","error":"TypeError: Dicer is not a constructor"},{"fix":"Double-check the regex or logic used to extract the `boundary` string from the `Content-Type` HTTP header and ensure it is passed correctly to `new Dicer({ boundary: '...' })`. The boundary must be an exact match.","cause":"The `boundary` string provided to the `Dicer` constructor does not accurately match the boundary specified in the `Content-Type` header of the incoming multipart stream.","error":"Dicer `part` or `finish` events are not firing, or parsing unexpectedly stops."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":""}