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"]
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.