第4章 构建Node Web程序

来源:互联网 发布:淘宝舒口健牙膏 编辑:程序博客网 时间:2024/06/08 12:00

4.1 HTTP服务器的基础知识
这里写图片描述

4.1.1 Node如何向开发者呈现HTTP请求
这里写图片描述

4.1.2 一个用“Hello World”做响应的HTTP服务器

var http = require('http');var server = http.createServer(function(req,res){        //res.end('Hello World');        res.write('Hello World');        res.end();});server.listen(3000);

这里写图片描述

4.1.3 读取请求头和设定响应头
res.setHeader(field,value)
res.getHeader(field)
res.removeHeader(field)

4.1.4 设定HTTP响应的状态码
设定res.statusCode属性。

4.2 构建RESTful Web服务

4.2.1 用POST请求创建资源
4.2.2 用GET请求获取资源
4.2.3 用DELETE请求移除资源
这里写图片描述

var http = require('http');var url = require('url');var items = [];var server = http.createServer(function(req,res){    switch(req.method) {        case 'POST':            var item = '';            req.setEncoding('utf8');            req.on('data',function(chunk){                item += chunk;            });            req.on('end',function(){                items.push(item);                res.end('OK\n');            });            break;        case 'GET':            items.forEach(function(item,i){                res.write(i + ') ' + item + '\n');            });            res.end();            break;        case 'DELETE':            var path = url.parse(req.url).pathname;            var i = parseInt(path.slice(1),10);            //检查数字是否有效            if(isNaN(i)) {                res.statusCode = 400;                res.end('Invalid item id');            }else if(!items[i]) {                res.statusCode = 404;                res.end('Item not found');            }else {                items.splice(i,1);                res.end('OK\n');            }            break;    }});server.listen(3000);

4.3 提供静态文件服务

4.3.1 创建一个静态文件服务器

//最基本的ReadStream静态文件服务器var http = require('http');var parse = require('url').parse;var join = require('path').join;var fs = require('fs');var root = __dirname;var server = http.createServer(function(req,res){    var url = parse(req.url);    //构造绝对路径    var path = join(root,url.pathname);    //创建fs.ReadStream    var stream = fs.createReadStream(path);    //将文件数据写到响应中    stream.on('data',function(chunk){        res.write(chunk);    });    stream.on('end',function(){        res.end();    });});server.listen(3000);

用stream.pipe()优化数据传输

var readStream = fs.createReadStream('./original.txt');var writeStream = fs.createWriteStream('./copy.txt');readStream.pipe(writeStream);

读取一个文件(ReadableStream)并把其中的内容写到另一个文件(WritableStream)中用的就是管道

4.3.2 处理服务器错误
为了防止服务器被错误搞垮,我们要监听错误,在fs.ReadStream上注册一个error事件处理器,返回状态码500表明有服务器内部错误。

var server = http.createServer(function(req,res){    var url = parse(req.url);    //构造绝对路径    var path = join(root,url.pathname);    //创建fs.ReadStream    var stream = fs.createReadStream(path);    //res.end()会在stream.pipe()内部调用    stream.pipe(res);    stream.on('error',function(err){        res.statusCode = 500;        res.end('Internal Server Error');    });});

4.3.3 用fs.stat()实现先发制人的错误处理
可以用stat()系统调用获取文件的相关信息,比如修改时间、字节数。

//检查文件是否存在,并在响应中提供Content-Lengthvar http = require('http');var parse = require('url').parse;var join = require('path').join;var fs = require('fs');var root = __dirname;var server = http.createServer(function(req,res){    var url = parse(req.url);    //构造绝对路径    var path = join(root,url.pathname);    //检查文件是否存在    fs.stat(path,function(err,stat){        if(err){            //文件不存在            if('ENOENT' == err.code){                res.statusCode = 404;                res.end('Not Found');            }             //其他错误            else {                res.statusCode = 500;                res.end('Internal Server Error');            }        } else {            //用stat对象的属性设置Content-Length            res.setHeader('Content-length',stat.size);            var stream = fs.createReadStream(path);            stream.pipe(res);            stream.on('error',function(err){                res.statusCode = 500;                res.end('Internal Server Error');            });        }    });});server.listen(3000);

4.4 从表单中接受用户输入

4.4.1 处理提交的表单域
表单提交请求带的Content-Type值通常有两种:
1)application/x-www-form-urlencoded:这是HTML表单的默认值
2)multipart/form-data:在表单中含有文件或非ASCII或二进制数据时使用。

//支持GET和POST的HTTP服务器var http = require('http');var items = [];var server = http.createServer(function(req,res){    if('/' == req.url){        switch(req.method){            case 'GET':                show(res);                break;            case 'POST':                add(req,res);                break;            default:                badRequest(res);        }    } else {        notFound(res);    }});server.listen(3000);//代办事项列表页面的表单和事项列表function show(res){     var html = '<html><head><title>Todo List</title></head><body>'                + '<h1>Todo List</h1>'                + '<ul>'                + items.map(function(item){                    return '<li>' + item + '</li>'                }).join('')                + '</ul>'                + '<form method="post" action="/">'                + '<p><input type="text" name="item"/></p>'                + '<p><input type="submit" value="Add Item"/></p>'                + '</form></body></html>';    res.setHeader('Content-Type','text/html');    res.setHeader('Content-Length',Buffer.byteLength(html));    res.end(html);}//notFound()函数接收响应对象,将状态码设为404,响应整体设为Not Foundfunction notFound(res){    res.statusCode = 404;    res.setHeader('Content-Type','text/plain');    res.end('Not Found');}//返回400Bad Request响应的函数实现起来跟notFound()几乎一样,向客户端指明该请求无效function badRequest(res) {    res.statusCode = 400;    res.setHeader('Content-Type','text/plain');    res.end('Bad Request');}//var qs = require('querystring');function add(req,res){    var body = '';    req.setEncoding('utf8');    req.on('data',function(chunk){body += chunk});    req.on('end',function(){        var obj = qs.parse(body);        items.push(obj.item);        show(res);    });}

这里写图片描述

QUERYSTRING模块
在add()函数中解析请求主体时,用到了Node的querystring模块。
这里写图片描述

4.4.2 用formidable处理上传的文件

//准备好接收上传文件的HTTP服务器var http = require('http');var formidable = require('formidable');var server = http.createServer(function(req,res){    switch(req.method){        case 'GET':            show(req,res);            break;        case 'POST':            upload(req,res);            break;    }});server.listen(3000);//提供带有文件上传控件的HTML表单function show(req,res){    var html = ''        +'<form method="post" action="/" enctype="multipart/form-data">'        +'<p><input type="text" name="name"/></p>'        +'<p><input type="file" name="file"/></p>'        + '<p><input type="submit" value="Upload"/></p>'        + '</form>';    res.setHeader('Content-Type','text/html');    res.setHeader('Content-Length',Buffer.byteLength(html));    res.end(html);}function upload(req,res){    //上传逻辑    if(!isFormData(req)){        res.statusCode = 400;        res.end('Bad Request:expecting multipart/form-data');        return;    }    var form = new formidable.IncomingForm();    form.parse(req,function(err,fields,files){        console.log(fields);        console.log(files);        res.end('upload complete!');            });}function isFormData(req){    var type = req.headers['content-type'] || '';    return 0 == type.indexOf('multipart/form-data');}

4.4.3 计算上传进度

form.on('progress',function(bytesReceived,bytesExpected){        var percent = Math.floor(bytesReceived/bytesExpected * 100);        console.log(percent);    });

4.5 用HTTPS加强程序的安全性

原创粉丝点击