作为构建web服务器的核心模块,HTTP模块封装了很多底层的操作,让我们很方便的构建一个http服务器;
下面看一个例子:
var http = require('http');
http
.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('Hello world');
res.end();
})
.listen(2017);
http构建一个服务器,添加回调函数,参数包含request和response,并监听2017端口;
http可以作为服务端和客户端来使用;
作为服务端
http.createServer([requestListener])、http.Server类
返回一个新建的http.Server
实例,其requestListener函数会被自动添加到request事件;
http.Server
实例的request事件表示,每接收到一个请求时触发;回调函数有两个参数,分别是request和response,分别是http.IncomingMessage
和http.ServerResponse
的实例;
http.IncomingMessage
对象由 http.Server
或 http.ClientRequest
创建,并作为第一个参数分别递给 'request'
和 'response'
事件。 它可以用来访问响应状态、消息头、以及数据。
它实现了 可读流 接口,还有以下额外的事件、方法、以及属性。
基本的一些属性有
- message.headers请求头或响应头的对象
- message.method请求的方法
- message.url请求的url字符串
http.ServerResponse
该对象在 HTTP 服务器内部被创建。 它作为第二个参数被传入 'request'
事件。
这个类实现了(而不是继承自)可写流 接口。 它是一个有以下事件的 EventEmitter
:...
基本方法有:
- response.writeHead()
- response.write()
- response.end([data][, encoding][, callback])
response.write(statusCode[, statusMessage][, headers])
发送一个响应头给请求。 状态码是一个三位数的 HTTP 状态码,如 404。 最后一个参数 headers 是响应头。 第二个参数 statusMessage 是可选的状态描述。
例子:
const body = 'hello world';
response.writeHead(200, {
'Content-Length': Buffer.byteLength(body),
'Content-Type': 'text/plain' });
该方法在消息中只能被调用一次,且必须在 response.end()
被调用之前调用。
如果在调用该方法之前调用 response.write()
或 response.end()
,则隐式的响应头会被处理并调用该函数。
response.setHeader()
设置的响应头会与 response.writeHead()
设置的响应头合并,且 response.writeHead()
的优先。
response.write(chunk[, encoding][, callback])
如果该方法被调用且 response.writeHead()
没有被调用,则它会切换到隐式响应头模式并刷新隐式响应头。
该方法会发送一块响应主体。 它可被多次调用,以便提供连续的响应主体片段。
Note that in the httpmodule, the response body is omitted when the request is a HEAD request. Similarly, the 204and 304responses must not include a message body.
chunk可以是一个字符串或一个 buffer。 如果 chunk是一个字符串,则第二个参数指定如何将它编码成一个字节流。 encoding默认为 'utf8'。当数据块被刷新时,callback会被调用。
注意:这是原始的 HTTP 主体,且与可能被使用的高级主体编码无关。
response.write()
首次被调用时,会发送缓冲的响应头信息和响应主体的第一块数据到客户端。 response.write()
第二次被调用时,Node.js 会以流的形式处理数据,并将它们分别发送。 也就是说,响应会被缓冲到响应主体的第一个数据块。
如果全部数据被成功刷新到内核缓冲区,则返回 true。 如果全部或部分数据还在内存中排队,则返回 false。 当缓冲区再次空闲时,则触发 'drain'事件。
response.end([data][, encoding][, callback])
该方法会通知服务器,所有响应头和响应主体都已被发送,即服务器将其视为已完成。 每次响应都必须调用 response.end()方法。如果指定了 data,则相当于调用 response.write(data, encoding)
之后再调用 response.end(callback)。如果指定了 callback,则当响应流结束时被调用。
作为客户端
http.ClientRequest 类
该对象在 http.request()
内部被创建并返回。 它表示着一个正在处理的请求,其请求头已进入队列。
要获取响应,需为 'response'
事件添加一个监听器到请求对象上。 当响应头被接收到时,'response'
事件会从请求对象上被触发 。 'response'
事件被执行时带有一个参数,该参数是一个 http.IncomingMessage
实例。
在 'response'
事件期间,可以添加监听器到响应对象上,比如监听 'data'事件。
如果没有添加 response事件处理函数,则响应会被整个丢弃。 如果添加了 response事件处理函数,则必须消耗完响应对象的数据,可通过调用 response.read()、或添加一个 'data'事件处理函数、或调用 .resume() 方法。 数据被消耗完时会触发 'end'事件。 在数据被读取完之前会消耗内存,可能会造成 'process out of memory'错误。
下面来看一个小爬虫的实例:
var http = require('http');
var url = 'http://www.imooc.com';
http.get(url,function(res) {
var html = '';
res.on('data',function(data) {
html += data;
});
res.on('end',function () {
console.log(html);//输出慕课网的html代码
})
}).on('error',function() {
console.log('获取错误');
});
注:作为客户端的res和服务端的res参数不同,实际上,这里的res和服务端的req是同一个类型的实例,即:http.IncomingRequest;