Skip to content

Commit

Permalink
feat: adding expressjs route for testing multipart content types (use…
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicolas PUZIN committed Apr 17, 2024
1 parent 95ad1db commit 7eab1b6
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 6 deletions.
17 changes: 17 additions & 0 deletions packages/bruno-tests/collection/multipart/mixed-content-types.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
meta {
name: mixed-content-types
type: http
seq: 1
}

post {
url: {{host}}/api/multipart/mixed-content-types
body: multipartForm
auth: none
}

body:multipart-form {
param1: test
param2: @file(multipart/small.png)
param3: {"test":"i am json"}
}
Binary file added packages/bruno-tests/collection/multipart/small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 4 additions & 6 deletions packages/bruno-tests/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,25 @@ const express = require('express');
const bodyParser = require('body-parser');
const xmlparser = require('express-xml-bodyparser');
const cors = require('cors');
const multer = require('multer');
const formDataParser = require('./multipart/form-data-parser');

const app = new express();
const port = process.env.PORT || 8080;
const upload = multer();

app.use(cors());
app.use(xmlparser());
app.use(bodyParser.text());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
formDataParser.init(app, express);

const authRouter = require('./auth');
const echoRouter = require('./echo');
const multipartRouter = require('./multipart');

app.use('/api/auth', authRouter);
app.use('/api/echo', echoRouter);
app.use('/api/multipart', multipartRouter);

app.get('/ping', function (req, res) {
return res.send('pong');
Expand All @@ -32,10 +34,6 @@ app.get('/query', function (req, res) {
return res.json(req.query);
});

app.post('/echo/multipartForm', upload.none(), function (req, res) {
return res.json(req.body);
});

app.get('/redirect-to-ping', function (req, res) {
return res.redirect('/ping');
});
Expand Down
56 changes: 56 additions & 0 deletions packages/bruno-tests/src/multipart/form-data-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Instead of using multer for example to parse the multipart form data, we build our own parser
* so that we can verify the content type are set correctly by bruno (for example application/json for json content)
*/

const extractParam = function (param, str, delimiter, quote, endDelimiter) {
let regex = new RegExp(`${param}${delimiter}\\s*${quote}(.*?)${quote}${endDelimiter}`);
const found = str.match(regex);
if (found != null && found.length > 1) {
return found[1];
} else {
return null;
}
};

const init = function (app, express) {
app.use(express.raw({ type: 'multipart/form-data' }));
};

const parse = function (req) {
const BOUNDARY = 'boundary=';
const contentType = req.headers['content-type'];
const boundary = '--' + contentType.substring(contentType.indexOf(BOUNDARY) + BOUNDARY.length);
const rawBody = req.body.toString();
let parts = rawBody.split(boundary).filter((part) => part.length > 0);
parts = parts.map((part) => part.trim('\r\n'));
parts = parts.filter((part) => part != '--');
parts = parts.map((part) => part.replace('\r\n\r\n', ';value='));
parts = parts.map((part) => part.replace('\r\n', ';'));
parts = parts.map((part) => {
let result = {};
const name = extractParam('name', part, '=', '"', '');
if (name) {
result.name = name;
}
const filename = extractParam('filename', part, '=', '"', '');
if (filename) {
result.filename = filename;
}
const contentType = extractParam('Content-Type', part, ':', '', ';');
if (contentType) {
result.contentType = contentType;
}
if (!filename) {
result.value = part.substring(part.indexOf('value=') + 'value='.length);
}
if (contentType === 'application/json') {
result.value = JSON.parse(result.value);
}
return result;
});
return parts;
};

module.exports.parse = parse;
module.exports.init = init;
10 changes: 10 additions & 0 deletions packages/bruno-tests/src/multipart/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const express = require('express');
const router = express.Router();
const formDataParser = require('./form-data-parser');

router.post('/mixed-content-types', (req, res) => {
const parts = formDataParser.parse(req);
return res.json(parts);
});

module.exports = router;

0 comments on commit 7eab1b6

Please sign in to comment.