node.js基礎:HTTP服務器

  一個HTTP服務器響應   html

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

   讀取請求頭及設定響應頭node

// 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\n');
			});
		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 +'\n');
				res.end();
			});
		break;
	}
}).listen(3000);

//爲了提升響應速度,能夠在響應中帶着Content-Length域一塊兒發送
var body = items.map(function(item,index){
	return i +'/'+ item;
}).join('\n');
res.setHeader('Content-Length',Buffer.byteLength());
res.setHeader('Content-Type','text/plain');
res.end(body);

  用DELETE請求移除資源ide

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);

   建立一個靜態文件服務器優化

   每一個靜態文件服務器都有個根目錄,也就是提供文件服務的基礎目錄。ui

   定義一個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);

   優化數據傳輸url

   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);
相關文章
相關標籤/搜索