Typective
A lightweight NodeJS library for strict mime-type validation on streams. It gets a ReadableStream and decets the mime-type using its Magic number and validates it using the provided allowed and forbidden lists; If it's allowed it will pass it to the created WritableStreams and if it's not it will throw an error.
Table of contents
Installation
npm i typective
Quick start
const typective = require("typective");
try{
const { type } = await typective(
fs.createReadStream("image-1.jpeg"),
{ allowed: ["image/*"] },
payload => [fs.createWriteStream(`image-2.${payload.extensions[0]}`)]
);
} catch(error){ console.error(error); }
Examples
Upload example
Save the file if it is an image
Note: We are using Busboy in this example for handling file uploads.
const http = require("http"),
busboy = require("busboy"),
fs = require("fs"),
typective = require("typective");
http.createServer((request, response) => {
if (request.method === "POST") {
const uploader = busboy({ headers: request.headers });
uploader.on("file", async (name, file, info) => {
/**
* Note: info.mimeType is just based on the file extension
* and not the actual mime-type of the file.
* For example if we have a video file named "video.mp4"
* And rename it to "video.jpeg" then upload it to the server;
* The file.mimeType would be "image/jpeg" which it is clearly
* Not the mime-type of our file!
*/
try {
const { type } = await typective(
file,
{
allowed: ["image/*"]
},
payload => [
fs.createWriteStream(
`./upload.${payload.extensions[0]}`
)
]
);
response.writeHead(200, {
"Content-Type": "application/json",
Connection: "close"
});
response.end(JSON.stringify({ type }));
} catch (error) {
response.writeHead(400, {
"Content-Type": "application/json",
Connection: "close"
});
response.end(JSON.stringify({ error: error.message }));
}
});
request.pipe(uploader);
}
}).listen(3000, () => {
console.log("Server running on port 3000");
});
Download example
Save the file if it is an image and not a PNG
const https = require("https"),
fs = require("fs"),
typective = require("typective");
const URL =
"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1200px-Image_created_with_a_mobile_phone.png";
https.get(URL, async response => {
try {
await typective(
response,
{
allowed: ["image/*"],
forbidden: ["image/png"]
},
payload => [
fs.createWriteStream(`./download.${payload.extensions[0]}`)
]
);
} catch (error) {
console.error(error);
}
});
API
Exports
typective
exports a single function.
( function )(< ReadableStream >sourceStream, < object >config, < function >contextCreator) - Detects mime-type of a given readable stream and passes it to given streams if the detected mime-type is allowed
-
Valid
options
properties:-
allowed - Array of allowed mime-types
-
forbidden - Array of forbidden mime-types
-
bufferSize - Buffer size of each chunk in the pipeline
-
-
contextCreator(< Object >payload) - A function that will be called with an payload object when the mime-type has been detected. You can use it to create and pass your WritableStreams to the
typective
. (It should always return an array of WritableStreams otherwisethe process would stuck)-
payload
properties:-
extensions - Array of detected extensions
-
category - Detected file category
-
-
This function will throw exceptions if given stream is not a readable stream or if the detected mime-type is not allowed.