Node内置了http模块提供HTTP服务器和客户端接口
var http = require("http");
创建HTTP服务器只需要简单的调用http.createServer()函数,参数是回调函数,接收两个参数: request, response对象。
var server = http.createServer(function(req, res){});
在触发回调函数之前Node就已经对HTTP请求头进行了解析,但是并没有对请求体进行解析。另外需要有开发者自行调用response.end()方法来结束响应。
HTTP服务器需要绑定一个端口号,用来监听接入的请求。使用http.server类的listen方法
一个最简单的HTTP服务器代码:
var http = require("http"); var server = http.createServer(function(req, res){ res.write("hello world"); res.end(); } server.listen(8080);
接下来让我们看看如何获取请求头信息和如何设置响应头信息
1. 获取请求头信息
req.headers
req.rawHeaders
通过这两个属性获取请求头信息。这两者的区别在于,headers获取的是键值对格式的对象,并且重复请求头信息会被舍弃。而rawHeaders获取的是列表,奇数为请求头名称,偶数为请求头信息,同时重复的请求头信息也会放在列表中。
2. 设置响应头信息
response对象提供了setHeader(field, value), getHeader(field, value), removeHeader(field) 方法
设置响应头一定要在发送消息体之前,常用的响应头包括
Content-Type: "text/plain", "text/html"
Content-Length 设置响应消息体的字节长度 可以使用Buffer.byteLength方法获取字符串数据的实际字节长度
3. 设定响应状态码
response.statusCode
NodeJS中的http模块提供了http.STATUS_CODES属性用来描述标准HTTP协议规定的状态码及描述文字说明
设置response.statusCode = 302 表示 重定向
构建RESTful WEB服务
创建标准的REST服务器需要实现四个HTTP操作: POST GET DELETE PUT 分别对应人们常说的CURD操作
另外人们也常用curl命令行方式来进行web操作
当有请求发送数据时,HTTP解析器会将数据做成data事件的形式,将解析好的数据放入chunk中。也就是监听request请求的data事件和end事件
var http = require("http"); var server = http.createServer(function(req, res){ req.setEncoding("utf-8"); req.on("data", function(chunk){ console.log("parsed", chunk); }); req.on("end", function(){ console.log("done parsing"); res.end(); }); });
使用req.method属性来判断请求方式
解析URL路径信息还需要用到核心模块url
通过理解req.method,url,和request请求对象的数据解析原理对于以后使用封装好的高级框架是有好处的。
比如在Express中,就提供了.all() .get() .post() .put() .delete()等方法
构建静态文件服务器
Stream.pipe()方法可以理解为将源头的数据(ReadableStream)通过管道pipe流动到目的地(WritableStream)
所有ReadableStream都能接入到任何的WriteableStream中,比如request就是一个ReadableStream, response就是一个WritableStream
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 pathname = parse(req.url).pathname; var path = join(root, pathname); fs.stat(path, function(err, stat){ if(err){ if(err.code === "ENOENT"){ res.statusCode = 404; res.end("Not Found"); }else{ res.statusCode = 500; res.end("Internal Server Error"); } }else{ //没有错误,准备读取文件内容并返回 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(8080);