在Node.js中的URL路由

作业完成:

节点初学者书

如何开始使用Node.js [已closures]

在Node中构造处理程序

Backstory:我想尝试写自己的框架,但是我遇到了一些麻烦,很可能是因为没有完全理解。

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

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 }); 

我知道有这个相同的语法的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; 

在写这篇文章的时候,我正在尝试用get()方法扩展这个对象。

index.js:

 var app = require('./server'); app.createServer().listen('1337'); 

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

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

我希望这足以说明我的问题,否则请说出我应该补充的内容,使之更加清晰。

提前致谢!

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

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

 var app = module.exports = { // some other code } exports.app = app; 

您将app添加为app的属性。 不需要最后一行。

2)你需要在app程序中持有处理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 } 

请注意,您可能会改变这一行: if (handler.url == path)以这样一种方式处理handler.url是一个正则expression式,并testing它的path 。 当然你可以实现.get.post变体,但是根据我的经验,在处理程序中检查请求是GET还是POST更容易。 现在你可以像这样使用上面的代码:

 app.route('/someUrl', function(req, res){ //do stuff here }); 

另一件事是,我已经展示给你的代码只激发它匹配的给定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(); }, 

现在在你的路线内,你可以使用

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

这将带你到另一个处理程序(或抛出exception,如果没有更多的处理程序)。

3)关于这些话:

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

这不是真的。 require总是返回模块对象的引用。 如果你看到undefined ,那么你已经搞砸了其他东西(改变模块本身?)。

最后说明:我希望它有一点帮助。 编写自己的框架可能是一件困难的工作,尤其是因为已经有像Express这样的优秀框架。 祝你好运!

编辑

实现.get.set方法其实并不困难。 你只需要像这样改变routefunction:

 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'); }, 

然后在路由algorithm中检查是否定义了type属性。 如果不是,那么使用该路线( undefinedtypes意味着:总是路线)。 否则,另外检查一个请求的方法是否匹配types。 你完成了!