12.2.2. Пример использования Node: модуль утилит клиента HTTP

В примере 12.3 определяется несколько вспомогательных клиентских функций, использующих модуль «http», позволяющих выполнять GET- и POST-запросы протокола HTTP. Пример оформлен как модуль «httputils», который можно использовать в собственных программах, например:

var httputils = require("./httputils"); // Отметьте отсутствие расш. ".js"

httputils.get(иrl. function(status. headers, body) { console.log(body); });

При выполнении программного кода модуля функция require() не использует обычную функцию eval(). Модули выполняются в специальном окружении, чтобы они не могли определять глобальные переменные или как-то иначе изменять глобальное пространство имен. Это специализированное окружение для выполнения модулей всегда включает глобальный объект с именем exports. Модули экспортируют свои API, определяя свойства этого объекта.[27]

Пример 12.3. Модуль «httputils» для интерпретатора Node

//

// Модуль "httputils" для интерпретатора Node.

//

// Выполняет асинхронный HTTP GET-запрос для указанного URL и передает

// код состояния HTTP, заголовки и тело ответа указанной функции обратного

// вызова. Обратите внимание, как этот метод экспортируется через объект exports.

exports.get = function(url, callback) {

  // Разобрать URL и получить необходимые фрагменты

  url = require('url‘).parse(url);

  var hostname = url.hostname, port = url.port || 80;

  var path = url.pathname, query = url.query;

  if (query) path += "?” + query;

  // Выполняем простой GET-запрос

  var client = require("http").createClient(port, hostname);

  var request = client.request("GET”, path, {

    "Host": hostname // Заголовки запроса

  });

  request.end();

  // Функция обработки ответа после начала его получения

  request.on("response", function(response) {

    // Указать кодировку, чтобы тело возвращалось как строка, а не байты

    response.setEncoding("utf8");

    // Для сохранения тела ответа по мере получения

    var body = response.on("data", function(chunk) { body += chunk; });

    // По окончании тела ответа вызвать функцию обратного вызова

    response.on("end", function() { if (callback)

      callback(response.statusCode, response.headers, body);

    ));

  });

};

// Простой HTTP POST-запрос с данными в теле запроса

exports.post = function(url, data, callback) {

  // Разобрать URL и получить необходимые фрагменты

  url = requiге('url').parse(url);

  var hostname = url.hostname, port = url.port || 80;

  var path = url.pathname, query = url.query;

  if (query) path += "?" + query;

  // Определить тип данных, отправляемых в теле запроса var type;

  if (data == null) data = "";

  if (data instanceof Buffer) // Двоичные данные

    type = "application/octet-stream";

  else if (typeof data === "string”) // Строковые данные

    type = "text/plain; charset=UTF-8";

  else if (typeof data === "object") { // Пары имя/значение

    data = require("querystring").stringify(data);

    type = "application/x-www-form-urlencoded";

  }

  // Выполнить POST-запрос и отправить тело запроса

  var client = require("http").createClient(port, hostname);

  var request = client.request("POST", path, {

    "Host": hostname,

    "Content-Type": type

  }):

  request.write(data); // Отправить тело запроса

  request.end();

  request.on("response", function(response) { // Обработать ответ

    response.setEncoding("utf8"); // Предполагается текст

    var body = "" // Для хранения тела ответа

    response.on("data", function(chunk) { body += chunk; });

    response.on("end", function() { // По завершении вызвать обработчик

    if (callback)

      callback(response.statusCode, response.headers, body);

  });

});