在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
方法其实并不困难。 你只需要像这样改变route
function:
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
属性。 如果不是,那么使用该路线( undefined
types意味着:总是路线)。 否则,另外检查一个请求的方法是否匹配types。 你完成了!