正如所见,将不同的URL映射到相同的请求处理程序上是很容易的:只要在对象中添加一个键为"https://www.jb51.net/"的属性,对应requestHandlers.start即可,这样我们就可以干净简洁地配置/start和/的请求都交由start这一处理程序处理。
在完成了对象的定义后,我们把它作为额外的参数传递给服务器,为此将server.js修改如下:
复制代码 代码如下:
var http = require("http");
var url = require("url");
function start(route, handle) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(handle, pathname);
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
这样我们就在start()函数里添加了handle参数,并且把handle对象作为第一个参数传递给了route()回调函数。
然后我们相应地在route.js文件中修改route()函数:
复制代码 代码如下:
function route(handle, pathname) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname]();
} else {
console.log("No request handler found for " + pathname);
}
}
exports.route = route;
通过以上代码,我们首先检查给定的路径对应的请求处理程序是否存在,如果存在的话直接调用相应的函数。我们可以用从关联数组中获取元素一样的方式从传递的对象中获取请求处理函数,因此就有了简洁流畅的形如handle[pathname]();的表达式,这个感觉就像在前方中提到的那样:“嗨,请帮我处理了这个路径”。
有了这些,我们就把服务器、路由和请求处理程序在一起了。现在我们启动应用程序并在浏览器中访问:8888/start,以下日志可以说明系统调用了正确的请求处理程序:
复制代码 代码如下:
Server has started.
Request for /start received.
About to route a request for /start
Request handler 'start' was called.
并且在浏览器中打开:8888/可以看到这个请求同样被start请求处理程序处理了:
复制代码 代码如下:
Request for / received.
About to route a request for /
Request handler 'start' was called.
让请求处理程序作出响应
很好。不过现在要是请求处理程序能够向浏览器返回一些有意义的信息而并非全是“Hello World”,那就更好了。
这里要记住的是,浏览器发出请求后获得并显示的“Hello World”信息仍是来自于我们server.js文件中的onRequest函数。
其实“处理请求”说白了就是“对请求作出响应”,因此,我们需要让请求处理程序能够像onRequest函数那样可以和浏览器进行“对话”。
不好的实现方式
对于我们这样拥有PHP或者Ruby技术背景的开发者来说,最直截了当的实现方式事实上并不是非常靠谱: 看似有效,实则未必如此。
这里我指的“直截了当的实现方式”意思是:让请求处理程序通过onRequest函数直接返回(return())他们要展示给用户的信息。
我们先就这样去实现,然后再来看为什么这不是一种很好的实现方式。
让我们从让请求处理程序返回需要在浏览器中显示的信息开始。我们需要将requestHandler.js修改为如下形式:
复制代码 代码如下:
function start() {
console.log("Request handler 'start' was called.");
return "Hello Start";
}
function upload() {
console.log("Request handler 'upload' was called.");
return "Hello Upload";
}
exports.start = start;
exports.upload = upload;
好的。同样的,请求路由需要将请求处理程序返回给它的信息返回给服务器。因此,我们需要将router.js修改为如下形式:
复制代码 代码如下:
function route(handle, pathname) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
return handle[pathname]();
} else {
console.log("No request handler found for " + pathname);
return "404 Not found";
}
}
exports.route = route;
正如上述代码所示,当请求无法路由的时候,我们也返回了一些相关的错误信息。
最后,我们需要对我们的server.js进行重构以使得它能够将请求处理程序通过请求路由返回的内容响应给浏览器,如下所示:
复制代码 代码如下:
var http = require("http");
var url = require("url");