1.0.0 • Published 5 years ago

nicer v1.0.0

Weekly downloads
3
License
MIT
Repository
github
Last release
5 years ago

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
Library123
dicer137.21mb/s100.65mb/s165.95mb/s
multiparty25.78mb/s29.48mb/s29.60mb/s
nicer106.55mb/s112.46mb/s134.24mb/s
nicerc114.42mb/s115.04mb/s116.57mb/s
LibraryMax Speed
(1) dicer92.93mb/s
(2) nicerc79.95mb/s
nicer72.23mb/s
(3) multiparty28.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.

NameTypeDescription
boundary*stringThe 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.

NameTypeDescription
stream*!stream.PassThroughThe mandatory field separator.
header*!BufferThe 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