一個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>
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'); }
用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);