I want to migrate my express endpoint to vercel serverless function. My endpoint in express is something like that:
router.route('/lead').post(uploadMultiImages, sendData);
uploadMultiImages is multer middleware:
import path from 'path';
import multerS3 from 'multer-s3';
import multer from 'multer';
import S3 from 'aws-sdk/clients/s3';
const config = {
accessKeyId: process.env.AWS_S3_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_S3_SECRET_ACCESS_KEY,
region: 'eu-west-1',
};
const multerFilter = (req: any, file: any, cb: any) => {
if (
file.mimetype === 'image/jpeg' ||
file.mimetype === 'application/msword' ||
file.mimetype ===
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ||
file.mimetype === 'application/pdf' ||
file.mimetype === 'image/png'
) {
cb(null, true);
} else {
cb(new Error('Not an image! Please upload images only.'), false);
}
};
const s3 = new S3({});
s3.config.update(config);
export const uploadMultiImages = multer({
storage: multerS3({
s3,
bucket: 'bucket-name',
acl: 'public-read',
key: function (
_req: any,
file: { originalname: string },
// eslint-disable-next-line no-unused-vars
cb: (arg0: null, arg1: string) => void
) {
cb(
null,
path.basename(file.originalname, path.extname(file.originalname)) +
'-' +
Date.now() +
path.extname(file.originalname)
);
},
}),
fileFilter: multerFilter,
}).array('file_upload', 12);
The sendData is a function in my controller that receives the request, check if the req.files exists and if it does, I extract the Amazon's URL provided by multer:
import { Request, Response } from 'express';
import { postFormData } from '@services/api/crm';
export async function sendData(req: Request, res: Response) {
try {
const formData = req.body;
if (!req?.files || req?.files?.length === 0) {
res.json({ data: formData, message: 'No file selected' });
} else {
const fileArray = req?.files as any[];
const galleryImageLocationArray = fileArray?.map((el) => el.location);
formData.attachment = galleryImageLocationArray.join(';');
res.status(200).json({
filesArray: fileArray,
locationArray: galleryImageLocationArray,
});
}
await postFormData(formData); // it does the post request to the CRM passing data
} catch (err: any) {
console.log('something wrong', err);
throw err.response?.data;
}
}
And it works fine. But now, I'm not able to replicate this logic with Nextjs _middleware.
Problem:
Middleware code runs in a special runtime environment known as the Edge Runtime, which is heavily based on Web APIs. You might notice that native node modules (e.g. fs) will not be available/usable in these files.
Well, multer has a dependency called "busboy" that use 'fs'. And I get an error.
So I tried to do something like that > https://github.com/leerob/nextjs-aws-s3/blob/main/pages/api/upload-url.js
But I can't understand how it works and if it could actually help me.
My folder structure for this endpoint in Next is:
-pages
-api
-lead
index.ts
_middleware.ts
I also asked myself, how can I get req.files in the _middleware function??
Am I missing something? Is it possible to replicate the behaviour I did in Express with this _middleware function in Nextjs?
Thanks