我已经在寻找解决办法了,但不幸的是没有一个奏效。也许你能帮助我。
我正在用Node.JS和Express编写一个基于插件的Web服务器。主要的Web服务器代码如下所示:
在这一部分,所有的插件都被初始化了,主服务器的所有路由都被初始化了。下面是插件和主服务器的编译
const express = require('express');
const path = require('path');
const fs = require('fs');
const settings = require('../settings/settings');
// Events
const events = require('./functions/events/events');
// Webserver
const app = express();
// Ordnerpfade definieren
const pluginsPath = path.join(__dirname, 'plugins');
const publicPath = path.join(__dirname, 'public');
const routesPath = path.join(__dirname, 'routes');
const viewsPath = path.join(__dirname, 'views');
// ETA RENDER ENGINE
const eta = require('eta');
eta.configure({
views: viewsPath,
useWith: true,
autoEscape: true,
cache: false
});
app.set('view engine', 'eta');
// Öffentliche Ressourcen des Webservers
app.use(express.static(publicPath, {
redirect: false
}));
// Plugins einbinden
global.plugins = {};
global.plugins.pluginData = {};
var pluginsActive = {}; //aktive Plugins
var pluginSettings = []; // Settings einzelner Plugins
var pluginAssets = []; // Assets einzelner Plugins
var pluginData = [];
function filterDirectories(dir) {
return fs.lstatSync(path.join(pluginsPath, dir)).isDirectory();
}
function getFilesInDirRec(fileExtension, pluginPublicFolder, dirPath, ignoredDirs, pluginName) {
let files = [];
fs.readdirSync(dirPath).forEach((file) => {
const filePath = path.join(dirPath, file);
const fileStat = fs.statSync(filePath);
if (fileStat.isDirectory()) {
if (!ignoredDirs.includes(file)) {
const subDirFiles = getFilesInDirRec(
fileExtension,
pluginPublicFolder,
filePath,
ignoredDirs,
pluginName
);
files = files.concat(subDirFiles);
}
} else if (file.endsWith(`.${fileExtension}`)) {
var assetPath = path.join("/", pluginName, path.relative(pluginPublicFolder, filePath));
files.push(assetPath);
}
});
return files;
}
fs.readdirSync(pluginsPath).filter(filterDirectories).forEach(pluginName => {
pluginData[pluginName] = {};
// Pfad zum Plugin
const pluginPath = path.join(pluginsPath, pluginName);
// Öffentliche Ressourcen des Plugins
const pluginPublicPath = path.join(pluginPath, 'public');
if (fs.existsSync(pluginPublicPath)) {
app.use(`/${pluginName}`, express.static(pluginPublicPath, {
redirect: false
}));
}
// Routen des Plugins
const pluginRoutesPath = path.join(pluginPath, 'routes');
if (fs.existsSync(pluginRoutesPath)) {
fs.readdirSync(pluginRoutesPath).forEach(routeName => {
routeName = routeName.split('.')[0];
if(routeName === "index"){ routeName = ""}
const router = require(path.join(pluginRoutesPath, routeName));
app.use(path.join('/', pluginName, routeName), router);
});
}
// Views des Plugins
const pluginViewsPath = path.join(pluginPath, 'views');
if (fs.existsSync(pluginViewsPath)) {
app.set(`views`, [pluginViewsPath, viewsPath]);
}
// JS und CSS Dateien des Plugins auslesen
const ignoredDirNames = ["helper"];
const pluginJSfiles = getFilesInDirRec( "js", pluginPublicPath, path.join(pluginPublicPath, 'js'), ignoredDirNames, pluginName);
const pluginCSSfiles = getFilesInDirRec( "css", pluginPublicPath, path.join(pluginPublicPath, 'css'), ignoredDirNames, pluginName);
// Dateiendung // Unterordner in "plugin/public"
pluginData[pluginName].assets = {};
pluginData[pluginName].assets.css = pluginCSSfiles;
pluginData[pluginName].assets.js = pluginJSfiles;
// Settings des Plugins
const pluginsSettingsPath = path.join(pluginPath, 'settings');
if (fs.existsSync(pluginsSettingsPath)) {
const thisPluginSettings = require(`${pluginsSettingsPath}/pluginSettings`);
pluginData[pluginName].settings = thisPluginSettings;
}
// Alle aktivierten Plugins global speichern
pluginsActive[pluginName] = true;
});
global.plugins.active = pluginsActive;
global.plugins.pluginData = pluginData;
// Middleware
const middleware = require('./middleware/middleware');
// Routen des Webservers hinzufügen
fs.readdirSync(routesPath).forEach(routeName => {
routeName = routeName.split('.')[0];
if(routeName === "index"){ routeName = ""}
const router = require(path.join(routesPath, routeName));
app.use(`/${routeName}`, router);
});
// Handle 404
app.use(function(req, res) {
if (res.headersSent) {
return;
}
res.status(404);
res.render("404", {});
});
const start = function() {
// Webserver starten
app.listen(settings.server.port, () => {
console.log('Webserver gestartet unter Port: ' + settings.server.port);
});
};
module.exports = {
start
};
下面是Web服务器的路由index
和test
。
const express = require('express');
const router = express.Router({ strict: true });
const eta = require('eta');
const path = require('path');
const viewsPath = path.join(__dirname, '..', 'views');
eta.configure({
views: viewsPath
});
const middleware = require('../middleware/middleware');
// Router-Instanz in Middleware-Funktion umwandeln
const pluginRouter = express();
pluginRouter.use(router);
// Eine Route-Instanz definieren
router.get('/', [middleware.plugins.getActivePlugins, middleware.metaData.getMetaDataSkeleton], async (req, res, next) => {
var templateData = {};
templateData = req.middlewareData.templateData;
templateData.metaData.title = templateData.metaData.app.name + " - Startseite";
templateData.metaData.customMetaTags.push({
proberty: "test",
oder: true,
but: "no"
});
console.log(templateData);
eta.renderFile('index', templateData)
.then(html => {
res.send(html);
})
.catch(err => {
console.error(err);
res.sendStatus(500);
});
});
// Eine Route-Instanz definieren
router.get('/test', [middleware.plugins.getActivePlugins, middleware.metaData.getMetaDataSkeleton], async (req, res, next) => {
var templateData = {};
templateData = req.middlewareData.templateData;
templateData.metaData.title = templateData.metaData.app.name + " - Startseite";
templateData.metaData.customMetaTags.push({
proberty: "test",
oder: true,
but: "no"
});
console.log(templateData);
eta.renderFile('index', templateData)
.then(html => {
res.send(html);
})
.catch(err => {
console.error(err);
res.sendStatus(500);
});
});
module.exports = pluginRouter;
当我调用那里的一条路由时,无论是https://example.cc
还是https://example.cc/test
-链接都不会改变,保持原样。
然而,当我调用插件的路由时,例如https://example.cc/blog或https://example.cc/tags,斜线/
总是自动添加到链接的末尾,结果为https://example.cc/blog/和https://example.cc/tags/ Google Chrome中的开发者控制台说,有一个301重定向到末尾为/
的页面。
下面是插件的一个路由的代码:
const path = require("path");
const express = require('express');
const router = express.Router();
const eta = require('eta');
const viewsPath = path.join(__dirname, "..", 'views');
eta.configure({
views: viewsPath
});
// Registrieren des Event-Listeners
const events = require('../../../functions/events/events');
// Plugin Router Initialisieren
const pluginRouter = express();
pluginRouter.use(router);
// GLOBAL MIDDLEWARE
const middleware = require('./../../../middleware/middleware');
// LOCAL MIDDLEWARE
const pluginMiddleware = require('./../middleware/pluginMiddleware');
const testMiddleware = pluginMiddleware.test;
// Eine Route-Instanz definieren
router.get('/', [middleware.plugins.getActivePlugins, middleware.metaData.getMetaDataSkeleton, testMiddleware], (req, res, next) => {
var templateData = {};
templateData = req.middlewareData.templateData;
templateData.metaData.title = templateData.metaData.app.name + " - Blog";
console.log(templateData);
// Auslösen eines Events
events.emitter.emit('getBlogIndex', {
eventData: "is-test"
});
// Rendern einer Datei
eta.renderFile(path.join(viewsPath, 'index'), templateData)
.then(html => {
res.send(html);
})
.catch(err => {
console.error(err);
res.sendStatus(500);
});
});
module.exports = pluginRouter;
无论我尝试什么,都没有效果。它总是在插件中进行301重定向到同一页面,但有额外的/
。
我尝试了以下方法:
我读到这与静态文件有关。每个插件都有自己的静态文件夹。该目录与插件路由目录处于同一级别。https://expressjs.com/en/4x/api.htmlExpress adds slash at the end of url weirdly
所以我试着将选项redirect
设置为false。不幸的是,这并没有带来任何成功。
对于插件:
// Öffentliche Ressourcen des Plugins
const pluginPublicPath = path.join(pluginPath, 'public');
if (fs.existsSync(pluginPublicPath)) {
app.use(`/${pluginName}`, express.static(pluginPublicPath, {
redirect: false
}));
}
对于主Web服务器
// Öffentliche Ressourcen des Webservers
app.use(express.static(publicPath, {
redirect: false
}));
然后我也试着在插件路由器中设置strict
选项,这也不起作用。
Express adds slash at the end of url weirdly
在每条路线中
const router = express.Router({ strict: true });
我也尝试了两者的组合。没有什么会导致路由停止做301转发。
除此之外,我还尝试了这个选项:Trailing slash gets appended to url in express server
在主Web服务器初始化时
app.enable('strict routing');
可惜也没什么用。我不知道还能找什么。你能帮我吗?因为我来这里很不幸没有更远。会很高兴的!亲切的问候。
我正在使用快捷方式^4.18.2
1条答案
按热度按时间cuxqih211#
休息了几个小时后,我重新审视了这个问题,并解决了它。这是一个偶然的机会,但我在Chrome开发者控制台中看到,该页面是从磁盘缓存加载的。这就是为什么我的尝试失败的全部问题。
所以我重复了我失败的尝试,解决方案很简单。我只是在插件路径中添加了这一行:
我开始隐姓埋名的模式是为了有一个原始的环境。看,一切都像它应该的那样工作。
现在我可以通过
http://example.cc/blog
和http://example.cc/blog/
访问每个路由,没有任何区别。我没想到在服务器上调用的操作也会以某种方式缓存在客户端上,这里只是一个链接,但这足以让我忙上一阵子。
干杯。