Skip to content
26 changes: 26 additions & 0 deletions src/plugins/octetstream.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable no-underscore-dangle */

import OctetStreamParser from "../parsers/OctetStream.js";
import FormidableError, * as errors from "../FormidableError.js";

export const octetStreamType = "octet-stream";
// the `options` is also available through the `options` / `formidable.options`
Expand Down Expand Up @@ -47,8 +48,33 @@ async function init(_self, _opts) {

// Keep track of writes that haven't finished so we don't emit the file before it's done being written
let outstandingWrites = 0;
let fileSize = 0;

this._parser.on("data", (buffer) => {
fileSize += buffer.length;
this._totalFileSize += buffer.length;

if (fileSize > this.options.maxFileSize) {
this._error(
new FormidableError(
`options.maxFileSize (${this.options.maxFileSize} bytes), received ${fileSize} bytes of file data`,
errors.biggerThanMaxFileSize,
413
)
);
return;
}
if (this._totalFileSize > this.options.maxTotalFileSize) {
this._error(
new FormidableError(
`options.maxTotalFileSize (${this.options.maxTotalFileSize} bytes) exceeded, received ${this._totalFileSize} bytes of file data`,
errors.biggerThanTotalMaxFileSize,
413
)
);
return;
}

this.pause();
outstandingWrites += 1;

Expand Down
87 changes: 87 additions & 0 deletions test/integration/octet-stream.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import url from "node:url";
import assert, { strictEqual, deepStrictEqual } from "node:assert";

import formidable from "../../src/index.js";
import {
biggerThanMaxFileSize,
biggerThanTotalMaxFileSize,
} from "../../src/FormidableError.js";

const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
Expand Down Expand Up @@ -52,3 +56,86 @@ test("octet stream", (done) => {
createReadStream(testFilePath).pipe(request);
});
});

test("octet stream enforces maxFileSize", (done) => {
const PORT2 = 13550;
let request;
let parsed = false;
const server = createServer((req, res) => {
const form = formidable({ maxFileSize: 1024, maxTotalFileSize: 2048 });

form.parse(req, (err, fields, files) => {
assert(err, "expected an error for over-sized octet-stream upload");
strictEqual(err.code, biggerThanMaxFileSize);
strictEqual(Object.keys(files).length, 0);

res.end();
parsed = true;
request.destroy();
server.close();
done();
});
});

server.listen(PORT2, (err) => {
assert(!err, "should not have error, but be falsey");

request = _request({
port: PORT2,
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
},
});

request.on("error", (error) => {
if (parsed) return;
server.close();
done(error);
});
request.end(Buffer.alloc(256 * 1024, 0x42));
});
});
Comment thread
GrosSacASac marked this conversation as resolved.
Resolved

test("octet stream enforces maxTotalFileSize", (done) => {
const PORT3 = 13551;
let request;
let parsed = false;
const server = createServer((req, res) => {
const form = formidable({ maxFileSize: 4096, maxTotalFileSize: 2048 });

form.parse(req, (err, fields, files) => {
assert(
err,
"expected an error for an octet-stream upload over the total limit"
);
strictEqual(err.code, biggerThanTotalMaxFileSize);
strictEqual(Object.keys(files).length, 0);

res.end();
parsed = true;
request.destroy();
server.close();
done();
});
});

server.listen(PORT3, (err) => {
assert(!err, "should not have error, but be falsey");

request = _request({
port: PORT3,
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
},
});

request.on("error", (error) => {
if (parsed) return;
server.close();
done(error);
});
request.end(Buffer.alloc(3000, 0x42));
});
});