express.static() 的 Express 中间件没有正确路由并且抛出 next() 不是函数
Express middleware for express.static() not routing correctly and throwing next() is not a function
尽管这个 运行 在我编写和测试它时在我的本地机器上是正确的,但当使用 Docker 部署到我们的 UAT 环境时它似乎失败了。我似乎无法找到为什么它会给我以下信息:
next() is not a function
我似乎也遇到了路由问题(再次仅在部署时出现),即使它在路由 /media/public 时似乎仍然会到达 /media 路由。
依赖关系
"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
Docker文件
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"]
确切错误
如有任何帮助,我们将不胜感激
您的 fileExists
被用作中间件和在 isAuthenticated
中调用的函数 — 在 isAuthenticated
中它没有被传递 res
或 next
.如果你在那里传递它,你可能会遇到其他问题,因为这两个函数都调用 res.status(status).send()
。当这些函数没有 await
ing 任何东西时,您也有一些 async
关键字 — 这没有破坏任何东西,只是浪费了几个字符 :).
您致电:
fileExists(req);
但是您对 fileExists()
的实施期望您通过它 (res, res, next)
而您没有通过它。因此,当 fileExists()
尝试调用 next()
.
时,您会收到错误 next() is not a function
我不清楚你到底想做什么,但也许你可以更改为将 (req, res, callback)
传递给 fileExists()
,然后在该回调中继续处理。这就是您自己手动调用中间件的方式,您似乎正在尝试这样做:
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');
}
};
尽管这个 运行 在我编写和测试它时在我的本地机器上是正确的,但当使用 Docker 部署到我们的 UAT 环境时它似乎失败了。我似乎无法找到为什么它会给我以下信息:
next() is not a function
我似乎也遇到了路由问题(再次仅在部署时出现),即使它在路由 /media/public 时似乎仍然会到达 /media 路由。
依赖关系
"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
Docker文件
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"]
确切错误
如有任何帮助,我们将不胜感激
您的 fileExists
被用作中间件和在 isAuthenticated
中调用的函数 — 在 isAuthenticated
中它没有被传递 res
或 next
.如果你在那里传递它,你可能会遇到其他问题,因为这两个函数都调用 res.status(status).send()
。当这些函数没有 await
ing 任何东西时,您也有一些 async
关键字 — 这没有破坏任何东西,只是浪费了几个字符 :).
您致电:
fileExists(req);
但是您对 fileExists()
的实施期望您通过它 (res, res, next)
而您没有通过它。因此,当 fileExists()
尝试调用 next()
.
next() is not a function
我不清楚你到底想做什么,但也许你可以更改为将 (req, res, callback)
传递给 fileExists()
,然后在该回调中继续处理。这就是您自己手动调用中间件的方式,您似乎正在尝试这样做:
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');
}
};