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

crypto-busboy

v2.0.2

Published

busboy upload with encryption option and type file detector

Downloads

11

Readme

Build Status node version npm version

crypto-busboy

Upload and download files from nodejs using streams.

Optional you can cipher all incoming files, and decipher for download, without storing any clear version of the files.

All data manipulation is done using streams.

This module can limit upload on:

  • file size (busBoy)
  • files count (busBoy)
  • file extension (sniffing file header not assuming mime headers that can be faked)

File extension detection only works with this extensions file-type module extensions support

This module is based on busboy upload module

Install

> npm i crypto-busboy

Features

  • upload files with busboy size limits and file count limit, (basic BusBoy usage)
  • upload only files with allowed extension file-type module extensions support.
  • option to cipher incoming files before storing to disk.
  • download ciphered files without storing any clear version of the file.

Prerequisites

  • NodeJs >=v10.16.3 (npm v6.9.0)

Use

CryptoBusBoy Options

const options = {
    dest: 'folder where to put uploads',
    key: 'super-password', // optional, if you don't want to cipher files delete this
    alg: 'aes256', // optional default to aes-256-cbc
    timeOut: 2000, // optional request timeout, default option 15sg, to disable data timeout detection pass 0    
    limits: { //optional limits
        fileSize: 2000 * 1024 * 1024,
        files: 3,
        allowed: ['jpg', 'png']
    }
}

options.dest

  • dest: can be a local path /foo/bar
  • dest: can be an object with createWriteStream method exposing your custom writeable stream
 const dest =  {
    createWriteStream: (filename) => {
        const dir = '/tmp/uptest';
        return fs.createWriteStream(dir + '/' + filename)
    }
};

File destination is a writeStream to a remote http server

const http = require('http');

const dest = {
    protocol: 'http',
    path: `http://server1/upload_pipe/`, 
    createWriteStream: (filename) => {
        return http
                  .request({
                       port: 4000, 
                       path: `/upload_pipe/${filename}`,
                       method:'post'
                  });
    }
};

options.key

Optional param, if you want to cipher uploads you must provide a password.

options.alg

Optional param, default alg aes-256-cbc.

options.timeOut

By default if a client start to upload a file and there is no incoming data in 15 seconds, cryptoBusBoy will assume the upload is broken and will tag the upload session as failed releasing all resources.

If you are dealing with very unstable clients You can increase timeOut value as you wish.

Can be disabled with options.timeOut: 0

options.limits

Optional param.

Limits

  • fileSize limit in bytes.
  • files limit, number of files allowed to Upload
  • file-type limit will limit files by mime type.

express example

const cryptoBusBoy = new CryptoBusBoy(options);
 
function uploadFiles(req, res, next){
        cryptoBusBoy.upload(req)
            .then(r => {
                if(r.warnings.length > 0)
                    res.statusCode = 429;
                else if (r.files.length > 0 && r.errors.length > 0)
                    res.statusCode = 429;
                else if (r.errors.length > 0)
                    res.statusCode = 400;
                
                if(r.files.length > 0)
                    saveto_db(r.files)
                        .then(() => res.json(r.files.map(f => f.filename)))
                        .catch(e => next(e));
                else
                    res.json(r);
            })
            .catch(e => next(e))
}

function downloadFile(req, res, next){
        const file = req.params.file;
        cryptoBusBoy
                    .download(req, res, next, file) //will validate file param name
                    .catch(e => next(e))
        // or if you are using req.params.file you can directly use
        // cryptoBusBoy.download(req, res, next);
}

function uploadFilesCustomOpt(req, res, next){
        const force_path = busOpt.dest + '/foo/';
        const dest_opt = {dest: force_path};

        cryptoBusBoy.upload(req, dest_opt)
            .then(r => {
                if(r.warnings.length > 0)
                    res.statusCode = 429;
                else if (r.files.length > 0 && r.errors.length > 0)
                    res.statusCode = 429;
                else if (r.errors.length > 0)
                    res.statusCode = 400;

                if(r.files.length > 0)
                    saveto_db(r.files)
                        .then(() => res.json(r.files.map(f => f.filename)))
                        .catch(e => next(e));
                else
                    res.json(r)
            })
            .catch(e => {
                next(e)
            })
    }

Upload outputs

Upload f4.jpeg with form field avatar = true

{
    "warnings":[],
    "errors":[],
    "files":[
        {
            "filename":"f4.jpeg",
            "fullname":"4541a890-f451-11e9-afca-ef6fa948a376-ciphered.jpeg",
            "newname":"4541a890-f451-11e9-afca-ef6fa948a376-ciphered",
            "fieldname":"my photo 4",
            "ext":"jpeg",
            "folder":"/crypto-upload/tests/files",
            "fullPath":"/crypto-upload/tests/files/4541a890-f451-11e9-afca-ef6fa948a376-ciphered.jpeg",
            "error":null,
            "finished": true,
            "failed": false,
            "size": 32606
        }
    ],
   "fields":[{"avatar":"true"}]}

Upload not allowed extension file xsl

{
  "warnings":[],
  "errors":
    [{
        "filename":"f1.xlsx",
        "fullname":"45463c70-f451-11e9-afca-ef6fa948a376-ciphered.xlsx",
        "newname":"45463c70-f451-11e9-afca-ef6fa948a376-ciphered",
        "fieldname":"my excel",
        "ext":"xlsx",
        "folder":"/crypto-upload/tests/files",
        "fullPath":"/crypto-upload/tests/files/45463c70-f451-11e9-afca-ef6fa948a376-ciphered.xlsx",
        "error":"EXTENSION NOT ALLOWED xlsx"
    }],
  "files":[],
  "fields":[]
}

Upload 5 files limit is 2, Ok two files and get warning = MAX FILES REACHED

{
"warnings": [ "MAX FILES REACHED, LIMIT IS 2 FILES" ],
"files": [
    {
      "filename": "f2.jpeg",
      "fullname": "bd87cd00-04ca-11ea-a94b-e3abd7553c43-ciphered.jpeg",
      "newname": "bd87cd00-04ca-11ea-a94b-e3abd7553c43-ciphered",
      "fieldname": "my photo 2",
      "encoding": "7bit",
      "mimetype": "image/jpeg",
      "crypto_mode": true,
      "detector_mode": true,
      "ext": "jpeg",
      "folder": "/crypto-busboy/tests/files",
      "fullPath": "/crypto-busboy/tests/files/bd87cd00-04ca-11ea-a94b-e3abd7553c43-ciphered.jpeg",
      "error": null,
      "finished": true,
      "failed": false,
      "size": 32606
    },
    {
      "filename": "f3.jpeg",
      "fullname": "bd89efe0-04ca-11ea-a94b-e3abd7553c43-ciphered.jpeg",
      "newname": "bd89efe0-04ca-11ea-a94b-e3abd7553c43-ciphered",
      "fieldname": "my photo 3",
      "encoding": "7bit",
      "mimetype": "image/jpeg",
      "crypto_mode": true,
      "detector_mode": true,
      "ext": "jpeg",
      "folder": "/crypto-busboy/tests/files",
      "fullPath": "/crypto-busboy/tests/files/bd89efe0-04ca-11ea-a94b-e3abd7553c43-ciphered.jpeg",
      "error": null,
      "finished": true,
      "failed": false,
      "size": 66860
    }
  ],
  "fields": [],
  "errors": []
}

Upload cipher file to remote http server

{
  "warnings":[],
  "errors":[],
  "files":
     [{
        "filename":"f2.jpeg",
        "fullname":"1b457120-0b26-11ea-b51f-8937c8745f61-ciphered.jpeg",
        "newname":"1b457120-0b26-11ea-b51f-8937c8745f61-ciphered",
        "fieldname":"my photo 2",
        "encoding":"7bit",
        "mimetype":"image/jpeg",
        "crypto_mode":true,
        "detector_mode":true,
        "ext":"jpeg",
        "folder":"http://localhost:46063/file/",
        "fullPath":"http://localhost:46063/file/1b457120-0b26-11ea-b51f-8937c8745f61-ciphered.jpeg",
        "error":null,
        "finished":true,
        "failed":false,
        "size":32606
      }],
  "fields":[]}

Debug=cryptoBus:*

> DEBUG=cryptoBus:* npm run test

Tests

Test will download some files from a repo and generate a ~~2GB~~ 50mb file that will be removed after tests finish

--big_file_size [mb|gb]

> npm run test
> NODE_ENV=test mocha --exit --big_file_size '50mb' tests/

AB Stress Upload Tests

You need to have installed AB - Apache HTTP server benchmarking tool

For test uploads with AB we need to base64 encode the file we are uploading, so instead of a binary stream we have a base64 data stream at the server.

Tests results will be increased against a typical browser upload because at the server we need to base64Decode the incoming stream before doing anything else with the file.

Run AB tests

  • -ft file to transform to ab format and test
  • -n number of requests
  • -c concurrent requests
  • -conf tests/server/conf/cipher_allowed.json|default.json|allowed.json|cipher.json

You can pass any json representing crypto-busboy options.

➜ node tests/ab -ft file.zip -c 10 -n 100 -conf tests/server/conf/cipher_allowed.json

The above command will:

  • start express server with crypto-busboy options cipher_allowed.json
  • Upload file.zip 100 times in bunches of 10 using AB tool.
  • Present AB results.
  • Download all 100 files to a temp location.
  • md5-check to verify that the file we uploaded is the same we downloaded.
  • Clean up everything.

if you keep a file to test upload that do not pass limits detector you will be notified.

Dependencies

Contributing

Pull requests are welcome.

License

MIT