Node.js中的URL路由

Hen*_*son 5 javascript node.js

做完作业:

Node初学者书

我如何开始使用Node.js [关闭]

在Node中构造处理程序

背景故事:我想尝试编写自己的框架但是我遇到了一些麻烦,很可能是由于没有完全理解它.

我想要实现的是一个如下所示的语法:

var app = require('./app'); //this part is understood and it works in my current code.
app.get('/someUrl', function(){ //do stuff here });
app.post('/someOtherUrl', function(){ //do stuff here });
Run Code Online (Sandbox Code Playgroud)

我知道具有相同语法的Express框架但是阅读它们的源代码仍然让我无法理解.

这可能是一项微不足道的任务,但我还是无法生产它.

尝试require('./app');在应用程序更深的文件中生成一个未定义的对象,所以我猜测服务器是一个单例对象.

那我试过了什么?

我当前的代码看起来像这样,不知怎的,我觉得这是要走的路,但我显然不能这样做.

我省略了所有require();语句以使其更具可读性.

server.js:

var app = module.exports = {
    preProcess: function onRequest(request, response){
        processor.preRequest(request); //this object adds methods on the request object
        var path = urllib.parse(request.url).pathname;
        router.route(urls, path, request, response);
    },
    createServer: function() {
        console.log("Server start up done.");
        return this.server = http.createServer(this.preProcess);
    }
};

exports.app = app;
Run Code Online (Sandbox Code Playgroud)

在撰写本文时,我正在尝试使用方法扩展此对象get().

index.js:

var app = require('./server');
app.createServer().listen('1337');
Run Code Online (Sandbox Code Playgroud)

router.route()位基本上将请求向前发送到应用程序和router.js文件内部我做了一些魔术并将请求路由到一个映射(到目前为止)到/ urlThatWasRequested的函数

这是我想留下的行为.我知道这可能是一个非常高的顺序,但我的所有代码都很容易丢弃,我不怕重写整个代码库,因为这是我自己的项目.

我希望这足以解释我的问题,请说出我应该添加的内容以使其更加清晰.

提前致谢!

fre*_*ish 11

我不确定你的问题是什么,但这里有一些想法:

1)您在这里创建一个循环引用:

var app = module.exports = {
    // some other code
}
exports.app = app;
Run Code Online (Sandbox Code Playgroud)

您添加app为属性app.最后一行没有必要.

2)你需要掌握处理程序app.你可以尝试这样的事情:

var app = module.exports = {
    handlers : [],
    route : function(url, fn) {
        this.handlers.push({ url: url, fn: fn });
    },
    preProcess: function onRequest(request, response){
        processor.preRequest(request);
        var path = urllib.parse(request.url).pathname;
        var l = this.handlers.length, handler;
        for (var i = 0; i < l; i++) {
            handler = this.handlers[i];
            if (handler.url == path)
                return handler.fn(request, response);
        }
        throw new Error('404 - route does not exist!');
    },
    // some other code
}
Run Code Online (Sandbox Code Playgroud)

请注意,您可以更改此行:if (handler.url == path)handler.url正则表达式的方式对其进行测试path.当然,你可以实现.get.post变种,但是从我的经验更容易检查请求是否是GETPOST 内部处理程序.现在您可以使用上面的代码:

app.route('/someUrl', function(req, res){ //do stuff here });
Run Code Online (Sandbox Code Playgroud)

另一件事是我向你展示的代码只触发它匹配的给定URL 的第一个处理程序.您可能希望制作涉及许多处理程序(即中间件)的更复杂的路由.在这种情况下,架构会有所不同,例如:

preProcess: function onRequest(request, response){
    var self = this;
    processor.preRequest(request);
    var path = urllib.parse(request.url).pathname;
    var l = self.handlers.length,
        index = 0,
        handler;
    var call_handler = function() {
        var matched_handler;
        while (index < l) {
            handler = self.handlers[index];
            if (handler.url == path) {
                matched_handler = handler;
                break;
            }
            index++;
        }
        if (matched_handler)
             matched_handler.fn(request, response, function() {
                 // Use process.nextTick to make it a bit more scalable.
                 process.nextTick(call_handler);
             });
        else
             throw new Error('404: no route matching URL!');
     };
     call_handler();
},
Run Code Online (Sandbox Code Playgroud)

现在你可以使用你的路线

app.route('/someUrl', function(req, res, next){ 
    //do stuff here
    next(); // <--- this will take you to the next handler
});
Run Code Online (Sandbox Code Playgroud)

这将带你到另一个处理程序(如果没有更多的处理程序,则抛出异常).

3)关于这些话:

试图要求('./ app'); 在应用程序更深的文件中生成一个未定义的对象,所以我猜测服务器是一个单例对象.

事实并非如此.require始终返回对模块对象的引用.如果你看到了undefined,那么你搞砸了别的东西(改变了模块本身?).

最后说明:我希望它有所帮助.编写自己的框架可能是一项艰巨的任务,尤其是因为已经存在像Express这样的优秀框架.祝你好运!

编辑

实施.get.set方法实际上并不困难.你只需要改变这样的route功能:

route : function(url, fn, type) {
    this.handlers.push({ url: url, fn: fn, type: type });
},
get : function(url, fn) {
    this.route(url, fn, 'GET');
},
post : function(url, fn) {
    this.route(url, fn, 'POST');
},
Run Code Online (Sandbox Code Playgroud)

然后在路由算法中检查type属性是否已定义.如果不是那么使用该路线(undefined类型意味着:始终路线).否则另外检查请求的方法是否与类型匹配.而且你已经完成了!