将快速路线分成单独的文件

时间:2015-12-17 04:30:04

标签: javascript node.js express

我已经尝试过我在s / o上找到的每一个答案,而且我确定我必须遗漏一些东西。对我来说没有什么错误反而给了我404.我尝试了Organize routes in Node.js,strongloop&#39} route-separation模式的答案,来自How to include route handlers in multiple files in Express?的答案,遇到类似的错误在Router.use requires middleware function?,但这些答案都没有奏效。 Unable to Split Routes into Separate Files in Express 4.0的答案不是错误,而是404s。似乎每个答案都有不同的语法和风格,也许我的混音和匹配不正确?

现在我的/routes/persons.js有这种模式:

    var express = require('express');
    var persons = express.Router();

    persons.route('/persons/:user_id')
        .put(function (req, res, next) {
            // etc
    });

    module.exports = persons;       

在我的server.js文件中,我有:

    var persons = require('./routes/persons');
    app.use('/persons', persons);

这种组合不会引发错误,但它也没有做任何事情。我尝试将端点添加到server.js行:

    var persons = require('./routes/persons');
    app.get('/persons/:user_id', persons.addpersons);

并剥离persons.js直到导出函数:

    exports.addpersons = function (req, res, next) {
            var list = req.body;
            // etc
    }

另外还有变体,例如在module.exports = function()中包装整个person.js文件,在最后粘贴module.exports = router,使用app代替router等。

我在俯瞰什么?我应该添加一些其他中间件,重新安排我如何调用端点,使用应用程序,或坚持使用router.route?如果没有错误但端点仍然是404,那么最有可能的罪魁祸首是什么?

提前多多感谢!

=============已编辑包含SERVER.JS =============

由于很清楚某些内容设置错误,在某处,这里是我的server.js文件:

        var express = require('express');
        var app = express();
        var methodOverride = require('method-override');
        var mongoose = require('mongoose');
        var bodyParser = require('body-parser');
        var router = express.Router();
        var jwt    = require('jsonwebtoken');
        var config = require('./config');
        var nodemailer = require('nodemailer');
        var bcrypt = require('bcrypt-nodejs');
        var crypto = require('crypto');
        var async = require('async');

        var transporter = nodemailer.createTransport({
            service: 'gmail',
            auth: {
                user: 'email@gmail.com',
                pass: 'password'
            }
        });

        // I don't know if both are necessary, used multiple conflicting tutorials
        app.use(require('express-session')({
            secret: 'secret',
            resave: false,
            saveUninitialized: false
        }));
        app.set('superSecret', config.secret);

        var Schema = mongoose.Schema,
            Person = require('./models/person.js'),
            User = require('./models/user.js'),
            Event = require('./models/event.js');

        var port = process.env.PORT || 8080;
        mongoose.connect(config.database);

        app.use(bodyParser.json());
        app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
        app.use(bodyParser.urlencoded({ extended: true }));
        app.use(methodOverride('X-HTTP-Method-Override'));
        app.use(express.static(__dirname + '/public'));

        // routes go here

        app.use('/api', router);
        app.listen(port);
        console.log('gogogo port ' + port);

我不知道在哪里我可能会寻找为什么包含路线需要在通常的模式中打破这样的。我的配置文件?我的procfile?这些是服务器上唯一的其他文件,不包括/ models和/ routes。

3 个答案:

答案 0 :(得分:3)

这里的关键是要了解app.use()req对象的影响(特别是req.path),app.get()和朋友的不同,以及Express如何包装path-to-regexp(其内部路径匹配模块)来处理路由。

1)app.use(path, middleware) 安装中间件。在已安装的中间件/路由器内,req.path相对于安装路径。只有请求路径的开头需要匹配,因此/foo将适用于/foo的请求(相对路径为/),/foo/bar(相对路径为{{ 1}})等。

/bar

尝试运行上面的设置,导航到app.use(function (req, res, next) { console.log('Main: %s %s', req.method, req.path); next(); }); app.use('/foo', function (req, res) { console.log('In /foo: %s %s', req.method, req.path); res.send('Got there'); }); 并查看以下日志:

localhost/foo

2)Main: GET /foo In /foo: GET / app.get(path, middleware)无法挂载目标中间件,因此保留app.post(path, middleware)req.path必须与您定义路线的整个模式相匹配,因此req.path仅适用于/foo次请求。

/foo

导航至app.use(function (req, res, next) { console.log('Main: %s %s', req.method, req.path); next(); }); app.get('/foo', function (req, res) { console.log('In /foo: %s %s', req.method, req.path); res.send('Got there'); }); 并查看:

localhost/foo

3)Main: GET /foo In /foo: GET /foo ,如快速文档中所述,只是方便定义多个app.route(path)app.get(middleware)等共享相同的app.post(middleware)

现在,在您的情况下,这是一个有效的设置:

主要

path

<强>路由/ persons.js

var persons = require('./routes/persons');
app.use('/persons', persons);

这很方便,因为您只需在主文件中设置一次var router = require('express').Router(); router.route('/:user_id') .post(function (req, res) { // handle potato data }) .get(function (req, res) { // get and send potato data }); module.exports = router; 入口点,以便以后可以根据需要轻松更新它(您也可以从配置文件中导入该路径值,来自您的路由器对象或其他什么,Node在这方面非常灵活)。 人员路由器本身负责管理其业务控制器,无论它在何处完全安装。

答案 1 :(得分:0)

而不是

persons.route('/persons/:user_id')
    .put(function (req, res, next) {
        // etc
});

做的:

persons.put('/persons/:user_id',function (req, res, next) {
  // etc
});

答案 2 :(得分:0)

我想出来了!

当然,这可能是完全错误的方式(请告诉我,如果是这样),但它的工作原理。

在我的server.js文件中,我有:

    var persons = require('./routes/persons');
    router.get('/persons/:user_id', persons);
    router.post('/persons/:user_id', persons);

和我的persons.js文件现在看起来像这样:

    var mongoose = require('mongoose');
    var express = require('express');
    var router = express.Router();

    var Schema = mongoose.Schema,
        Person = require('../models/person.js');

    router.post('/persons/:user_id', function (req, res) {
        var potatoBag = req.body;
        Person.collection.insert(potatoBag, function onInsert(err, potatoBag) {
            if (err) {
                return res.json(err);
            } else {
                res.status(200).end();
            }
        });
    });

    router.get('/persons/:user_id', function(req, res) {
        var id = req.params.user_id;
        Person.find({'user_id':id},function(err, person) {
            if (err)
                return res.json(err);
            res.send(person);
        });
    });

    module.exports = router;

这似乎比大多数示例的开销更大,但也许是因为a)使用router.route和b)使用导入的模式?我在那里也有(req, res, next),它在我移除next件之前一直保持适合。可能仍然有点尴尬,但嘿,它的工作。感谢大家的帮助!