Fork me on GitHub

Node.js — Документация


Содержание


HTTP

Для использования клиента и сервера HTTP необходимо подключить соответствующий модуль с помощью require('http').

Интерфейс HTTP спроектирован в Node таким образом, чтобы поддерживать многие возможности протокола, которые традиционно было довольно сложно использовать. В частности, большие сообщения с возможным chunk-encoding. Интерфейс никогда не сохраняет в буфере целиком запрос или ответ, давая пользователю возможность принимать и отправлять данные в потоковом режиме.

Заголовки сообщения HTTP представлены примерно таким объектом:

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

Ключи приводятся к нижнему регистру. Значения не изменяются.

Для поддержки всего спектра возможных применений HTTP, соответствующее API в Node довольно низкоуровневое. Оно основано на потоках и передаче сообщений. Node разбирает HTTP-сообщение на заголовки и тело, остальное должен сделать программист.

http.Server

Это EventEmitter со следующими событиями:

Событие: 'request'

function (request, response) { }

Генерируется каждый раз при получении запроса. Заметьте, что в течении одного соединения может происходить несколько запросов (в случае keep-alive соединения). Объект request — экземпляр http.ServerRequest, объект response — экземпляр http.ServerResponse.

Событие: 'connection'

function (socket) { }

Генерируется при установке нового HTTP-соединения. socket — объект типа net.Socket. Обычно пользователи не используют это событие. Объект потока socket также можно найти в свойстве объекта запроса request.connection.

Событие: 'close'

function (errno) { }

Генерируется при завершении работы сервера.

Событие: 'checkContinue'

function (request, response) { }

Событие наступает кажды раз при получении заголовка 'Expect: 100'. Если для этого события не назначен ни один обработчик, то сервер автоматически отвечает '100 Continue'.

Обработка этого события подразумевает вызов response.writeContinue если клиент должен продолжить отправку тела запроса, или генерацию другого HTTP запроса (например '400 Bad Request') если клиент не должен этого делать.

Имейте в виду, что если это событие наступило и было обработано, то событие request не наступает.

Событие: 'upgrade'

function (request, socket, head) { }

Генерируется каждый раз когда клиент запрашивает апгрейд соединения до защищённого (см. RFC 2817). Если это событие никак не обрабатывается соединение для которого запрошен апгрейд будет закрыто.

После генерации этого события, у объекта server не будет обработчика события data, и программисту нужно назначить его заново чтобы обрабатывать данные, получаемые этим соединением.

Событие: 'clientError'

function (exception) { }

Если соединение с клиентом генерирует событие 'error' — оно поднимается сюда.

http.createServer([requestListener])

Возвращает новый объект web-сервера.

Функция requestListener автоматически добавляется к событию 'request' сервера.

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

Начинает приём соединений на указанном порту и имени хоста. Если имя хоста не указано, сервер будет принимать соединения на любой IPv4-адрес машины (INADDR_ANY).

Чтобы слушать unix-сокет, передайте имя файла вместо порта и имени хоста.

Эта функция асинхронна. Функция, переданная последним параметром callback будет вызвана когда сервер будет связан с портом.

server.listen(path, [callback])

Начинает слушать unix-сокет с заданным путём path.

Эта функция асинхронна. Функция, переданная последним параметром callback будет вызвана когда сервер будет связан с сокетом.

server.close()

Прекращает приём новых соединений сервером.

http.ServerRequest

Этот объект создаётся автоматически HTTP-сервером (не пользователем) и передаётся первым аргументом обработчику события 'request'.

Это EventEmitter со следующими событиями:

Событие: 'data'

function (chunk) { }

Генерируется при получении части тела сообщения. Пример: Порция данных передаётся единственных аргументов, декодируется в соответствии с transfer-encoding. Эта порция представляется строкой, кодировку которой можно установить с помощью request.setEncoding().

Событие: 'end'

function () { }

Генерируется строго один раз для каждого сообщения. После этого события не будут генерироваться другие события типа 'data'.

Событие: 'close'

function (err) { }

Указывает, что соединение было разорвано до вызова response.end() или возможности отправить данные.

Аргумент err всегда присутствует и указывает на причину разрыва соединения:

err.code === 'timeout' указывает на превышение таймаута соединения. Одной из причин может быть то, что все входящие подключения имеют таймаут по умолчанию 2 минуты.

err.code === 'aborted' означает, что клиент преждевременно закрыл соединение.

Как и событие 'end', это событие может наступить только один раз за соединение и после этого события не будут генерироваться другие события типа 'data'.

Примечание: 'close' может случиться до 'end', но не наоборот.

request.method

Метод запроса в виде строки. Только для чтения. Пример 'GET' или 'DELETE'.

request.url

Строка с URL запроса. Здесь содержится URL в том виде, в котором он задан в самом HTTP-запросе. Если запрос выглядит так:

GET /status?name=ryan HTTP/1.1\r\n
Accept: text/plain\r\n
\r\n

Тогда значением request.url будет:

'/status?name=ryan'

Если вы хотите разделить URL на составные части, вы можете использовать require('url').parse(request.url). Пример:

node> require('url').parse('/status?name=ryan')
{ href: '/status?name=ryan',
  search: '?name=ryan',
  query: 'name=ryan',
  pathname: '/status' }

Если вам нужно извлечь параметры из строки запроса, можно использовать функцию require('querystring').parse, или передать true в качестве второго аргумента require('url').parse. Пример:

node> require('url').parse('/status?name=ryan', true)
{ href: '/status?name=ryan',
  search: '?name=ryan',
  query: { name: 'ryan' },
  pathname: '/status' }

request.headers

Заголовки запроса. Только для чтения.

request.trailers

HTTP trailers (если есть). Только для чтения. Доступны тольк после наступления события 'end'.

request.httpVersion

Версия протокола HTTP в виде строки. Только чтение. Пример: '1.1', '1.0'. Также request.httpVersionMajor содержит первое число и request.httpVersionMinor — второе.

request.setEncoding(encoding=null)

Задаёт кодировку тела запроса. Либо 'utf8', либо 'binary'. По умолчанию принимает значение null, что означает что в обработчик события 'data' поступает буфер.

request.pause()

Прекращает генерирование событий запросом. Можно использовать для ускорения закачки файла.

request.resume()

Возобновляет генерирование событий запросом

request.connection

Объект соединения, экземпляр net.Socket.

При поддержке HTTPS достоверность и содержимое сертификата могут быть проверены с помощью методов verifyPeer() и getPeerCertificate() объекта request.connection сервера.

http.ServerResponse

Этот объект создаётся внутри HTTP-сервера — не пользователем. Он передаётся вторым параметром в обработчик события 'request' и является потоком с возможностью записи.

response.writeContinue()

Отправдяет клиенту сообщение 'HTTP/1.1 100 Continue', которое разрешает отправку тела запроса. См. описанеи события 'checkContinue' объекта http.Server.

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

Отправляет заголовки ответа клиенту. statusCode это три цифры кода статуса HTTP, например 404. Последний аргумент, headers, это заголовки ответа. Также вторым аргументом можно передать фразу reasonPhrase.

Пример:

var body = 'hello world';
response.writeHead(200, {
  'Content-Length': body.length,
  'Content-Type': 'text/plain' });

Этот метод должен быть вызван только однажды для каждого сообщения и должен быть вызван до response.end().

Если вы вызываете response.write() или response.end() перед response.writeHead(), то эта функция будет вызвана автоматически со всеми неявно отправленными заголовками.

Примечание: Content-Length содержит количество байт, а не символов. Пример выше корректен потому, что строка 'hello world' содержит только однобайтные символы. Если тело сообщения содержит многобайтные символы, то необходимо использовать Buffer.byteLength() для определения количества использованных для кодирования байтов. Node не проверяет, совпадает ли значение заголовка Content-Length и размер тела принятого ответа.

response.statusCode

При использовании неявных заголовков (без явного вызова response.writeHead()) это свойство устанавливает код ответа, который будет послан клиенту при отправке заголовков.

Пример:

response.statusCode = 404;

Это свойство отражает код статуса ответа после отправки заголовков.

response.setHeader(name, value)

Устанавливает неявный заголовок. Если этот заголовок уже существует в очереди для отправки, то его значение будет переобпределено новым. если вы хотите установить несколько заголовков с одинаковым именем, используйте массив строк.

Пример:

response.setHeader("Content-Type", "text/html");

или

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

response.getHeader(name)

Возвращает значение заголовка, который был поставлен в очередь, но ещё не был отправлен клиенту. Обратите внимание, что имя заголовка регистро независимо. Этот метод может быть вызван только до явной отправки заголовков.

Пример:

var contentType = response.getHeader('content-type');

response.removeHeader(name)

Удаляет заголовок из очередь для отправки.

Пример:

response.removeHeader("Content-Encoding");

response.write(chunk, encoding='utf8')

Если этот метод вызывается, а response.writeHead() ещё не был вызван, то происходит выключение неявного режима отправки заголовков и все заголовки из очереди немедленно отправляются клиенту.

Данный метод отправляет часть тела ответа. Метод может быть вызван несколько раз для отправки последующих частей тела ответа.

Аргумент chunk может быть буфером или строкой. Если chunk это строка, то бойвторой параметр указывает в какой кодировке отправлять её в поток. По умолчанию encoding принимает значение 'utf8'.

Замечание: Это необработанное тело HTTP-ответа и не имеет отношения к более высокоуровневым вещам вроде multi-part encoding, которые тоже могут использоваться.

После первого вызова response.write() клиенту будет отправлены заголовки и первая часть тела сообщения. После второго вызова response.write() Node предполагает что вы начинаете потоковую передачу данных и отправляет часть тела отдельно. Таким образом, данные буферизуются только до первой части тела ответа.

response.addTrailers(headers)

Этот метод добавляет завершающие заголовки HTTP, следующие после тела ответа.

Эти заголовки могут быть использованы **только* в случае использование ответом chunked encoding; в противном случае они будут проигнорированы.

Имейте в виду, что протокол HTTP требует указания заголовка Trailer в случае использования HTTP trailers, например:

response.writeHead(200, { 'Content-Type': 'text/plain',
                          'Trailer': 'TraceInfo' });
response.write(fileData);
response.addTrailers({'Content-MD5': "7895bf4b8828b55ceaf47747b4bca667"});
response.end();

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

Этот метод отправляет серверу сигнал что все заголовки и тело ответа отправлены; сервер должен считать это сообщение законченным. Метод response.end() ДОЛЖЕН быть вызван при каждом ответе.

Если задан аргумент data, то этот вызов эквивалентен поледовательному вызову response.write(data, encoding) и response.end().

http.request(options, callback)

Node поддерживает множественные соединения для выполнения HTTP запросов. Эта функция позволяет легко создавать их.

Параметры options:

http.request() возвращает объект класса http.ClientRequest, являющийся потоком с возможностью записи. Если вы хотите отпавить файл с помощью POST-запроса, вам нужно записать его в этот объект.

Пример подключения к google.com:

var options = {
  host: 'www.google.com',
  port: 80,
  path: '/upload',
  method: 'POST'
};

var req = http.request(options, function(res) {
  console.log('STATUS: ' + res.statusCode);
  console.log('HEADERS: ' + JSON.stringify(res.headers));
  res.setEncoding('utf8');
  res.on('data', function (chunk) {
    console.log('BODY: ' + chunk);
  });
});

req.on('error', function(e) {
  console.log('problem with request: ' + e.message);
});

// write data to request body
req.write('data\n');
req.write('data\n');
req.end();

Обратите внимание на вызов req.end() в примере. Используя http.request() вы должны вызвать req.end(), иначе всё что вы делали до этого с объектом не произойдёт и никакие данные не будут отправлены.

В случае возникновение ошибки (на уровне разрешения DNS имени, на уровне TCP или на уровне обработки тела HTTP запроса) будет сгенерировано событие 'error' объекта запроса req.

Нужно иметь в виду следующие особенности реализации:

http.get(options, callback)

Так как большинство запросов являются GET запросами без тела, Node содержит этот дополнительный метод. Единственное отличие от метода http.request() заключается в использовании запроса типа GET и автоматическом вызове req.end().

Пример:

var options = {
  host: 'www.google.com',
  port: 80,
  path: '/index.html'
};

http.get(options, function(res) {
  console.log("Got response: " + res.statusCode);
}).on('error', function(e) {
  console.log("Got error: " + e.message);
});

Событие: 'upgrade'

function (response, socket, head) { }

Генерируется каждый раз когда сервер отвечает на запрос предложением улучшить соединение до безопасного. Если это событие не обрабатывается, клиент при получении заголовка upgrade будет закрывать соединение.

Пример клиента и сервера, который демонстрирует использование события upgrade для http.getAgent:

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

// 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, upgradeHead) {
  socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
               'Upgrade: WebSocket\r\n' +
               'Connection: Upgrade\r\n' +
               '\r\n\r\n');

  socket.ondata = function(data, start, end) {
    socket.write(data.toString('utf8', start, end), 'utf8'); // echo back
  };
});

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

  // make a request
  var agent = http.getAgent('127.0.0.1', 1337);

  var options = {
    agent: agent,
    port: 1337,
    host: '127.0.0.1',
    headers: {
      'Connection': 'Upgrade',
      'Upgrade': 'websocket'
    }
  };

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

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

http.Agent

http.getAgent(host, port)

http.request() использует специального Агента для обработки множества соединений с HTTP сервером. Обычно объекты класса Agent не должны быть доступны в пользовательском коде, однако иногда это может быть полезно. Метод http.getAgent() позволяет получить доступ к этому объекту.

agent.maxSockets

По умолчанию равно 5. Определяет максимальное количество сокетов, одновременно открытых клиентом.

agent.sockets

Массив сокетов, используемых в данный момент. Не изменяйте этот массив.

agent.queue

Очередь запросов, ожидающих отправки.

http.ClientRequest

Объект создаётся внутри Node и возвращается методом http.request(). Он представляет собой незаконченный запрос, заголовки которого ещё не отправлены. Заголовки могут быть изменены с помощью методов setHeader(name, value), getHeader(name) и removeHeader(name). Установленные заголовки посылаются клиенту с первым фрагментом данных или при закрытии соединения.

Чтобы получить ответ, добавьте обработчик событию 'response' объекта запроса. Событие 'response' будет сгенерировано объектом запроса при получении заголовков ответа. Обработчик события 'response' выполняется с одним аргументом — экземпляром http.ClientResponse.

Во время события 'response' можно добавлять обработчики к объекту ответа; в частности, чтобы получать части тела ответа надо добавить обработчик событию 'data'. Заметьте что обработчик события 'response' вызывается до того, как будут получены части тела ответа, поэтому не надо беспокоиться, что первая часть тела будет пропущена. Если обработчик 'data' добавляется во время события 'response', то всё тело ответа будет получено наверняка.

// Good
request.on('response', function (response) {
  response.on('data', function (chunk) {
    console.log('BODY: ' + chunk);
  });
});

// Bad - misses all or part of the body
request.on('response', function (response) {
  setTimeout(function () {
    response.on('data', function (chunk) {
      console.log('BODY: ' + chunk);
    });
  }, 10);
});

Это поток с возможностью записи.

Это экземпляр EventEmitter со следующими событиями:

Событие: 'continue'

function () { }

Генерируется когда сервер посылайет HTTP ответ '100 Continue' HTTP, обычно если запрос содержит заголовок 'Expect: 100-continue'. Эта инструкция говорит клиенту о необходимости начать передачу тела запроса.

Событие: 'response'

function (response) { }

Генерируется когда на запрос приходит ответ. Это событие генерируется только один раз. Аргументом обработчика response будет экземпляр http.ClientResponse.

request.write(chunk, encoding='utf8')

Отправляет часть тела запроса. Вызывая этот метод несколько раз, пользователь может отправлять тело ответа серверу в потоковом режиме — в таком случае предпочтительно добавлять в заголовки ['Transfer-Encoding', 'chunked'] при создании запроса.

Аргумент chunk должен быть массивом чисел или строкой.

Аргумент encoding необязателен и имеет значение только если chunk строка.

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

Завершает отправку запроса. Если какие то части тела запроса ещё не были отправлены, они отправляются. Если запрос разбит на части, будет послана завершающая последовательность '0\r\n\r\n'.

Если задан аргумент data, то этот вызов эквивалентен поледовательному вызову request.write(data, encoding) и request.end().

request.abort()

Прерывает запрос. (Добавлено в версии v0.3.8)

http.ClientResponse

Этот объект создаётся при создании запроса с помощью http.request(). Он передаётся обработчику события 'response' объекта запроса.

Объект ответа — поток с возможностью чтения.

Событие: 'data'

function (chunk) { }

Часть тела сообщения передаётся обработчику в качестве единственного аргуметна. Строка уже преобразована из кодировки с помощью которой осуществлялась передача. Часть тела сообщения передаётся обработчику в виде строки. Кодировка тела сообщения задаётся response.setBodyEncoding().

Событие: 'end'

function () { }

Генерируется только однажды для каждого сообщения. Обработчик вызывается без аргументов. После этого сообщение не будет генерировать никаких событий.

Событие: 'close'

function (err) { }

Указывает на то, что соединения было закрыто до генерации события end. См. описание события 'close' для http.ServerRequest.

response.statusCode

Код статуса HTTP из трёх цифр, например 404.

response.httpVersion

Версия HTTP для текущего соединения. Скорее всего либо '1.1', либо '1.0'. Также response.httpVersionMajor — первая цифра версии, а response.httpVersionMinor — вторая.

response.headers

Заголовки ответа.

response.trailers

См. описание выше.

response.setEncoding(encoding=null)

Задаёт кодировку тела ответа. Может принимать значения 'utf8', 'ascii' или 'base64'. По умолчанию используется null, что означает что в обработчик события 'data' поступает буфер.

response.pause()

Приостанавливает генерацию событий ответом. Можно использовать для ускорения закачки файла.

response.resume()

Возобновляет генерацию событий ответом.