• node.js基础:HTTP服务器


      一个HTTP服务器响应   

    var http = require('http');
    http.createServer(function(request,response){
    	 response.end('hello world!');
    }).listen(3000);
    

       读取请求头及设定响应头

    // res.setHeader(field, value)
    // res.getHeader(field)
    // res .removeHeader(field)
    // 默认状态码200(表明成功)
    res.setHeader('Content-Type','text/html');
    res.writeHead(200,{'Content-Type':'text/html'});
    

       设定HTTP响应的状态码

    //当所请求的资源不存在时返回一个404 Not Found状态码
    //设定res.statusCode属性。在程序响应期间可以随时给这个属性赋值,需要是在第一次调用res.write()或res.end()之前设置.
    res.statusCode = 302;
    

       用POST请求创建资源

    var http = require('http');
    http.createServer(function(request,response){
    	request.setEncoding('utf-8');
    	request.on('data',function(chunk){
    		console.log( chunk );
    	});
    	request.on('end',function(){
    		console.log('done');
    		response.end('hello world!');
    	});
    }).listen(3000);
    //默认情况下,data事件会提供Buffer对象,这是node.js版的字节数组
    //不需要二进制数据,调用req.setEncoding(encoding)方法可以将流编码为ascii或utf8,这样data事件会给出字符串
    
    var http = require('http');
    var url = require('url');
    var items = [];
    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
    ');
    			});
    		break;
    	}
    }).listen(3000);
    

       用GET请求获取资源

    var http = require('http');
    var url = require('url');
    var items = [];
    http.createServer(function(req, res){
    	switch (req.method){
    		case 'POST':
    			//..
    		break;
    		case 'GET':
    			items.forEach(function(item,index){
    				res.write(index +'/'+ item +'
    ');
    				res.end();
    			});
    		break;
    	}
    }).listen(3000);
    
    //为了提高响应速度,可以在响应中带着Content-Length域一起发送
    var body = items.map(function(item,index){
    	return i +'/'+ item;
    }).join('
    ');
    res.setHeader('Content-Length',Buffer.byteLength());
    res.setHeader('Content-Type','text/plain');
    res.end(body);
    

      用DELETE请求移除资源

    var http = require('http');
    var url = require('url');
    var items = [];
    http.createServer(function(req, res){
    	switch (req.method){
    		case 'POST':
    			//..
    		break;
    		case 'GET':
    			//..
    		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 nod found');
    			}else{
    				items.splice(i,1);
    				res.end('delete done');
    			}
    		break;
    	}
    }).listen(3000);
    

       创建一个静态文件服务器

       每个静态文件服务器都有个根目录,也就是提供文件服务的基础目录。

       定义一个root变量,它将作为这个静态文件服务器的根目录。

    var root = __dirname;
    //__dirname 的值是该文件所在目录的路径。
    //如果有分散在不同目录中的文件,__dirname可以有不同的值。
    
    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); //绝对路径
    	var stream = fs.createReadStream(path); //高层流式硬盘访问文件内容
    	stream.on('data', function(chunk){
    		res.write(chunk);
    	});
    	stream.on('end', function(){
    		res.end();
    	});
    });
    server.listen(3000);
    

       优化数据传输

       node.js中的管道: 是来自源头(即ReadableStream)的数据,管道可以让数据流动到某个目的地(即WritableStream),可以用pipe方法把管道连起来。

    var readStream = fs.createReadStream('./original.txt')
    var writeStream = fs.createWriteStream('./copy.txt')
    readStream.pipe(writeStream);
    
    //...
    var server = http.createServer(function(req, res){
    	var url = parse(req.url);
    	var path = join(root, url.pathname); //绝对路径
    	var stream = fs.createReadStream(path); //高层流式硬盘访问文件内容
    	stream.pipe(res);
    });
    //...
    

       处理服务器错误

       如果访问不存在的文件,或者不允许访问的文件,或者碰到任何与文件I/O有关的问题,当前的服务器会抛出错误。

       在node.js中,所有继承了EventEmitter的类都可能会发出error事件。

       默认情况下,如果没有设置监听器,error事件会被抛出。也就是说如果你不监听这些错误,那它们就会搞垮服务器。

       注册一个error事件处理器,可以捕获任何可以预见或无法预见的错误,给客户端更优雅的响应。

     
    //..
    stream.pipe(res);
    stream.on('error',function(error){
    	res.statusCode = 500;
    	res.end('Invalid Server Error');
    });
    //..
    

       一个简单的支持GET、POST的HTTP服务器

       模板文件 template.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>A HTTP Server</title>
    </head>
    <body>
        <ul>%</ul>
        <form  method="POST" action="/">
            <p><input type="text" name="item" value="" /></p>
            <p><input type="submit" value="Add item" /></p>
        </form>
    </body>
    </html>

       node.js文件 index.js

    var http = require('http');
    var fs = require('fs');
    var qs = require('querystring');
    var items = [];
    var server = http.createServer(function(req, res){
    	if(req.url == '/'){
    		switch (req.method.toUpperCase()){
    			case 'GET':
    				show(res);
    			break;
    			case 'POST':
    				add(req, res);
    			break;
    			default:
    				badRequest(res);
    		}
    	}else{
    		notFound(res);
    	}
    });
    server.listen(3000);
    
    function show(res){
    	fs.readFile('./template.html',function(err, data){
    		var html = data.toString().replace('%', items.map(function(item,index){
    			return '<li>'+ item +'</li>'; 
    		}).join(''));
    	    res.setHeader('Content-Type','text/html');
    	    res.setHeader('Content-Length',Buffer.byteLength(html));
    	    res.end(html);
    	});
    }
    
    function add(req, res){
    	var body = '';
    	req.setEncoding('utf8');
    	req.on('data',function(chunk){
    		body += chunk;
    	});
    	req.on('end',function(){
    		items.push( qs.parse(body).item );
    		show(res);
    	});
    }
    
    function notFound(res){
    	res.statusCode = 404;
    	res.setHeader('Content-Type','text/plain');
    	res.end('Not Found');
    }
    
    function badRequest(res){
    	res.statusCode = 400;
    	res.setHeader('Content-Type','text/plain');
    	res.end('Bad Request');
    }
    

       一个文件上传HTTP服务器

      上传文件需要把表单的enctype属性设为multipart/form-data。

      formidable模块可以高效流畅的方式解析文件上传请求。

      html模板文件: template.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>upload file</title>
    </head>
    <body>
        <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 file" /></p>
        </form>
    </body>
    </html>
    template

      node.js文件:index.js

    var http = require('http');
    var fs = require('fs');
    var qs = require('querystring');
    var formidable = require('formidable')
    var items = [];
    var server = http.createServer(function(req, res){
        if(req.url == '/'){
            switch (req.method.toUpperCase()){
                case 'GET':
                    show(res);
                break;
                case 'POST':
                    upload(req, res);
                break;
                default:
                    badRequest(res);
            }
        }else{
            notFound(res);
        }
    });
    server.listen(3000);
    
    function show(res){
        fs.readFile('./template.html',function(err, data){
            var html = data.toString();
            res.setHeader('Content-Type','text/html');
            res.setHeader('Content-Length',Buffer.byteLength(html));
            res.end(html);
        });
    }
    
    function upload(req,res){
        if(!isFormData(req)){
            return badRequest(res);
        }
        var form  = formidable.IncomingForm();
        form.uploadDir = __dirname; //路径设置
        // form.on('field',function(field,value){
        //     console.log(field);
        //     console.log(value);
        // });
        // form.on('file',function(name,file){
        //     console.log(name);
        //     console.log(file);
        // });
        // form.on('end',function(){
        //      res.end('upload complate');
        // });
        // form.parse(req);
    
        //上传进度事件
        form.on('progress',function(bytesReceived,bytesExpected){
            var progress = Math.floor( bytesReceived/bytesExpected*100 );
            console.log(progress);
        });
    
        form.parse(req,function(err,fields,files){
            console.log(fields);
            console.log(files);
            //console.log( files.file.path );
            res.end('upload complate');
        });
    }
    
    function isFormData(req){
        var type = req.headers['content-type'] || '';
        return type.indexOf('multipart/form-data') == 0;
    }
    
    function notFound(res){
        res.statusCode = 404;
        res.setHeader('Content-Type','text/plain');
        res.end('Not Found');
    }
    
    function badRequest(res){
        res.statusCode = 400;
        res.setHeader('Content-Type','text/plain');
        res.end('Bad Request');
    }
    node.js code

       用https加强程序的安全性

       如果想在node.js程序里使用https,第一件事就是取得一个私钥和一份证书。

       生成私钥需要OpenSSL,在装node.js时就已经安装了。

       生成名为key.pem的私钥文件, 在项目根目录输入命令:openssl genrsa 1024 > key.pem

       生成名为key-cert.pem的证书,在项目根目录输入命令:openssl req -x509 -new -key key.pem > key-cert.pem

    var https = require('https');
    var fs = require('fs');
    
    var options = {
    	key: fs.readFileSync('./key.pem'),
    	cert: fs.readFileSync('./key-cert.pem')
    };
    
    https.createServer(options,function(req,res){
    	res.writeHead(200);
    	res.end('hello node.js!');
    }).listen(3000);
    
  • 相关阅读:
    处理流之转换流
    处理流之缓冲流 buffered
    java学习笔记 字符流Reader与Writer
    java学习笔记 OutputStream与InputStream
    java学习笔记 Map接口
    java 学习笔记 Iterator 迭代器
    java学习笔记 genenic 范形
    应急响应介绍
    安全之红蓝对抗简介
    密码学基础下篇
  • 原文地址:https://www.cnblogs.com/eyeear/p/4741284.html
Copyright © 2020-2023  润新知