expressjs / multer

Node.js middleware for handling `multipart/form-data`.
MIT License
11.52k stars 1.05k forks source link

File upload middleware does not work when I chain it with other middlewares. I get req.file = undefined #1248

Open imhazard17 opened 5 months ago

imhazard17 commented 5 months ago

When I try to upload file without chaining the middlewares, the file upload works but when I chain it with other middlewares like input validation and authentication the file does not upload and I get req.file/req.files object as undefined.

Kindly help me to find what the issue is as I have been not able to find one yet.

I use postman to test the api and have set the correct body, authorization token and form data but still the error persists.

Github link of the project: https://github.com/imhazard17/user_mvp

Endpoint

// PUT /upl/upload
router.put('/upload', [userInputValidation, authentication, upload.single('file')], errForward(async (req, res) => {
    if (!req.file) {
        return res.status(404).json({ err: 'File not uploaded' })
    }

    return res.status(200).json({ file: req.file })
}))

Authentication middleware

function authentication(req, res, next) {
    if(!req.headers.authorization) {
        return res.status(411).json({
            err: 'Could not find auth token'
        })
    }

    const authToken = req.headers.authorization.split(' ')[1]

    let jwtVerifyRes

    try {
        jwtVerifyRes = jwt.verify(authToken, process.env.JWT_SECRET)
    } catch(e) {
        return res.status(403).json({
            err: 'Could not authenticate user'
        })
    } finally {
        req.locals = {}
        req.locals.userId = parseInt(jwtVerifyRes)
        next()
    }
}

Input validation middleware

function userInputValidation(req, res, next) {
    const schema = z.object({
        username: z.string().min(5).max(30)
        password: z.string().min(8).max(40),
        firstName: z.string().max(30).optional(),
        lastName: z.string().max(30).optional(),
    })

    try {
        schema.parse(req.body)
    } catch(e) {
        return res.status(411).json({
            err: 'Wrong inputs recieved'
        })
    } finally {
        next()
    }
}
joeyguerra commented 4 months ago

Weird. Do you see that error when you're authorized and the input is valid? Meaning it's gotten successfully through the previous middleware?

I had another observation, I see the code is responding with a 411, which is Length Required. I presume it should be 401.

Doc999tor commented 4 months ago

I'd try to remove errForward middleware since the last middleware is synchronous - for ensuring the req context is not lost / overridden

mattyod commented 3 months ago

In case it helps, I encountered similar after adding express-openapi-validator to an endpoint expecting a single file. req.file was undefined but the uploaded file was still referenced in req.files[] as a single entry.