npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

nicer

v1.0.0

Published

An Http Multipart/Form-Data Request Body Parser.

Downloads

2

Readme

nicer

npm version

nicer is An Http Multipart/Form-Data Request Body Parser. It can receive form data fields and files headers and stream their data.

yarn add nicer

| Library | 1 | 2 | 3 | | ---------- | ---------- | ---------- | ---------- | | dicer | 137.21mb/s | 100.65mb/s | 165.95mb/s | | multiparty | 25.78mb/s | 29.48mb/s | 29.60mb/s | | nicer | 106.55mb/s | 112.46mb/s | 134.24mb/s | | nicerc | 114.42mb/s | 115.04mb/s | 116.57mb/s |

| Library | Max Speed | | ---------- | --------- | | (1) dicer | 92.93mb/s | | (2) nicerc | 79.95mb/s | | nicer | 72.23mb/s | | (3) multiparty | 28.79mb/s |

Table Of Contents

API

The package is available by importing its default constructor function:

import Nicer from 'nicer'

constructor(  boundary: string,): Nicer

Creates a transform that emits objects with a header buffer and the body stream. The body stream is a pass-through so all data must be written as it comes, the request doesn't pause for data to be consumed. The header is a buffer which can be parsed more and/or decrypted, but it does not stream. The assumption is the headers are short therefore a header buffer is accumulated until \r\n is found. Just make sure to run behind NginX then it should be alright.

Nicer: A stream that emits objects with a header buffer and the body PassThrough stream.

| Name | Type | Description | | ------------- | --------------- | ------------------------------ | | boundary* | string | The mandatory field separator. |

import { Transform } from 'stream'
import Nicer from 'nicer'

const detected = []

await http.startPlain((req, res) => {
  const boundary = getBoundary(req, res)
  console.log('Boundary detected: %s', boundary)
  req.pipe(new Nicer({ boundary })).pipe(new Transform({
    objectMode: true,
    transform(obj, enc, next) {
      const { header: HEADER, stream: STREAM } = obj

      // to print in sync have to wait for all data
      // since STREAM is a pass-through
      let d = []
      detected.push(['%s\n====\n', HEADER, d])

      STREAM.on('data', (data) => {
        d.push(data)
      })
      next()
    },
    final() {
      res.statusCode = 200
      res.end(JSON.stringify(detected))
    },
  }))
})

Part: A part that gets emitted by Nicer.

| Name | Type | Description | | ----------- | ---------------------------- | ------------------------------ | | stream* | !stream.PassThrough | The mandatory field separator. | | header* | !Buffer | The header found before data. |

Boundary detected: u2KxIV5yF1y+xUspOQCCZopaVgeV6Jxihv35XQJmuTx8X3sh

Content-Disposition: form-data; name="key"
====
 [ 'value' ] 


Content-Disposition: form-data; name="alan"
====
 [ 'watts' ] 


Content-Disposition: form-data; name="file"; filename="test/fixture/test.txt"
Content-Type: application/octet-stream
====
 [ 'a test file\n' ]

Errors

The errors are spawned when the buffer remaining the stream after the final event, and processed to extract the rest of the fields, still contains symbols different from -- ([45,45]).

-------example
Content-Disposition: form-data; name="key"

data
-------exampleWAT
Boundary detected: -----example
[!] Error Unexpected end of request body, wanted to see "--" but saw WA.
    Detected Data:

Content-Disposition: form-data; name="key"
====
 [ 'data' ]

Debug

The software can write debug information, when the DEBUG=nicer env variable is set.

import { Writable } from 'stream'
import Nicer from '../src'

const detected = []

await http.startPlain((req, res) => {
  const boundary = getBoundary(req, res)
  console.log('Boundary detected: %s', boundary)
  const nicer = new Nicer({ boundary })
  const bt = new BufferTransform(50)

  req.pipe(bt).pipe(nicer).pipe(new Writable({
    objectMode: true,
    write(obj, enc, next) {
      const { header: HEADER, stream: STREAM } = obj
      next()
    },
    final() {
      res.statusCode = 200
      res.end(JSON.stringify(detected))
    },
  }))
})
nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +0ms
  nicer 🔎  Finished boundary scan, buffer of length 50B left, separators found: 0 +2ms
  nicer one consume safe consumed 0B and left 50B +1ms
  nicer <concat-transform> +1ms
  nicer <concat-transform> 100B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +0ms
  nicer   ⭐  Found starting boundary at index 2 +0ms
  nicer 🔎  Finished boundary scan, buffer of length 48B left, separators found: 1 +0ms
  nicer one consume safe consumed 52B and left 48B +1ms
  nicer <concat-transform> +0ms
  nicer <concat-transform> 98B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +0ms
  nicer 🔎  Finished boundary scan, buffer of length 98B left, separators found: 0 +0ms
  nicer one consume safe consumed 46B and left 52B +0ms
  nicer <concat-transform> +0ms
  nicer <concat-transform> 102B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +0ms
  nicer   🔛  Found boundary, data size 7B +0ms
  nicer   🗒  Found header and data of size <53B> +1ms
  nicer      Content-Disposition: form-data; name="key" +0ms
  nicer      value +0ms
  nicer 🔎  Finished boundary scan, buffer of length 43B left, separators found: 1 +2ms
  nicer one consume safe consumed 59B and left 43B +0ms
  nicer <concat-transform> +0ms
  nicer <concat-transform> 93B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +0ms
  nicer 🔎  Finished boundary scan, buffer of length 93B left, separators found: 0 +0ms
  nicer one consume safe consumed 41B and left 52B +0ms
  nicer <concat-transform> +1ms
  nicer <concat-transform> 102B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +0ms
  nicer   🔛  Found boundary, data size 13B +0ms
  nicer   🗒  Found header and data of size <54B> +0ms
  nicer      Content-Disposition: form-data; name="alan" +0ms
  nicer      watts +0ms
  nicer 🔎  Finished boundary scan, buffer of length 37B left, separators found: 1 +0ms
  nicer one consume safe consumed 65B and left 37B +1ms
  nicer <concat-transform> +0ms
  nicer <concat-transform> 87B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +0ms
  nicer 🔎  Finished boundary scan, buffer of length 87B left, separators found: 0 +0ms
  nicer one consume safe consumed 35B and left 52B +0ms
  nicer <concat-transform> +0ms
  nicer <concat-transform> 102B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +11ms
  nicer 🔎  Finished boundary scan, buffer of length 102B left, separators found: 0 +0ms
  nicer       <concat-header> +0ms
  nicer       <concat-header> 85B +1ms
  nicer one consume safe consumed 50B and left 52B +0ms
  nicer <concat-transform> +0ms
  nicer <concat-transform> 102B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +1ms
  nicer   🔛  Found boundary, data size 50B +0ms
  nicer   🗒  Found header and data of size <135B> +0ms
  nicer      Content-Disposition: form-data; name="file"; filename="test/fixture/test.txt" +0ms
  nicer      Content-Type: ap... +0ms
  nicer 🔎  Finished boundary scan, buffer of length 0B left, separators found: 1 +1ms
  nicer one consume safe consumed 102B and left 0B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +0ms
  nicer 🔎  Finished boundary scan, buffer of length 4B left, separators found: 0 +0ms
  nicer one consume safe consumed 0B and left 4B +0ms
  nicer 🔍  Staring boundary --u2KxIV5yF1y+x... scan +2ms
  nicer 🔎  Finished boundary scan, buffer of length 4B left, separators found: 0 +1ms
  nicer one consume safe consumed 0B and left 4B +0ms

Copyright

(c) Idio 2019