http 模块是 node.js 处理 networking 网络的关键模块。在之前的章节我介绍了使用 http 模块建立 server 以及发起 GET/POST 请求的方法,可以参考:https://blog.niekun.net/archives/2137.html

http 模块集成于 node.js 核心无需单独安装,使用下面命令引入模块:

const http = require('http')

模块提供了很多 properties,methods 和 classes。

Properties 属性

http.METHODS

http.METHODS property 返回 http 所有的可用 method 列表:

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

http.STATUS_CODES

http.STATUS_CODES 返回所有的 http 状态码及描述的 list 列表:

> console.log(require('http').STATUS_CODES)
{
  '100': 'Continue',
  '101': 'Switching Protocols',
  '102': 'Processing',
  '103': 'Early Hints',
  '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': 'Too Early',
  '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'
}

http.globalAgent

http.globalAgent 指向 http.Agent class 的一个 instance 实例,也就是一个 Agent object。

这个 Agent object 用来管理 server 同 http 客户端链接的持续连接和链接复用,这也是 node.js 网络服务的关键点。

> console.log(require('http').globalAgent)
Agent {
  _events: [Object: null prototype] {
    free: [Function (anonymous)],
    newListener: [Function: maybeEnableKeylog]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  defaultPort: 80,
  protocol: 'http:',
  options: { path: null },
  requests: {},
  sockets: {},
  freeSockets: {},
  keepAliveMsecs: 1000,
  keepAlive: false,
  maxSockets: Infinity,
  maxFreeSockets: 256,
  scheduling: 'lifo',
  maxTotalSockets: Infinity,
  totalSocketCount: 0,
  [Symbol(kCapture)]: false
}

methods 功能

http.createServer()

http.createServer() 返回一个 http.Server class 实例。

const server = http.createServer((req, res) => {
  //handle every single request with this callback
})

http.request()

http.request() 对服务器发起一个 http 请求。返回一个 http.ClientRequest class 实例。

const options = {
    hostname: 'localhost',
    port: 3000,
    path: '/',
    method: 'GET'
}

const req = https.request(options, res => {
    console.log(`statusCode is:${res.statusCode}`);
    res.on('data', d => {
        process.stdout.write(d)
    })
})

req.on('error', err => console.log(err))
req.end()

http.get()

http.get() 同 http.request() 类似,但会自动将 http method 设置为 GET,且自动调用 req.end()。

const https = require('http')
const options = {
    hostname: 'localhost',
    port: 3000,
    path: '/'
}

const req = https.get(options, res => {
    console.log(`statusCode is:${res.statusCode}`);
    res.on('data', d => {
        process.stdout.write(d)
    })
})

req.on('error', err => console.log(err))

Classes 类

http 模块提供 5 个 calsses:

  • http.Agent
  • http.ClientRequest
  • http.Server
  • http.ServerResponse
  • http.IncomingMessage

http.Agent

node.js 会创建一个全局的 http.Agent instance 实例来管理 server 同 http 客户端链接的持续连接和链接复用,这个 object 可以确保一个客户端对服务端发起的一系列请求是按队列排序的,且使用单独的 socket 接口。同样 agent object 管理着一个 sockets 池,这是影响性能的关键因素。

http.ClientRequest

当 http.request() 或 http.get() 被调用时会创建一个 http.ClientRequest object。

当收到来自服务器的 response 时,response event 会被触发,http.request() 内定义的 callback 会作为 response 的响应被调用,同时将 http.IncomingMessage 的实例作为传入参数,其中包含了 response 数据。

response 数据有两种方式读取,第一种是通过 response.read() method,第二种是在 response 的 callback function 中通过监听 data event 来获取 stream 中的数据。

http.Server

当通过 http.createServer() 创建一个 server 时会返回 http.Server 实例。 http.Server 实例需要使用它的以下 method:

  • close() 停止 server 接收新的链接
  • listen() 启动 server 并开始监听请求

http.createServer() 的 callback 监听 request event 并响应。

http.ServerResponse

由 http.Server object 创建,作为 request event 的第二个参数传入,代码中作为 callback 的 res 参数使用:

const server = http.createServer((req, res) => {
  //res is an http.ServerResponse object
})

end() 是 http.ServerResponse object 必须被使用的 method,用来表示 response 信息已经完整,可以结束这个 response,同时将 response 发送出去。

下面的 method 可以用来处理 http headers:

  • getHeaderNames() 获取当前 http headers 名称的列表
  • getHeaders() 获取当前 http headers 副本
  • setHeader('headername', value) 设置一个 http header
  • getHeader('headername') 获取当前的一个 http header 的设置
  • removeHeader('headername') 删除一个 http header
  • hasHeader('headername') 如果某个 http header 有被设置则返回 true
  • headersSent() 如果 http headers 已经发送给了客户端则返回 true

服务端编辑好 headers 条目后可以通过 response.writeHead() method 发送给客户端,第一个参数是 statusCode。

通过 response.write() 在 response body 中发送数据给客户端,它会将缓冲区的数据发送到 http response stream。如果还没有使用 response.writeHead() 发送 headers 则会先发送 headers,包含 statusCode 和 message,它们可以通过下面语法设置:

response.statusCode = 500
response.statusMessage = 'Internal Server Error'

http.IncomingMessage

http.IncomingMessage 可以在以下两个地方创建:

  • http.Server 当监听 request event
  • http.ClientRequest 当监听 response event

它可以用来访问 response 数据:

  • 通过 statusCode 和 statusMessage 读取状态信息
  • 通过 headers method 或 rawHeaders method 读取 headers 信息
  • 通过 method method 获取可用 http method
  • 通过 httpVersion method 获取 http 版本信息
  • 通过 url method 获取 URL 信息
  • 通过 socket method 获取底层 socket 信息

在 http.IncomingMessage 生效一个可读的 stream 接口后,数据可在 stream 中读取。

标签:无

你的评论