-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0a9616c
Showing
4 changed files
with
170 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules/ | ||
examples/ | ||
yarn.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import parter from "./lib/parter.js"; | ||
|
||
export default parter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
}); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |