nodejs 5.2.0文档自翻译——HTTP模块

HTTP

通过require("http")来使用HTTP的客户端和服务端。

Node.js中的HTTP接口用于提供对传统协议中难以使用的特性的支持。 尤其是那些庞大或者是块编码的信息。该接口不会缓冲整个请求或者响应——用户可以自己使用流来处理数据。

HTTP头信息会被以如下的对象格式来表示:

{ 'content-length': '123',
  'content-type': 'text/plain',
  'connection': 'keep-alive',
  'host': 'mysite.com',
  'accept': '*/*' }

键都是小写的。值没有被修改。

为了尽可能的支持HTTP应用的全部范围,Node.js的API是很低级的。 它只会处理流和信息的解析。它只是将一个信息解析成HTTP头或者HTTP体但是不会去解析实际的HTTP头或HTTP体。

想了解如何处理重复的http头的细节请参考message.headers

原生的http头被保留在rawHeaders属性中,并以[key, value, key2, value2, ...]的数组形式呈现。比如, 之前的信息头对象就含有一个如下形式的rawHeaders列表:

[ 'ConTent-Length', '123456',
  'content-LENGTH', '123',
  'content-type', 'text/plain',
  'CONNECTION', 'keep-alive',
  'Host', 'mysite.com',
  'accepT', '*/*' ]

Class: http.Agent

HTTP代理用于作为一个HTTP客户端请求的socket池。

HTTP代理默认对客户端请求使用keep-alive连接。如果一个空闲的socket没有待定处理的http请求,那么这个socket会被关闭。这意味着当服务器处于低负荷状态时开发者不需要去关闭每一个使用KeepAlive的连接,这是一个好消息。

如果你选择使用KeepAlive,你可以将设置一个标识设置为true来创建一个代理对象(详细信息参考constructor options)。然后,代理对象会在池中保存空闲的socket用于以后来使用。他们会被打上明确的标记所以Node.js的进程不会一直处于运行状态。无论如何,当不需要再使用KeepAlive代理时用destroy()来取消它不失为一个好主意,那样所有的sockets也会被关闭。

当socket发生一个'close'事件或者一个特殊的'agentRemove'事件时socket会被从代理池中移除。这意味着如果你试图去维持一个HTTP请求一段时间而又不愿意将其放入池中,你可以像下面这样来处理:

http.get(options, function(res) {
  // Do stuff
}).on("socket", function (socket) {
  socket.emit("agentRemove");
});

又或者,你可以选择使用agent:false来完全脱离池:

http.get({
  hostname: 'localhost',
  port: 80,
  path: '/',
  agent: false  // create a new agent just for this one request
}, function (res) {
  // Do stuff with response
})

new Agent([options])

  • options对象用于配置agent. 可以设置以下几个属性:
    • keepAlive 布尔型,在池中保持sockets可以在之后给其他请求使用。默认值是false
    • keepAliveMsecs 整型,当使用HTTP KeepAlive,TCP KeepAlive包要发送多久socket就会保持连接多久,默认是1000. 只有当keepalive为true的时候才会起作用。
    • maxSockets number型,每个主机能够接受的最大的sockets数量,默认是infinity。
    • maxFreeSockets number型,处于空闲状态的socket的最大值。只有当keepAlive设置为true才会起作用。默认值是256。

当这些属性被设置为各自的默认值并被http.request()使用时,默认的 http.globalAgent 才会被使用。

如果想配置其中的任何一个值,你必须创建一个自己的http.Agent对象。

var http = require('http');
var keepAliveAgent = new http.Agent({ keepAlive: true });
options.agent = keepAliveAgent;
http.request(options, onResponseCallback);

agent.destroy()

销毁任何一个正在被agent使用的sockets。

通常情况下并不需要这么做。不管怎么说,如果你正在使用开启了keepAlive的agent,最好明确的关闭一个即将不被使用的agent。除此以外,sockets会维持一段时间直到服务器关闭他们。

agent.freeSockets

当使用HTTP KeepAlive时,agent.freeSockets对象会包含一个当前空闲的sockets数组。不要修改它。

agent.getName(options)

通过对request选项的进行设置来获取一个独一无二的名字,用于确认一个连接是否可以重复使用 。在http代理中,他会返回host:port:localAddress. 在https代理中,这个独一无二的名称中将会包含CA,cert,ciphers以及其他HTTPS/TLS-specific选项用于决定一个socket是否可以重复使用。

agent.maxFreeSockets

默认值是256.对于支持HTTP KeepAlive的代理,这个属性设置了处于空闲状态的sockets的最大数量。

agent.maxSockets

默认值是Infinity,用于决定一个一个代理可以设置最多多少个并发的sockets。

agent.requests

一个包含了还没有分配sockets的请求队列的对象,不要修改他。

agent.sockets

一个包含了代理中正在使用的sockets的数组的对象。不要修改他。

Class: http.ClientRequest

这个对象是在内部创建然后被 http.request()返回的。它代表了一个正在处理的请求,该请求的头部已经进入请求队列中。通过使用setHeader(name,value)getHeader(name)removeHeader(name)仍然可以改变该头部。实际的头部会随着第一个数据块一起发送或者当连接结束时发送。 

为了得到响应对象,应该给request对象添加一个监听器用于监听response。当响应头被接收到时,request对象会发送一个'response'。'response'事件会被执行,在执行时会使用一个http.IncomingMessage的实例作为参数。

在'response'事件期间,可以为reponse对象添加监听器;特别是监听'data'事件。

如果没有添加'response'处理函数,那么这个相应对象会被直接丢弃. 不管怎么说,如果你给 'response'事件添加了处理函数,那么你必须接收从response对象传递过来的数据要么对 'readable'事件使用response.read()处理,或是添加一个 'data' 事件的处理函数, 也可以使用 .resume() 方法。只有在数据被接收完毕之后, 'end' 事件才会被触发。同样的,只要数据没有被读取,那么将持续消耗内存直到产生一个'进程耗尽内存'的错误。

注意:Node.js不会去确认Content-Length以及被发送的body的长度是否相等。

该请求实现了Writable Stream接口。这是一个 包含了下列事件的EventEmitter

Event: 'abort'

function () { }

当请求被客户端打断时触发。该事件只会在第一次调用 abort()时触发。

Event: 'connect'

function (response, socket, head) { }

当服务器通过CONNECT方法响应一个请求时触发。如果该事件没有被监听,接受CONNECT方法的客户端将关闭连接。

下面这对客户端和服务端的交互将向你展示如何监听'connect'事件。

var http = require('http');
var net = require('net');
var url = require('url');

// Create an HTTP tunneling proxy
var proxy = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('okay');
});
proxy.on('connect', function(req, cltSocket, head) {
  // connect to an origin server
  var srvUrl = url.parse('http://' + req.url);
  var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, function() {
    cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
                    'Proxy-agent: Node.js-Proxy\r\n' +
                    '\r\n');
    srvSocket.write(head);
    srvSocket.pipe(cltSocket);
    cltSocket.pipe(srvSocket);
  });
});

// now that proxy is running
proxy.listen(1337, '127.0.0.1', function() {

  // make a request to a tunneling proxy
  var options = {
    port: 1337,
    hostname: '127.0.0.1',
    method: 'CONNECT',
    path: 'www.google.com:80'
  };

  var req = http.request(options);
  req.end();

  req.on('connect', function(res, socket, head) {
    console.log('got connected!');

    // make a request over an HTTP tunnel
    socket.write('GET / HTTP/1.1\r\n' +
                 'Host: www.google.com:80\r\n' +
                 'Connection: close\r\n' +
                 '\r\n');
    socket.on('data', function(chunk) {
      console.log(chunk.toString());
    });
    socket.on('end', function() {
      proxy.close();
    });
  });
});

Event: 'continue'

function () { }

当服务器回送'100 Continue'时触发该事件,通常情况是因为请求中包含了'Expected:100-continue'。这是一个让客户端发送请求体的指令。

Event: 'response'

function (response) { }

当请求接收到响应时触发该事件。该事件只会触发一次。这个response参数http.IncomingMessage的一个实例。

可选项:

  • host: 请求要发送到的服务器的域名或者IP地址。
  • port: 远程服务器的端口号。
  • socketPath: Unix域名套接字(使用host:post或者socketPath)。

Event: 'socket'

function (socket) { }

当一个socket被分配给一个request时触发该事件。

Event: 'upgrade'

function (response, socket, head) { }

每当服务器向request返回一个upgrade时触发该事件。如果没有监听该事件,客户端会收到一个upgrade头并关闭连接。

一组客户端和服务器端交互的例子将向你展示如何监听'upgrade'事件。

var http = require('http');

// Create an HTTP server
var srv = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('okay');
});
srv.on('upgrade', function(req, socket, head) {
  socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
               'Upgrade: WebSocket\r\n' +
               'Connection: Upgrade\r\n' +
               '\r\n');

  socket.pipe(socket); // echo back
});

// now that server is running
srv.listen(1337, '127.0.0.1', function() {

  // make a request
  var options = {
    port: 1337,
    hostname: '127.0.0.1',
    headers: {
      'Connection': 'Upgrade',
      'Upgrade': 'websocket'
    }
  };

  var req = http.request(options);
  req.end();

  req.on('upgrade', function(res, socket, upgradeHead) {
    console.log('got upgraded!');
    socket.end();
    process.exit(0);
  });
});

request.abort()

将request标记为中止。使用该方法会将数据保留在被中止的response中并将socket移除。

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

完成request的发送。如果请求体中仍有部分未被发送,那么会这一部分flush到stream中。如果request被分块发送,那么该方法会发送一个终结符号 '0\r\n\r\n'。

那么该方法相当于调用之后紧接着调用

如果指定了data,那么该方法相当于先调用response.write(data, encoding)之后再调用request.end(callback)。

如果指定了callback,那么这个回调函数会在request流结束时被调用。

request.flushHeaders()

flush请求头。

处于效率的考虑,Node.js一般会将请求头缓存直到你调用request.end()或者请求数据的第一个数据块被写出。之后它会尽量将请求头和数据打包在一个TCP数据包中。

通常来说,你是很希望在TCP往返的过程中请求头都会被保留,除非第一个数据过了很久才发送。request.flushHeaders()让你可以忽视最优化并启动请求(可能不太准确,建议参照原文)。

request.setNoDelay([noDelay])

一旦一个socket被分配给这个request并且连接成功,socket.setNoDelay()就会被调用。

request.setSocketKeepAlive([enable][, initialDelay])

一旦一个socket被分配给这个request并连接成功,socket.setKeepAlive()就会被调用。

request.setTimeout(timeout[, callback])

一旦一个socket被分配给这个request并连接成功,socket.setTimeout()就会被调用。

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

发送请求体的一个数据块。通过多次调用该方法,使用者可以以流的形式将请求体发送给服务器--这种情况下建议在创建请求时使用['Transfer-Encoding', 'chunked']作为头部。

chunk参数必须是一个buffer类型或者string类型。

encoding参数是可选的,只有在chunk是字符串类型是才能使用。默认值是'utf8'。

callback参数是可选的,当数据块被flushed时,该回调函数会被调用。

request.write()方法返回一个request对象。

Class: http.Server

这是一个包含了下列事件的EventEmitter

Event: 'checkContinue'

function (request, response) { }

每当收到一个Expect:100-continues时触发该事件。如果没有监听该事件,那么服务器会在合适的时机自动的响应一个100 Continue。

处理该事件时,如果客户端可以继续发送请求体,那么需要调用response.writeContinue() 如果客户端不能继续发送请求体,则生成一个合适的HTTP响应(比如,400 Bad Request)。

请注意,当该事件被触发和处理时,'request'事件将不会被触发。

Event: 'clientError'

function (exception, socket) { }

如果客户端连接时触发了一个事件,将会被转发到这里。

socket 是最初发生错误的的一个net.Socket对象。

Event: 'close'

function () { }

当服务器关闭时触发该事件。

Event: 'connect'

function (request, socket, head) { }

当客户端请求为CONNECT方法时触发该事件。 如果没有监听该事件,那么当客户端发起CONNECT请求时,连接会被关闭。

  • request  是一个http的请求参数,和request事件中是相同的。
  • socket 是介于服务器和客户端之间的网络socket。
  • head 是一个Buffer实例,是隧道流的第一个包,可能是个空包。

该事件触发后。请求的socket将不会监听'data'事件,这意味着你需要手动去绑定一个处理从socket传递给服务器的数据的监听器。

Event: 'connection'

function (socket) { }

当一个新的TCP流建立后触发。socket是net.Socket类型的一个对象。一般来说用户并不需要去接触这个事件。特别注意的是,协议分析器绑定到socket的方式会导致socket无法触发'readable'事件。socket在 request.connection中也可以访问到。

Event: 'request'

function (request, response) { }

每当产生一个请求时触发。请注意每个连接可能存在多个请求(比如keep-alive连接)。requesthttp.IncomingMessage的实例,responsehttp.ServerResponse的实例。

Event: 'upgrade'

function (request, socket, head) { }

当客户端发送一个upgrade的http请求时触发。如果没有监听该事件,那么当客户端发起upgrade请求时会断开连接。

  • request 是表示http请求的参数,和request事件中相同。
  • socket 是介于服务器和客户端的网络socket。
  • head 是一个Buffer的实例,是upgrade流的第一个数据包,有可能是个空包。

在该事件触发后,请求的socket将不在监听data事件,这意味着你需要手动绑定一个处理该socket发给服务器的数据的监听器。

server.close([callback])

停止服务器接收新的连接。详情请参考net.Server.close()

server.listen(handle[, callback])

  • handle Object类型
  • callback Function类型

 

The handle 对象可以被设置成一个服务器或一个socket(任何一个含有下划线的成员_handle),又或者是一个{fd: <n>} 对象。

该方法使服务器用特殊的句柄来接收连接,但是它假设文件描述符或者处理器已经被绑定给一个端口或domain socket。

Windows环境下不支持监听一个文件描述符。

该方法是异步的。最后一个参数 callback 将被作为 'listening'事件的监听器。 可以参考 net.Server.listen()

server.listen(path[, callback])

开启一个UNIX socket服务器用于监听对给定 path 的连接。

该函数是异步的。最后一个 callback 参数会被作为 'listening' 事件的监听器。可以参考 net.Server.listen(path)

server.listen(port[, hostname][, backlog][, callback])

在特定的端口和主机名接收连接。如果省略了主机名,服务器会在任何一个可以使用的IPv6地址或一个IPv4地址接受连接。如果将端口设置为0那么将会随机分配一个端口。

如果用于监听一个unix socket,那么需要提供一个文件名来代替端口和主机名。

backlog是指待处理连接队列的最大长度。实际长度通过操作系统的sysctl设置(比如linux下设置tcp_max_syn_backlog和somaxconn)来决定。这个参数的默认值是511(而不是512)。

该方法是异步的。最后一个callback参数会作为'listening' 事件的监听器。可以参考  net.Server.listen(port)

server.maxHeadersCount

最大的请求头数量限制,默认设置为1000。如果设置成0则代表不做限制。

server.setTimeout(msecs, callback)

  • msecs Number类型
  • callback Function类型

设置socket的超时时间。如果出现超时,则在Server对象上触发一个'timeout' 事件,则将socket作为一个参数传递。

如果在Server对象上监听了 'timeout' 事件,那么当一个超时的socket被作为参数时会调用该监听器。

默认的,Server的超时时间被设置成2分钟,如果超时那么socket会自动销毁。不管怎么说,如果你给Server的事件分配了一个回调函数,那么你将负责去处理过期的socket。

返回一个server对象。

server.timeout

  • Number类型 默认值 = 120000 (2 分钟)

一个socket被判断为超时之前的闲置毫秒数。

请注意socket的超时逻辑上说是设置在连接上的,所以改变这个值只会影响新连接而不会影响已存在的连接。

设置为0用于禁止连接的任意自动超时行为。

Class: http.ServerResponse

该对象由HTTP server内部创建--而不是被用户创建。他被作为第二个参数传递给 'request' 事件。

response实现了 Writable Stream 接口。 这是一个包含下列事件的 EventEmitter :

Event: 'close'

function () { }

要指出底层连接会在调用 response.end() 之前或被flush之前被终结。

Event: 'finish'

function () { }

当response被发送时触发该事件。更加需要注意的是,该事件被触发当response头和体的最后一个部分More specifically, this event is emitted when the last segment of the response headers and body have been handed off to the operating system for transmission over the network. It does not imply that the client has received anything yet.

After this event, no more events will be emitted on the response object.

 

posted @ 2015-12-13 18:31  ADAM亚当  阅读(566)  评论(0编辑  收藏  举报