Skip to content

Commit

Permalink
Added parser for file
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr-M1M3 committed Jul 5, 2022
0 parents commit 0a9616c
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
examples/
yarn.lock
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import parter from "./lib/parter.js";

export default parter;
144 changes: 144 additions & 0 deletions lib/parter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Author: Mr-M1M3
* Project: busboy-promise
* Description: Turning an event based multipart parser, busboy to promise based
* Started Written: 5th July, 2022.
*/
import {
IncomingMessage
} from "http";

import {Buffer} from "buffer";

import busboy from "busboy";

export default async function parter(req, options) {

if (options) { // if user passes options

if (typeof options != 'object') { // it must be an object

return Promise.reject(`Expected second parameter to be an object containing options for Busboy. Got ${typeof options}`);

}

} else { // if user doesn't passes any option

options = {}; // replace it with an empty object

}

if (!options.headers) { // if options object doesn't contain headers

options.headers = req.headers; // set option.headers to req.headers

}

const bb = busboy(options); // instantiate busboy

if (req instanceof Request) { // if req is an instance of Request

// pipe request body, a readable stream to busboy instance which is an writable stream.
//NOTE: body of Request instance is a readable stream and in nodejs readable stream `pipeTo` is not available.
//Rather, we use `pipe()`;
req.body.pipe(bb);


} else if (req instanceof IncomingMessage) { // if req is an instance of node IncomingMessage

// nodejs IncomingMessage is a stream.
// So, it is possible to pipe the whole request object to another stream
req.pipe(bb);

} else { // if req is invalid

return Promise.reject("Expected first argument to be an instance of Request or IncomingMessage");

}

function cleanUp() {

}

return new Promise((acc, rej) => {

const data = { // an empty object to hold parsed data
files: {},
fields: {}
}

bb.on("error", busboyError);
bb.on("file", appendFile); // when a file is received, calls appendFile
bb.on("finish", finishParse);

function appendFile(name, stream, info) {
// TODO: Process received file

const bufferArray = []; // empty array to receive buffers


stream.on("error", streamError); // if any error happens, calls streamError function
stream.on("data", appendBuffer); // calls appendBuffer when a new chunk is received
stream.on("end", done);

function appendBuffer(chunk){ // just pushes new chunk to `bufferArray`
bufferArray.push(chunk);
}

function done(){
let bufferLength = 0; // initially, total buffer length is assumed 0

for(let _buffer of bufferArray){ // determine the whole length of total buffers
bufferLength += _buffer.length;
}

// finally
data.files[name] = {};
data.files[name].content = Buffer.concat(bufferArray, bufferLength);
data.files[name].info = info;

}

function streamError(error) {

streamCleanUp(); // removes all the listeners of the stream

rej({

message: `an error happened while reading the stream of file named \`${name}\``,
error

});

};

function streamCleanUp() {
cleanUp();
stream.removeListener("data", appendBuffer);
stream.removeListener("end", done);
stream.removeListener("error", streamError);
}
}

function finishParse(){
acc(data);
}

function busboyError(error) { // if any error happens

cleanUp(); // 1. remove all listeners

rej({ // rejects promise
message: "an error happened in busboy",
error
})
}

function cleanUp(){
bb.removeListener("file", appendFile);
bb.removeListener("finish", finishParse);
bb.removeListener("error", busboyError);
}
});

}
20 changes: 20 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "partrer",
"version": "0.0.1",
"description": "Promise based multipart parser",
"main": "index.js",
"repository": "https://github.com/obboy/parter",
"author": "m1m3@obboy",
"license": "MIT",
"dependencies": {
"busboy": "^1.6.0"
},
"type": "module",
"devDependencies": {
"express": "^4.18.1",
"nodemon": "^2.0.18"
},
"scripts": {
"test:dev": "nodemon examples/server.js"
}
}

0 comments on commit 0a9616c

Please sign in to comment.