Nodejs网络模块(下) - HTTP与HTTPS模块

原创 Lin_Grady 教程 nodejs 99阅读 2018-08-21 19:37:05 举报

网络模块

NS提供了net、dgram、http、https分别用于处理TCP、UDP、HTTP、HTTPS,适用于客户端和服务端。

因为net和dgram是比较底层的功能模块,所以我只是简单说些方法和示例,重点放在http和https上。

Nodejs网络模块(上) - Net与Dgram模块
Nodejs网络模块(下) - HTTP与HTTPS模块

前置知识

Nodejs的Stream对象
网络协议基础 — TCP、UDP、SOCKET与参考模型
Http协议系列 — 协议原理构成与连接管理
Http协议系列 — cookie,Session,缓存机制
Http协议系列 — Http2、特殊字符编码与常见问题简答
Http协议系列—-进阶Https基础

HTTP

Node.js 中的 HTTP 接口被设计成支持协议的许多特性。 比如,大块编码的消息。 这些接口不缓冲完整的请求或响应,用户能够以流的形式处理数据。
HTTP 消息头由一个对象表示,键名是小写的,键值不能修改。

为了支持各种可能的 HTTP 应用,Node.js 的 HTTP API 是非常底层的。 它只涉及流处理与消息解析。 它把一个消息解析成消息头和消息主体,但不解析具体的消息头或消息主体。

然后我们简单知道一下下面几个类作用就进入实操了。

http.Agent 类

Agent 负责为 HTTP 客户端管理连接的持续与复用。 它为一个给定的主机与端口维护着一个等待请求的队列,且为每个请求重复使用一个单一的 socket 连接直到队列为空,此时 socket 会被销毁或被放入一个连接池中,在连接池中等待被有着相同主机与端口的请求再次使用。 是否被销毁或被放入连接池取决于 keepAlive 选项。

连接池中的连接的 TCP Keep-Alive 是开启的,但服务器仍然可能关闭闲置的连接,在这种情况下,这些连接会被移出连接池,且当一个新的 HTTP 请求被创建时再为指定的主机与端口创建一个新的连接。 服务器也可能拒绝允许同一连接上有多个请求,在这种情况下,连接会为每个请求重新创建,且不能被放入连接池。 Agent 仍然会创建请求到服务器,但每个请求会出现在一个新的连接。

但一个连接被客户端或服务器关闭时,它会被移出连接池。 连接池中任何未被使用的 socket 会被释放,从而使 Node.js 进程在没有请求时不用保持运行。

当 Agent 实例不再被使用时,建议 destroy() 它,因为未被使用的 socket 也会消耗操作系统资源。

当 socket 触发 'close' 事件或 'agentRemove' 事件时,它会被移出代理。 当打算长时间保持打开一个 HTTP 请求且不想它留在代理中,则可以如下处理:

代理也可被用于单独的请求。 使用 {agent: false} 作为 http.get() 函数或 http.request() 函数的选项,则会为客户端连接创建一个默认配置的一次性使用的 Agent

http.ClientRequest 类

该对象在 http.request() 内部被创建并返回。 它表示着一个正在处理的请求,其请求头已进入队列。 请求头仍可使用 setHeader(name, value)、getHeader(name)removeHeader(name) API 进行修改。 实际的请求头会与第一个数据块一起发送或当调用 request.end() 时发送。

要获取响应,需为 'response' 事件添加一个监听器到请求对象上。 当响应头被接收到时,'response' 事件会从请求对象上被触发 。 'response' 事件被执行时带有一个参数,该参数是一个 http.IncomingMessage 实例。

在 'response' 事件期间,可以添加监听器到响应对象上,比如监听 'data' 事件。

如果没有添加 'response' 事件处理函数,则响应会被整个丢弃。 如果添加了 'response' 事件处理函数,则必须消耗完响应对象的数据,可通过调用 response.read()、或添加一个 'data' 事件处理函数、或调用 .resume() 方法。 数据被消耗完时会触发 'end' 事件。 在数据被读取完之前会消耗内存,可能会造成 'process out of memory' 错误。

注意:Node.js 不会检查 Content-Length 与已传输的请求主体的长度是否相等。

该请求实现了可写流接口。

http.Server 类

继承自 net.Server

http.ServerResponse 类

该对象在 HTTP 服务器内部被创建。 它作为第二个参数被传入 'request' 事件。
这个类实现了(而不是继承自可写流接口。

http.IncomingMessage 类

IncomingMessage 对象由 http.Server 或 http.ClientRequest 创建,并作为第一个参数分别递给 'request' 和 'response'事件。 它可以用来访问响应状态、消息头、以及数据。
它实现了可读流接口。

例子

connect事件

入参描述
request/response (http.IncomingMessage)HTTP 请求/响应,同 'request' 事件。
socket (net.Socket)服务器与客户端之间的网络 socket
head (Buffer)流的第一个数据包,可能为空。

当该事件被触发后,请求的 socket 上没有 'data' 事件监听器,这意味着需要绑定 'data' 事件监听器,用来处理 socket 上被发送到服务器的数据。

listen事件

用法很多,具体看文档吧。

  • server.listen(handle[, backlog][, callback])
  • server.listen(options[, callback])
  • server.listen(path[, backlog][, callback]) for IPC servers
  • server.listen([port][, host][, backlog][, callback]) for TCP servers
    (还有更多方法可自行查询文档,我就不贴了)

http.request(options[, callback])

  • options (Object | string | URL)
    • protocol (string) 使用的协议。默认为 http:。
    • host (string) 请求发送至的服务器的域名或 IP 地址。默认为 localhost。 * hostname (string) host 的别名。为了支持 url.parse(),hostname 优先于 host。
    • family (number) 当解析 host 和 hostname 时使用的 IP 地址族。 有效值是 4 或 6。当未指定时,则同时使用 IP v4 和 v6。
    • port (number) 远程服务器的端口。默认为 80。
    • localAddress (string) 为网络连接绑定的本地接口。
    • socketPath (string) Unix 域 Socket(使用 host:port 或 socketPath)。
    • method (string) 指定 HTTP 请求方法的字符串。默认为 'GET'。
    • path (string) 请求的路径。默认为 '/'。 应包括查询字符串(如有的话)。如 '/index.html?page=12'。 当请求的路径中包含非法字符时,会抛出异常。 目前只有空字符会被拒绝,但未来可能会变化。
    • headers (Object) 包含请求头的对象。
    • auth (string) 基本身份验证,如 'user:password' 用来计算 Authorization 请求头。
    • agent (http.Agent) | (boolean) 控制 Agent 的行为。 可能的值有:
    • undefined (默认): 对该主机和端口使用 http.globalAgent。
    • Agent 对象:显式地使用传入的 Agent。
    • false: 创建一个新的使用默认值的 Agent。
    • createConnection (Function) 当不使用 agent 选项时,为请求创建一个 socket 或流。 这可以用于避免仅仅创建一个自定义的 Agent 类来覆盖默认的 createConnection 函数。详见 agent.createConnection()。 Any Duplex stream is a valid return value.
  • timeout (number): 指定 socket 超时的毫秒数。 它设置了 socket 等待连接的超时时间。
  • callback (Function)
  • 返回: (http.ClientRequest)

Node.js 为每台服务器维护多个连接来进行 HTTP 请求。 该函数允许显式地发出请求。

options 可以是一个对象、或字符串、或 URL 对象。 如果 options 是一个字符串,它会被自动使用 url.parse() 解析。 如果它是一个 URL 对象, 它会被默认转换成一个 options 对象。

可选的 callback 参数会作为单次监听器被添加到 'response' 事件。

http.request() 返回一个 http.ClientRequest 类的实例。 ClientRequest 实例是一个可写流。 如果需要通过 POST 请求上传一个文件,则写入到 ClientRequest 对象。

注意,在例子中调用了 req.end()。 使用 http.request() 必须总是调用 req.end() 来表明请求的结束,即使没有数据被写入请求主体。

如果请求过程中遇到任何错误(DNS 解析错误、TCP 级的错误、或实际的 HTTP 解析错误),则在返回的请求对象中会触发 'error' 事件。 对于所有的 'error' 事件,如果没有注册监听器,则抛出错误。

以下是需要注意的几个特殊的请求头。

  • 发送 'Connection: keep-alive' 会通知 Node.js,服务器的连接应一直持续到下一个请求。
  • 发送 'Content-Length' 请求头会禁用默认的块编码。
  • 发送 'Expect' 请求头会立即发送请求头。 通常情况下,当发送 'Expect: 100-continue' 时,超时时间与 continue 事件的监听器都需要被设置。 详见 RFC2616 章节 8.2.3。
  • 发送 Authorization 请求头会替代 auth 选项计算基本身份验证。

http.createServer([options][, requestListener])

  • options (Object)
    • IncomingMessage (http.IncomingMessage) 指定要使用的 IncomingMessage 类,用于拓展原始的IncomingMessage类. 缺省: IncomingMessage.
    • ServerResponse (http.ServerResponse) 指定要使用的 ServerResponse类, 用于拓展原始的ServerResponse类. 缺省: ServerResponse.
  • requestListener (Function)
  • 返回: (http.Server) 返回一个新的 http.Server实例。

步骤:
1,创建服务器
2,监听连接事件
3,监听端口1337,发送一个请求到代理服务器
4,连接事件中连接到一个服务器

http.get(options[, callback])

因为大多数请求都是 GET 请求且不带请求主体,所以 Node.js 提供了该便捷方法。 该方法与 http.request() 唯一的区别是它设置请求方法为 GET 且自动调用 req.end()。

HTTPS

基本和HTTP一样了,有两大类

  • https.Agent 类:类似于 http.Agent 的代理对象
  • https.Server 类:tls.Server 的子类,跟 http.Server 一样触发事件

例子

https.createServer([options][, requestListener])

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复