简体   繁体   中英

Express middleware for express.static() not routing correctly and throwing next() is not a function

Despite this running correctly on my local machine while I was writing and testing it, it seems to fail when deployed out to our UAT environment using Docker. I can't seem to track down why it's giving me the following:

next() is not a function

I also seem to be having a routing issue (again only when it's deployed) where even if it when the route is /media/public it seems to still hit the /media route.

dependencies

"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1"

server.js

require('dotenv').config();
const express = require('express');
const { join } = require('path');
const { fileExists, isAuthenticated } = require('./helpers/utils');
const { PORT, ROOT_SHARE } = process.env;
const app = express();

global.__basedir = __dirname

app.use('/robots.txt', function (_req, res) {
    res.type('text/plain');
    res.send('User-agent: *\nDisallow:/');
});

app.use('/media/public', [fileExists, express.static(join(__dirname, ROOT_SHARE, '/public'))]);
app.use('/media', [isAuthenticated, express.static(join(__dirname, ROOT_SHARE))]);

app.listen(PORT, () => console.info(`[File Server] : running on ${PORT}`));

utils.js

const { existsSync } = require('fs');
const { verify } = require('jsonwebtoken');
const { join } = require('path');
const { ACCESS_SECRET, NODE_ENV  } = process.env;

const fileExists = async (req, res, next) => {
    let mediaFile = (NODE_ENV === 'local') ? join(__basedir, req.baseUrl, req.path).replace('\\src','') : req.originalUrl;
    console.log(mediaFile);
    if (!existsSync(mediaFile)) {
        console.log('NOT FOUND')
        return res.status(404).send('NOT FOUND');
    }

    return next();
}

const isAuthenticated = async (req, res, next) => {
    const accessToken = valueOrNull((req.cookies && req.cookies['x-access-token']) || (req.headers && req.headers['x-access-token']));
    
    if (!accessToken) {
        console.log('accessToken not found')
        return res.status(401).send('UNAUTHORIZED');
    }

    try {
        fileExists(req);
        const { user } = verify(accessToken, ACCESS_SECRET);

        if (user) {
            console.log('VALID USER');
        }
    } catch (err) {
        console.log(err)
        return res.status(401).send('UNAUTHORIZED');
    }

    return next();
};

const valueOrNull = (value) => {
    return (typeof value == 'undefined' || value === null || value === '') ? undefined : value;
}

module.exports = {
    fileExists,
    isAuthenticated
}

.env

ROOT_SHARE=../media

Dockerfile

FROM node:latest

RUN mkdir -p /media

WORKDIR /app

COPY package.json .
COPY package-lock.json .

RUN npm install && npm cache clean --force --loglevel=error

RUN npm install -g pm2

COPY src /app/src

EXPOSE 3000

ENTRYPOINT ["node", "src/server.js"]

exact errornext() 不是函数

Any help would be greatly appreciated

Your fileExists is being used both as a middleware and as a function called in isAuthenticated — in isAuthenticated it's not being passed res or next . If you do pass it there, you may end up having other issues, since both functions call res.status(status).send() . You also have some async keywords on those functions when they're not await ing anything — that's not breaking anything, it's just a waste of a few characters:).

You call:

fileExists(req);

but your implementation of fileExists() expects you to pass it (res, res, next) and you are not passing that. Thus, you get the error next() is not a function when fileExists() tries to call next() .

It's not clear to me exactly what you're trying to do, but perhaps you can change to this where you pass (req, res, callback) to fileExists() and then you continue your processing in that callback. That's how you manually call middleware yourself which it appears you are trying to do:

const isAuthenticated = (req, res, next) => {
    const accessToken = valueOrNull((req.cookies && req.cookies['x-access-token']) || (req.headers && req.headers['x-access-token']));
    
    if (!accessToken) {
        console.log('accessToken not found')
        return res.status(401).send('UNAUTHORIZED');
    }

    try {
        fileExists(req, res, () => {
            const { user } = verify(accessToken, ACCESS_SECRET);

            if (user) {
                console.log('VALID USER');
            }
            return next();

        });
    } catch (err) {
        console.log(err)
        return res.status(401).send('UNAUTHORIZED');
    }

};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM