Node.js API详解之 http(上)

http模块提供了创建服务端与客户端的接口,
通过 const http = require(‘http’); 的方式引用http模块
本章介绍服务端部分,也就是请求接收端的api.

目录:

http 模块

http.Server 类

http.ServerResponse 类

http.IncomingMessage 类

http.createServer([requestListener])

说明:

新建一个 http.Server 实例
requestListener:一个回调函数,该函数会自动绑定到request事件上,每收到一个请求时会执行requestListener

demo:

const http = require('http');

const httpServer = http.createServer((req, res) => {
	console.log('request');
});

request 事件

说明:

每次接收到一个请求时触发。

demo:

const http = require('http');

const httpServer = http.createServer();

httpServer.on('request', (req, res) => {
	console.log('request Event');
});

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
});

//输出
// start httpServer
// request Event

server.listen()

说明:

启动一个HTTP服务监听connections,它与net模块下的server.listen()使用方式相同。
启动的服务可能是一个 TCP 或者 一个 IPC server,取决于监听的内容。
我们主要介绍TCP servers的创建方式:
server.listen([port][, host][, backlog][, callback])
port:要监听的端口
host:域名
backlog:待连接队列的最大长度
callback:此方法将会被添加为’listening’ 事件的监听器。

demo:

const http = require('http');

const httpServer = http.createServer((req, res) => {
	console.log('request');
});

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
});

server.listening

说明:

返回一个布尔值,标识服务器是否正在监听连接。

demo:

const http = require('http');

const httpServer = http.createServer((req, res) => {
	console.log('request');
});

console.log(httpServer.listening);

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
	console.log(httpServer.listening);
});

//输出:
// false
// start httpServer
// true

server.close([callback])

说明:

停止服务端接收新的连接。

demo:

const http = require('http');

const httpServer = http.createServer((req, res) => {
	console.log('request');
});

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
	//关闭http服务
	httpServer.close();
});

close 事件

说明:

当服务器关闭时触发。

demo:

const http = require('http');


const httpServer = http.createServer();

httpServer.on('close', () => {
	console.log('httpServer has been closed');
});

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
	httpServer.close();
});

//输出
// start httpServer
// httpServer has been closed

server.maxHeadersCount

说明:

限制请求头的最大数量,默认为 2000。 如果设为 0,则没有限制。

demo:

const http = require('http');

const httpServer = http.createServer((req, res) => {
	console.log('request');
});

httpServer.maxHeadersCount = 5;

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
});

server.setTimeout([msecs][, callback])

说明:

设置 socket 的超时时间。 如果发生超时,则触发服务器对象的 ‘timeout’ 事件,并传入 socket 作为一个参数。

server.timeout

说明:

socket 被认定为超时的空闲毫秒数。

server.keepAliveTimeout

说明:

服务器完成最后的响应之后需要等待额外的传入数据的活跃毫秒数, socket 才能被销毁.

checkContinue 事件

说明:

每当接收到一个带有 HTTP Expect: 100-continue 请求头的请求时触发。
如果该事件未被监听,则服务器会自动响应 100 Continue。

demo:

httpServer.on('checkContinue', (req, res) => {
	// do something
});

checkExpectation 事件

说明:

每当接收到一个带有 HTTP Expect 请求头(值不为 100-continue)的请求时触发。
如果该事件未被监听,则服务器会自动响应 417 Expectation Failed。

demo:

httpServer.on('checkExpectation', (req, res) => {
	// do something
});

clientError 事件

说明:

如果客户端触发了一个 ‘error’ 事件,则它会被传递到这里。
该事件的监听器负责关闭或销毁底层的 socket。

demo:

server.on('clientError', (err, socket) => {
  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});

connect 事件

说明:

每当客户端发送 HTTP CONNECT 请求时触发。
如果该事件未被监听,则发送 CONNECT 请求的客户端会关闭连接。

demo:

httpServer.on('connect', (req, socket, head) => {
	// do something
});

connection 事件

说明:

当一个新的 TCP 流被建立时触发。

demo:

httpServer.on('connection', (socket) => {
	// do something
});

upgrade 事件

说明:

每当客户端发送 HTTP upgrade 请求时触发。
如果该事件未被监听,则发送 upgrade 请求的客户端会关闭连接。

demo:

httpServer.on('upgrade', (req, socket, head) => {
	// do something
});

http.ServerResponse 类

说明:

该类提供了对响应对象的处理。

response.setHeader(name, value)

说明:

为一个隐式的响应头设置值。 如果该响应头已存在,则值会被覆盖。
如果要发送多个名称相同的响应头,则使用字符串数组。
例子:
response.setHeader(‘Content-Type’, ‘text/html’);

response.setHeader(‘Set-Cookie’, [‘type=ninja’, ‘language=javascript’]);

demo:

const http = require('http');

const httpServer = http.createServer();

httpServer.on('request', (req, res) => {
	res.setHeader('Content-Type', 'text/html');
  	res.setHeader('X-Foo', 'bar');
	res.end('ok');
});

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
});

效果:

response.addTrailers(headers)

说明:

该方法会添加 HTTP 尾部响应头(一种在消息尾部的响应头)到response。
发送尾部响应头之前,需先发送 Trailer 响应头,并在值里带上尾部响应头字段的列表。

demo:

res.setHeader('Content-Type', 'text/html');

res.setHeader('Trailer', 'Content-MD5');

res.write('Welcome to isjs');

res.addTrailers({'Content-MD5':'7895bf4b8828b55ceaf47747b4bca6'});

res.end();


response.end([data][, encoding][, callback])

说明:

该方法会通知服务器,所有响应头和响应主体都已被发送,即服务器将其视为已完成。
每次响应都必须调用 response.end() 方法。
data:如果指定了 data,则相当于调用 response.write(data, encoding) 之后再调用 response.end(callback)。
callback:如果指定了 callback,则当响应流结束时被调用。

demo:

const http = require('http');

const httpServer = http.createServer();

httpServer.on('request', (req, res) => {
	res.setHeader('Content-Type', 'text/html');
  	res.setHeader('X-Foo', 'bar');
	res.end('Welcome to isjs', 'utf8', () => {
		console.log('request success');
	});
});

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
});

close 事件

说明:

在 response.end() 被调用或能够刷新之前被终止时触发。

response.write(chunk[, encoding][, callback])

说明:

该方法会发送一块响应主体。 它可被多次调用,以便提供连续的响应主体片段。
chunk:chunk 可以是一个字符串或一个 buffer。 如果 chunk 是一个字符串,则第二个参数指定如何将它编码成一个字节流。
encoding: 默认为 ‘utf8’。
callback:当数据块被刷新时,callback 会被调用。
如果全部数据被成功刷新到内核缓冲区,则返回 true。 如果全部或部分数据还在内存中排队,则返回 false。
当缓冲区再次空闲时,则触发 ‘drain’ 事件。

demo:

const http = require('http');

const httpServer = http.createServer();

httpServer.on('request', (req, res) => {
	res.setHeader('Content-Type', 'text/html');
  	res.setHeader('X-Foo', 'bar');
  	
  	res.write('Welcome to ', 'utf8', () =>{
  		console.log('change response');
  	});
	res.write('isjs', 'utf8'	);


	res.end(() => {
		console.log('request success');
	});
});

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
});

// start httpServer
// change response
// request success

response.writeContinue()

说明:

发送一个 HTTP/1.1 100 Continue 消息到客户端,表示请求主体可以开始发送。

response.writeHead(statusCode[, statusMessage][, headers])

说明:

发送一个响应头给请求。
statusCode是一个三位数的 HTTP 状态码,如 404。
headers 是响应头。
statusMessage 是可选的状态描述。
该方法在消息中只能被调用一次,
且必须在 response.end() 被调用之前调用。
response.setHeader() 设置的响应头会与 response.writeHead() 设置的响应头合并,且 response.writeHead() 的优先

demo:

const http = require('http');

const httpServer = http.createServer();

httpServer.on('request', (req, res) => {
	const body = 'Welcome to isjs';

	res.setHeader('Content-Type', 'text/html');
  	res.setHeader('X-Foo', 'bar');

	res.writeHead(200, {
  		'Content-Length': Buffer.byteLength(body),
  		'Content-Type': 'text/plain' });

  	res.write(body, 'utf8', () =>{
  		console.log('change response');
  	});

	res.end(() => {
		console.log('request success');
	});
});

httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
});

效果:

response.getHeader(name)

说明:

读取一个已入队列但尚未发送到客户端的响应头。
name:响应头字段名,名称不区分大小写。

demo:

res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');

res.write('Welcome to isjs', 'utf8', () =>{
	console.log('change response');
});

console.log(res.getHeader('content-type'));

res.end(() => {
	console.log('request success');
});

//输出: text/html

response.getHeaderNames()

说明:

返回一个当前响应中 http 头信息名称数组. 名称均为小写.

demo:

res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');

res.write('Welcome to isjs', 'utf8', () =>{
	console.log('change response');
});

console.log(res.getHeaderNames());

res.end(() => {
	console.log('request success');
});

//输出: [ 'content-type', 'x-foo' ]

response.getHeaders()

说明:

返回当前响应头文件的浅拷贝。 由于使用了浅拷贝,因此数组值可能会改变.
返回对象的键是响应头名称,值是各自的响应头值。 所有响应头名称都是小写的。

demo:

res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');

res.write('Welcome to isjs', 'utf8', () =>{
	console.log('change response');
});

console.log(res.getHeaders());

res.end(() => {
	console.log('request success');
});
//输出: { 'content-type': 'text/html', 'x-foo': 'bar' }

response.hasHeader(name)

说明:

判断当前的响应头中是否有指定的字段。
name:字段名,不区分大小写

demo:

res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');

res.write('Welcome to isjs', 'utf8', () =>{
	console.log('change response');
});

console.log(res.hasHeader('content-type'));

res.end(() => {
	console.log('request success');
});
//输出: true

response.headersSent

说明:

判断当前响应头是否被发送

demo:

res.setHeader('Content-Type', 'text/html');

res.setHeader('X-Foo', 'bar');

console.log('Before write:', res.headersSent);

res.write('Welcome to isjs', 'utf8', () =>{
	console.log('change response');
});

console.log('After write:', res.headersSent);

res.end();

//输出:
//Before write: false
//After write: true

response.statusCode

说明:

用来设置响应头中的状态码。

demo:

res.setHeader('Content-Type', 'text/html');

res.setHeader('X-Foo', 'bar');

res.removeHeader('content-type');

res.statusCode = 301;

res.write('Welcome to isjs', 'utf8', () =>{
	console.log('change response');
});

res.end();

效果:

response.statusMessage

说明:

设置响应头中的状态信息

demo:

res.setHeader('Content-Type', 'text/html');

res.setHeader('X-Foo', 'bar');

res.removeHeader('content-type');

res.statusCode = 301;

res.statusMessage = 'Token has failed';

res.write('Welcome to isjs', 'utf8', () =>{
	console.log('change response');
});

res.end();

效果:

finish 事件

说明:

当响应已被发送时触发。 更具体地说,当响应头和响应主体的最后一部分已被交给操作系统通过网络进行传输时,触发该事件。
这并不意味着客户端已接收到任何东西。

demo:

res.setHeader('Content-Type', 'text/html');

res.setHeader('X-Foo', 'bar');

res.on('finish', () => {
	console.log('finish Event');
});

res.write('Welcome to isjs');

res.end();

response.finished

说明:

返回一个布尔值,表示响应是否已完成。 默认为 false。
执行 response.end() 之后,该值会变为 true。

demo:

res.setHeader('Content-Type', 'text/html');

res.setHeader('X-Foo', 'bar');

res.removeHeader('content-type');

res.write('Welcome to isjs', 'utf8', () =>{
	console.log('change response');
});

console.log(res.finished)
res.end();
console.log(res.finished)
//输出:
//false
//true

response.removeHeader(name)

说明:

从待发送的响应头中移除指定的字段。

demo:

res.setHeader('Content-Type', 'text/html');

res.setHeader('X-Foo', 'bar');

res.removeHeader('content-type');

console.log(res.getHeaders())

res.write('Welcome to isjs', 'utf8', () =>{
	console.log('change response');
});

res.end();

//输出:
// { 'x-foo': 'bar' }

response.sendDate

说明:

当为 true 时,如果响应头里没有日期响应头,则日期响应头会被自动生成并发送。默认为 true。

response.socket,response.connection

说明:

该属性返回一个 实例,在response.end()之后,该属性为null。
也可以通过response.connection来访问socket

demo:

const ip = res.socket.remoteAddress;
const port = res.socket.remotePort;
console.log(`你的IP地址是 ${ip},你的源端口是 ${port}。`);

res.setHeader('Content-Type', 'text/html');

res.write('Welcome to isjs');

res.end();

response.setTimeout(msecs[, callback])

说明:

设置 socket 的超时时间为 msecs。 如果提供了回调函数,则它会作为监听器被添加到响应对象的 ‘timeout’ 事件。
如果没有 ‘timeout’ 监听器被添加到请求、响应或服务器,则 socket 会在超时后被销毁。

http.IncomingMessage 类

说明:

IncomingMessage对象由 http.Server 或 http.ClientRequest 创建,作为第一个参数传递给request和response事件。
它可以用来访问响应状态、消息头、以及参数数据。

message.headers

说明:

该属性返回请求头信息的名称与值的对象,名称为小写。

demo:

const http = require('http');
 
const httpServer = http.createServer();
 
httpServer.on('request', (req, res) => {

	console.log(req.headers);

	res.end('success');
});
 
httpServer.listen(8061, '127.0.0.1', () => {
	console.log('start httpServer');
});
// { host: '127.0.0.1:8061',
//   connection: 'keep-alive',
//   'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
//   accept: 'image/webp,image/apng,image/*,*/*;q=0.8',
//   referer: 'http://127.0.0.1:8061/',
//   'accept-encoding': 'gzip, deflate, br',
//   'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8' }

message.httpVersion

说明:

该属性返回客户端发送的HTTP版本。

demo:

httpServer.on('request', (req, res) => {

	console.log(req.httpVersion);

	res.end('success');
});
// 1.1

message.method

说明:

返回一个字符串,表示请求的方法。 该属性只读。 例如:’GET’、’DELETE’。

demo:

httpServer.on('request', (req, res) => {

	console.log(req.method);

	res.end('success');
});
//GET

message.rawHeaders

说明:

该属性返回接收到的原始的请求头或响应头列表。
注意,键和值在同一个列表中。 偶数位的是键,奇数位的是对应的值。
头信息的名称不会被转换为小写,重复的也不会被合并

demo:

httpServer.on('request', (req, res) => {

	console.log(req.rawHeaders);

	res.end('success');
});
// [ 'Host',
//   '127.0.0.1:8061',
//   'Connection',
//   'keep-alive',
//   'Pragma',
//   'no-cache',
//   'Cache-Control',
//   'no-cache',
//   'User-Agent',
//   'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
//   'Accept',
//   'image/webp,image/apng,image/*,*/*;q=0.8',
//   'Referer',
//   'http://127.0.0.1:8061/',
//   'Accept-Encoding',
//   'gzip, deflate, br',
//   'Accept-Language',
//   'zh-CN,zh;q=0.9,en;q=0.8' ]

message.rawTrailers

说明:

接收到的原始的 Trailer 请求头或响应头的的键和值。 只在 ‘end’ 事件时被赋值。

demo:

httpServer.on('request', (req, res) => {

	console.log(req.rawTrailers);

	res.end('success');
});
// []

message.socket

说明:

返回与连接关联的 net.Socket 对象。

demo:

httpServer.on('request', (req, res) => {

	console.log(req.socket);

	res.end('success');
});
// Socket {...}

message.statusCode

说明:

仅在 http.ClientRequest 返回的响应中有效。
返回一个三位数的 HTTP 响应状态码。 如 404。

demo:

httpServer.on('request', (req, res) => {

	console.log(req.statusCode);

	res.end('success');
});
//因为是http.Server 返回的message对象,所以该属性值为:null

message.statusMessage

说明:

仅在 http.ClientRequest 返回的响应中有效。
返回 HTTP 响应状态消息(原因描述)。 如 OK 或 Internal Server Error。

demo:

httpServer.on('request', (req, res) => {

	console.log(req.statusMessage);

	res.end('success');
});
//因为是http.Server 返回的message对象,所以该属性值为:null

message.trailers

说明:

返回 Trailer 请求头或响应头对象。 只在 ‘end’ 事件时被赋值。

demo:

httpServer.on('request', (req, res) => {

	console.log(req.trailers);

	res.end('success');
});
//{}

message.url

说明:

仅在 http.Server 返回的请求中有效。
返回请求的 URL 字符串。

demo:

httpServer.on('request', (req, res) => {

	console.log(req.url);

	res.end('success');
});
// /index.html

close 事件

说明:

当底层连接被关闭时触发。 同 ‘end’ 事件一样,该事件每个响应只触发一次。

aborted 事件

说明:

当请求已被终止且网络 socket 已关闭时触发。

message.destroy([error])

说明:

调用接收到 IncomingMessage 的 socket 上的 destroy() 方法。
error:如果提供了 error,则触发 ‘error’ 事件,且把 error 作为参数传入事件的监听器。

message.setTimeout(msecs, callback)

说明:

调用 message.connection.setTimeout(msecs, callback)。
返回 message。

http.METHODS

说明:

该属性返回http支持的解析的方式。

demo:

const http = require('http');
 
console.log(http.METHODS);
// [ 'ACL',
//   'BIND',
//   'CHECKOUT',
//   'CONNECT',
//   'COPY',
//   'DELETE',
//   'GET',
//   'HEAD',
//   'LINK',
//   'LOCK',
//   'M-SEARCH',
//   'MERGE',
//   'MKACTIVITY',
//   'MKCALENDAR',
//   'MKCOL',
//   'MOVE',
//   'NOTIFY',
//   'OPTIONS',
//   'PATCH',
//   'POST',
//   'PROPFIND',
//   'PROPPATCH',
//   'PURGE',
//   'PUT',
//   'REBIND',
//   'REPORT',
//   'SEARCH',
//   'SUBSCRIBE',
//   'TRACE',
//   'UNBIND',
//   'UNLINK',
//   'UNLOCK',
//   'UNSUBSCRIBE' ]

http.STATUS_CODES

说明:

该属性返回标准HTTP响应状态码的集合,以及各自的描述。

demo:

const http = require('http');
 
console.log(http.STATUS_CODES);
// { '100': 'Continue',
//   '101': 'Switching Protocols',
//   '102': 'Processing',
//   '200': 'OK',
//   '201': 'Created',
//   '202': 'Accepted',
//   '203': 'Non-Authoritative Information',
//   '204': 'No Content',
//   '205': 'Reset Content',
//   '206': 'Partial Content',
//   '207': 'Multi-Status',
//   '208': 'Already Reported',
//   '226': 'IM Used',
//   '300': 'Multiple Choices',
//   '301': 'Moved Permanently',
//   '302': 'Found',
//   '303': 'See Other',
//   '304': 'Not Modified',
//   '305': 'Use Proxy',
//   '307': 'Temporary Redirect',
//   '308': 'Permanent Redirect',
//   '400': 'Bad Request',
//   '401': 'Unauthorized',
//   '402': 'Payment Required',
//   '403': 'Forbidden',
//   '404': 'Not Found',
//   '405': 'Method Not Allowed',
//   '406': 'Not Acceptable',
//   '407': 'Proxy Authentication Required',
//   '408': 'Request Timeout',
//   '409': 'Conflict',
//   '410': 'Gone',
//   '411': 'Length Required',
//   '412': 'Precondition Failed',
//   '413': 'Payload Too Large',
//   '414': 'URI Too Long',
//   '415': 'Unsupported Media Type',
//   '416': 'Range Not Satisfiable',
//   '417': 'Expectation Failed',
//   '418': 'I\'m a teapot',
//   '421': 'Misdirected Request',
//   '422': 'Unprocessable Entity',
//   '423': 'Locked',
//   '424': 'Failed Dependency',
//   '425': 'Unordered Collection',
//   '426': 'Upgrade Required',
//   '428': 'Precondition Required',
//   '429': 'Too Many Requests',
//   '431': 'Request Header Fields Too Large',
//   '451': 'Unavailable For Legal Reasons',
//   '500': 'Internal Server Error',
//   '501': 'Not Implemented',
//   '502': 'Bad Gateway',
//   '503': 'Service Unavailable',
//   '504': 'Gateway Timeout',
//   '505': 'HTTP Version Not Supported',
//   '506': 'Variant Also Negotiates',
//   '507': 'Insufficient Storage',
//   '508': 'Loop Detected',
//   '509': 'Bandwidth Limit Exceeded',
//   '510': 'Not Extended',
//   '511': 'Network Authentication Required' }