javascript - 使用大量路由时 res.render() 上的中间件

标签 javascript node.js express

我创建了一个网页以在本地使用它。我有大量的路由,如下所示 - 31 个 .ejs 文件和 3 个 .html 文件。 (它们都在同一个“views”文件夹中)。

//app.js - using node and express
    app.get('/page1', function(req, res){
        res.render('page1');
    });
    app.get('/page2', function(req, res){
        res.sendFile('views/page2.html', { root: __dirname });
    });

我对每个文件都使用 app.get。我有一种感觉,这不是 DRY 代码,所以现在我正在尝试找出一种更优雅、更优化的方法来实现相同的结果。

  • 我知道许多 res.sendFile(); 可以用单个 express.static() 中间件语句替换。我通常在“公共(public)”文件夹上使用 express.static() ,我用它来保存所有 css 文件 - 就像这样 app.use(express.static(path.join(__dirname) ,'公共(public)')));。但我仍然不明白如何使用它来简化我的所有 res.sendFile()

  • 至于许多 res.render(); 路由,我知道如果我不传递任何自定义数据,我可能可以用一个处理以下任意一个的中间件来替换它们:模板文件的整个目录(及其相应的路由)或文件列表。我只是不知道该怎么做。


非常感谢任何帮助,谢谢!

<小时/> [更新]

  • richie
    • node_modules
    • public
      • css files, images, etc
    • views
      • partials
        • all partial files
      • programmingPublic
        • all ejs files from a same topic
      • other files (html & other ejs)
    • appjs
    • packagejson
    • package-lockjson



const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');

const app = express(); 

// Body Parser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));

// engine
app.set("view engine", "ejs");

// Set static path
app.use(express.static(path.join(__dirname, 'public')));

const fs = require('fs');

function renderStatic(dir) {
    return function(req, res, next) {
        let target = path.join(dir, req.path);
        fs.access(target, fs.constants.R_OK, function(err) {
            if (err) {
                // file not found, just move on
                next();
            } else {
                res.render(target);
            }
        });
    }
}

app.use(renderStatic(path.join(__dirname, "views/programmingPublic")));

下面是我的侧菜单的格式:(所有这些文件都在“programmingPublic”文件夹内)

<a href="/programming" class="title">Programming</a>
<li><a href="/c">C</a></li>
<li><a href="/cpp">C++</a></li>
<li><a href="/python">Python</a></li>
<li><a href="/javascript">JavaScript</a></li>
<li><a href="/php">PHP</a></li>

最佳答案

如果您有一堆页面需要调用 res.render(),但没有将自定义选项传递给每个渲染,那么您可以将所有这些模板隔离在它们自己的目录中,然后使用一些像这样的中间件:

const path = require('path');
const fs = require('fs');

function renderStatic(dir, options) {
    const regex = /^\.|\.\.|\/\.|\\\./;
    options = options || {};

    return function(req, res, next) {
        let target = path.join(dir, req.path);
        if (options.ext && !path.extname(target)) {
           target = target + options.ext;
        }
        // don't allow leading dot or double dot anywhere in the path
        if (regex.test(target)) {
           next();
           return;
        }
        fs.access(target, fs.constants.R_OK, function(err) {
            if (err) {
                // file not found, just move on
                next();
            } else {
                res.render(target);
            }
        });
    }
}

app.use(renderStatic(path.join(__dirname, "renderPublic"), {ext: ".ejs"}));

请注意,您必须将这些模板文件隔离在它们自己的目录中,以便在其中找不到其他文件。

为了安全完整性,此代码还需要像 express.static() 一样过滤掉路径中的 ... 项以防止攻击者向上访问您的目录层次结构以访问渲染静态目录中的其他文件。

<小时/>

然后,对于您使用 res.sendFile() 且没有其他逻辑的路由,只需将这些 HTML 文件隔离在它们自己的目录中并指向 express.static() > 在该目录中。然后,express.static() 中间件会在该目录中找到匹配的 HTML 文件,并自动为您执行 res.sendFile() 操作,与您的 CSS 文件。

关于javascript - 使用大量路由时 res.render() 上的中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53233806/

相关文章:

javascript - sqlite3更新查询刷新 Electron 渲染器进程

node.js - Sailsjs 模块

node.js - PassportJS req.user 发送所有用户数据

javascript - 找不到文件 'jquery.ui.sortable'

javascript - 无法在 console.log 中打印 € 符号?

javascript - 我如何在此处的 map 中添加自定义图像标记?

c++ - c++ 和 node.js 之间的 RSA 加密

javascript - Ember.js - 在哪里放置下拉选项?

node.js - 服务器重启时自动启动 Node.js 应用程序(Ghost Blog)

javascript - 使用node或express js从请求中获取客户端Windows登录用户名