Пытаясь начать работать с Node.js, я недавно завершил руководство learnyounode. Это модуль Workshopper с интерфейсом командной строки, доступный через NodeSchool.io и npm. По сути, он обучает основам Node.js, предоставляя 13 задач с возрастающей сложностью и способ тестирования ваших решений. После каждой задачи он предоставляет подсказки и ссылки на документацию, которые помогут вам найти информацию, необходимую для решения задачи. В отличие от многих других обучающих систем, которыми я пользовался, он не помогает вам в каждой детали. Вы должны провести некоторое исследование и подумать самостоятельно, что я считаю гораздо более эффективным для усвоения информации. Последняя задача учебника — создание HTTP-сервера и JSON API, который манипулирует датой ISO. В этой статье я собираюсь понять требования задачи и составить свое решение. Я предполагаю общее знакомство с JavaScript, JSON и HTTP.

Задание №13 от «learnyounode»

Напишите HTTP-сервер, который обслуживает данные JSON при получении запроса GET
по пути ‘/api/parsetime’. Ожидайте, что запрос будет содержать строку запроса
с ключом «iso» и временем в формате ISO в качестве значения.

Например:

/api/parsetime?iso=2013–08–10T12:10:15.474Z

Ответ JSON должен содержать только 'час', 'минута' и 'секунда'
свойства. Например:

{
«час»: 14,
«минута»: 23,
«секунда»: 15
}

Добавьте вторую конечную точку для пути '/api/unixtime', который принимает ту же
строку запроса, но возвращает время эпохи UNIX в миллисекундах (количество
миллисекунд с 00:00 1 января 1970 года: 00 UTC) под свойством unixtime.
Например:

{ “unixtime”: 1376136615474 }

Ваш сервер должен прослушивать порт, указанный первым аргументом
вашей программы.

Разбивка требований к задаче

Прежде чем я начну исследовать или набирать код, мне нужно точно понять, что от меня требуется. Мне нужно подвести итоги того, какие требования я уже знаю, как решить из предыдущих задач, и какие требования мне нужно изучить. Вот как я разбил вызов:

  1. Нам нужно создать HTTP-сервер, который получает запрос GET, определенный путь и время в формате ISO в строке запроса. Сервер должен отвечать на эти запросы строкой JSON в определенном формате.
  2. Пути HTTP-запросов, которые нас интересуют: «/api/parsetime» и «/api/unixtime».
  3. Дата в формате ISO будет находиться внутри строки запроса с именем поля «iso», например: /api/parsetime?iso=2013–08–10T12:10:15.474Z
  4. Если мы получим путь parsetime, наш ответ JSON должен будет включать часы, минуты и секунды из запрошенной даты ISO.
  5. Если мы получим путь unixtime, наш ответ JSON должен будет включать формат времени эпохи UNIX запрошенной даты ISO.
  6. Наш HTTP-сервер должен прослушивать номер порта, указанный в качестве первого аргумента командной строки для нашей программы.

Создание моего решения

Чтобы выполнить требование № 1, нам нужно создать HTTP-сервер, который отвечает на запросы GET строковой версией нашего вывода в формате JSON. Для этого мы можем использовать базовый модуль Node http, функцию http.createServer и JSON.stringify(), которая превращает объект JavaScript в строку JSON.

var http = require(‘http’)
var server = http.createServer( function(request, response) {
  if (response.method === ‘GET’) { 
    // server logic to build output
    // then send our output in the http response
    response.writeHead(200, {‘content-type’: ‘application/json’})
    response.end(JSON.stringify(output));
  }
}

Чтобы выполнить требования № 2–3, нам нужно извлечь путь и время из запрошенного URL-адреса. Для этого мы можем использовать основной модуль Node url и функцию url.parse, которая преобразует URL в объект JavaScript. Передача второго аргумента true заставляет url.parse() дополнительно анализировать строку запроса URL в формате объекта, что позволит нам получить доступ к времени ISO с помощью parsedURL.query.iso. Наконец, мы создадим новый объект даты JavaScript из строки в формате ISO, чтобы мы могли работать с датой и изменять ее в других форматах для наших ответов.

var url = require(‘url’)

и внутри нашей функции обратного вызова createServer:

var parsedURL = url.parse(request.url, true);
var path = parsedURL.pathname;
var date = new Date(parsedURL.query.iso);

Чтобы выполнить требования № 4–5, мы создадим наши выходные данные в виде объектов JavaScript в требуемых форматах. Чтобы получить доступ к нужным нам частям и форматам времени, мы будем использовать встроенные в JavaScript методы даты для нашего объекта date.

if (path === ‘/api/parsetime’) {
  var output = { hour: date.getHours(),
                 minute: date.getMinutes(),
                 second: date.getSeconds()
               };
} else if (path === ‘/api/unixtime’) {
  var output = {unixtime: date.getTime()};
}

Наконец, для требования № 6 нам нужно указать серверу прослушивать предоставленный номер порта, к которому мы можем получить доступ из массива process.argv. Позиции 0 и 1 используются системой, поэтому первый аргумент командной строки находится в позиции 2.

server.listen(process.argv[2]);

Полное решение

var http = require(‘http’);
var url = require(‘url’);
var server = http.createServer(function(request, response) {
  if (request.method === ‘GET’) {
    var parsedURL = url.parse(request.url, true);
    var path = parsedURL.pathname;
    var date = new Date(parsedURL.query.iso);
    if (path === ‘/api/parsetime’) {
      var output = { hour: date.getHours(),
                     minute: date.getMinutes(),
                     second: date.getSeconds()
      };
    } else if (path === ‘/api/unixtime’) {
      var output = {unixtime: date.getTime()};
    }
    if (output) {
      response.writeHead(200, {‘content-type’: ‘application/json’});
      response.end(JSON.stringify(output));
    }
  }
});
server.listen(process.argv[2]);

Я нашел это руководство очень полезным для изучения основ Node и знакомства с наиболее важными структурами и методами. Для меня это был просто правильный баланс между руководством и принуждением к самостоятельному обучению из документации по Node.js и JavaScript. Далее я перейду к учебникам для мастеров по изучению Express.js, npm и MongoDB!