创建服务器及请求响应等简单的node.js例子

457 查看

1 服务器

1.1 server.js创建服务器

http.createServer(function(request, response) {
    console.log("Request received");
    response.writeHead("200", { "Content-Type": "text/plain" });
    response.write("it works");
    response.end();
}).listen(8888);

console.log("Server has started");

1.2 模块化server.js

var http = require("http");

function start() {
    http.createServer(function(request, response) {
        console.log("Request received");
        response.writeHead("200", { "Content-Type": "text/plain" });
        response.write("it works");
        response.end();
    }).listen(8888);

    console.log("Server has started");
}

exports.start = start; //导出模块

1.3 引用server模块

var server = require("./server"); //index.js文件中引用server模块
server.start(); //模块中start方法

2 路由

2.1 url模块

var http = require("http");
var url = require("url"); //引用url模块

function start() {
    http.createServer(function(request, response) {
        console.log("Request received");
        console.log(url); //url模块有如下几个方法
        //{ parse: [Function: urlParse],
        // resolve: [Function: urlResolve],
        // resolveObject: [Function: urlResolveObject],
        // format: [Function: urlFormat],
        // Url: [Function: Url] }

        console.log(request.url);
        //当访问http://localhost:8888/index时返回如下结果:
        ///index
        ///favicon.ico

        console.log(url.parse(request.url)); //解析request.url,返回Url对象,结果如下:
        // Url {
        //   protocol: null,
        //   slashes: null,
        //   auth: null,
        //   host: null,
        //   port: null,
        //   hostname: null,
        //   hash: null,
        //   search: null,
        //   query: null,
        //   pathname: '/index',
        //   path: '/index',
        //   href: '/index' }        

        console.log(url.parse(request.url).pathname); //获取pathname
        //当访问http://localhost:8888/index时返回如下结果:
        ///index
        ///favicon.ico

        var pathname = url.parse(request.url).pathname;
        response.writeHead("200", { "Content-Type": "text/plain" });
        response.write("Request for " + pathname + " received."); //刷新页面即显示pathname
        //Request for /index received.

        response.end();
    }).listen(8888);

    console.log("Server has started");
}

exports.start = start;

2.2 router.js编辑路由

function route(pathname) {
    console.log("About to route a request for " + pathname);
}

exports.route = route;

2.3 引用router模块

index.js文件编写:

var server = require("./server");
var router = require("./router"); //引用router模块
server.start(router.route); //start方法传入router模块中的route方法

2.4 调用router.route方法

var http = require("http");
var url = require("url");

function start(route) {
    http.createServer(function(request, response) {
        console.log("Request received");
        
        var pathname = url.parse(request.url).pathname;
        console.log("Request for " + pathname + " received.");

        route(pathname); //调用route方法

        response.writeHead("200", { "Content-Type": "text/plain" });
        response.write("it works.");
        response.end();
    }).listen(8888);

    console.log("Server has started");
}

exports.start = start;

3 事件处理程序处理URL

3.1 requestHandlers.js

function start() {
    console.log("Request handler 'start' has called.");
}
function upload() {
    console.log("Request handler 'upload' has called.");
}
exports.start = start;
exports.upload = upload;

3.2 index.js引入requestHandlers模块

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {};
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;

server.startServer(router.route, handle);

3.3 修改server.js

var http = require("http");
var url = require("url");

function startServer(route, handle) {
    http.createServer(function(request, response) {
        var pathname = url.parse(request.url).pathname;
        route(handle, pathname);
        response.writeHead(200, { "Content-Type": "text/plain" });
        response.write("hello world");
        response.end();
    }).listen(8888);
}

exports.startServer = startServer;

3.4 修改router.js

function route(handle, pathname) {
    console.log("path: " + pathname);
    if (typeof handle[pathname] === "function") {
        handle[pathname]();
    } else {
        console.log("No request handler found for " + pathname);
    }
}

exports.route = route;

至此,我们已经可以通过输入不同url来触发不同的事件处理程序:

index.js:

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {};
handle["/"] = requestHandlers.index;
handle["/about"] = requestHandlers.about;
server.start(router.route, handle);

server.js:

var http = require("http");
var url = require("url");
function start(route, handle) {
    http.createServer(function(request, response) {
        var pathname = url.parse(request.url).pathname;
        route(pathname, handle);

        response.writeHead(200, { "Content-Type": "text/plain" });
        response.write("hello");
        response.end();
    }).listen(8888);
}

exports.start = start;

router.js:

function route(pathname, handle) {
    console.log("path: " + pathname);
    if (typeof handle[pathname] === "function") {
        handle[pathname]();
    } else {
        console.log("404");
    }
}
exports.route = route;

requestHandlers.js:

function index() {
    console.log("index page.");
}
function about() {
    console.log("about page.");
}
exports.index = index;
exports.about = about;

访问localhost:8888/about会返回about page.


4 router路由处理response

4.1 修改server.js

var http = require("http");
var url = require("url");

function start(route, handle) {
    http.createServer(function(request, response) {

        var pathname = url.parse(request.url).pathname;
        route(pathname, handle, response); //response传递给route

    }).listen(8888);
}

exports.start = start;

4.2 修改router.js

function route(pathname, handle, response) {
    console.log("path: " + pathname);
    if (typeof handle[pathname] === "function") {
        handle[pathname]();
    } else {
        response.writeHead(404, { "Content-Type": "text/plain" });
        response.write("404 not found.");
        response.end();
    }
}
exports.route = route;

4.3 修改requestHandlers.js

function index(response) {
    console.log("index page.");
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.write("wel zealzing.cn");
    response.end();
}

function about(response) {
    console.log("about page.");
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.write("About us.");
    response.end();
}
exports.index = index;
exports.about = about;

当然,在router.js中也需要修改一下if-else循环语句中的部分:

if (typeof handle[pathname] === "function") {
    handle[pathname](response); //传入response参数
} else {
    response.writeHead(404, { "Content-Type": "text/plain" });
    response.write("404 not found.");
    response.end();
}

5 处理POST请求

5.1 生成表单

function index(response) {
    console.log("index page.");
    response.writeHead(200, { "Content-Type": "text/html" });
    var body = "<!DOCTYPE html>"+"<html lang='en'>"+"<head>"+"<meta charset='UTF-8'>"+"</head>"+"<body>"+"<form action='message' method='post'>"+"<label for='texture'></label>"+"<input type='text' name='texture'></input>"+"<input type='submit' value='submit'></input>"+"</form>"+"</body>"+"</html>";
    response.end(body);
}

function about(response) {
    console.log("about page.");
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.write("About us.");
    response.end();
}
exports.index = index;
exports.about = about;

注意:头部信息要改为text/html而不是text/plain

5.2 事件监听器

事件监听器分为两个部分:

request.addListener("data", function(chunk) {
    // body...a new chunk of data was received.
});
request.addListener("end", function() {
    // body...all chunks of data have been received.
});

5.3 增加事件监听器

var http = require("http");
var url = require("url");

function start(route, handle) {
    http.createServer(function(request, response) {
        var postData = ""; //postData
        var pathname = url.parse(request.url).pathname;

        request.setEncoding("utf-8"); //encoding to utf-8
        request.addListener("data", function(chunk) {
            postData = postData + chunk; //received chunk...
            //console.log("Received POST data chunk " + chunk + "."); //输出到log可有可无
        });
        request.addListener("end", function() {
            route(pathname, handle, response, postData); //postData传递给route
        });
    }).listen(8888);
}

exports.start = start;

5.4 修改router.js

function route(pathname, handle, response, postData) {
    console.log("path: " + pathname);
    if (typeof handle[pathname] === "function") {
        handle[pathname](response, postData); //传入postData参数
    } else {
        response.writeHead(404, { "Content-Type": "text/plain" });
        response.write("404 not found.");
        response.end();
    }
}
exports.route = route;

5.5 最后再修改requestHandler

function index(response, postData) {
    console.log("index page.");
    response.writeHead(200, { "Content-Type": "text/html" });
    var body = "<!DOCTYPE html>"+"<html lang='en'>"+"<head>"+"<meta charset='UTF-8'>"+"</head>"+"<body>"+"<form action='/about' method='post'>"+"<label for='texture'></label>"+"<input type='text' name='texture'></input>"+"<input type='submit' value='submit'></input>"+"</form>"+"</body>"+"</html>";
    response.end(body);
}

function about(response, postData) {
    console.log("about page.");
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.write("About " + postData + "."); //这里返回数据
    response.end();
}
exports.index = index;
exports.about = about;

5.6 提取字段text值

如果直接使用上述代码运行,当输入值为Oliver时:


About texture=Oliver.

显然这不是我们想要的,应该在requestHandler修改如下代码:

var querystring = require("querystring"); //引入模块
function index(response, postData) {
    console.log("index page.");
    response.writeHead(200, { "Content-Type": "text/html" });
    var body = "<!DOCTYPE html>"+"<html lang='en'>"+"<head>"+"<meta charset='UTF-8'>"+"</head>"+"<body>"+"<form action='/about' method='post'>"+"<label for='texture'></label>"+"<input type='text' name='texture'></input>"+"<input type='submit' value='submit'></input>"+"</form>"+"</body>"+"</html>";
    response.end(body);
}

function about(response, postData) {
    console.log("about page.");
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.write("About " + querystring.parse(postData).texture + "."); //parseing
    response.end();
}
exports.index = index;
exports.about = about;

这样就可以了,如果在texture中填写js脚本,node貌似也不会执行:

Received POST data chunk texture=%3Cscript%3Ealert%28%22wtf%22%29%3B%3C%2Fscript%3E.

server.js:


var http = require("http");
var url = require("url");

function start(route, handle) {
    http.createServer(function(request, response) {
        var postData = ""; //postData
        var pathname = url.parse(request.url).pathname;

        request.setEncoding("utf-8"); //encoding to utf-8
        request.addListener("data", function(chunk) {
            postData = postData + chunk; //received chunk...
            console.log("Received POST data chunk " + chunk + ".");
        });
        request.addListener("end", function() {
            route(pathname, handle, response, postData); //postData传递给route
        });
    }).listen(8888);
}

exports.start = start;

index.js:

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {};
handle["/"] = requestHandlers.index;
handle["/index"] = requestHandlers.index;
handle["/about"] = requestHandlers.about;

server.start(router.route, handle);

router.js:

function route(pathname, handle, response, postData) {
    console.log("path: " + pathname);
    if (typeof handle[pathname] === "function") {
        handle[pathname](response, postData); //传入postData参数
    } else {
        response.writeHead(404, { "Content-Type": "text/plain" });
        response.write("404 not found.");
        response.end();
    }
}
exports.route = route;

requestHandler.js:

var querystring = require("querystring"); //引入模块
function index(response, postData) {
    console.log("index page.");
    response.writeHead(200, { "Content-Type": "text/html" });
    var body = "<!DOCTYPE html>"+"<html lang='en'>"+"<head>"+"<meta charset='UTF-8'>"+"</head>"+"<body>"+"<form action='/about' method='post'>"+"<label for='texture'></label>"+"<input type='text' name='texture'></input>"+"<input type='submit' value='submit'></input>"+"</form>"+"</body>"+"</html>";
    response.end(body);
}

function about(response, postData) {
    console.log("about page.");
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.write("About " + querystring.parse(postData).texture + "."); //parseing
    response.end();
}
exports.index = index;
exports.about = about;

6 文件上传

直接使用formidable模块:

npm install formidable

以及fs模块读写硬盘中的文件

var fs = require("fs");