HTTP / 2 начинает использоваться все больше и больше (он подскочил с 11% в начале этого года до 18% общего использования в Интернете). Если вы помните наши последние сообщения в блоге о HTTP / 2, такие как HTTP / 2: взгляд в будущее Интернета, Альтернативы HTTP / 2 или Оптимизация с помощью Server Push и Service Workers, вы можете вспомнить некоторые подробностей в протоколе HTTP / 2 и отличиях от первой версии. Ознакомьтесь с ними, если нет, так как мы не будем вдаваться в детали RFC в этом блоге.

В наших последних сообщениях в блоге мы упоминали, что версия HTTP / 2 начала реализовываться в репозитории nodejs / http2, но в то время не было решено, будет ли она объединена с основными модулями Node.js. или если это будет внешний модуль. Основная причина появления новой реализации заключалась в том, что другие реализации не полностью соблюдают HTTP / 2 RFC.

В конце концов, был отправлен запрос на включение, чтобы добавить его в ядро. Он был объединен и включен как экспериментальный под флагом (--expose-http2) в августе (версия 8.4.0).

После объявления в Twitter о том, что флаг собирается быть удаленным в выпуске 8.x LTS, Node.js в конечном итоге избавился от флага в версии 8.8.0 (24 октября). HTTP / 2 по-прежнему считается экспериментальным и, несмотря на то, что он еще не готов на 100%, вы уже можете начать экспериментировать с ним и ознакомиться с документацией по HTTP / 2 API.

Играя вокруг

Создание сервера HTTP / 2 не должно быть таким сложным. Фактически, если у вас уже есть опыт работы с Node.js, он должен быть очень похож на то, к чему вы привыкли. Посмотрите следующий пример:

const http2 = require('http2'),  
  fs = require('fs');
const options = {  
  key: fs.readFileSync('keys/server.key'),
  cert: fs.readFileSync('keys/server.crt')
};
const server = http2.createSecureServer(options);  
server.on('stream', (stream, requestHeaders) => {  
  stream.respond({
    'content-type': 'text/html',
    ':status': 200
  });
  stream.end('<h1>Hi, and welcome to YLD blog!</h1>');
});
server.listen(3000);

Основные отличия заключаются в том, что мы требуем http2 и отправляем параметры учетных данных функции http2.createSecureServer. Браузеры реализуют HTTP / 2 только по протоколу HTTPS, убедитесь, что вы настраиваете соединение TLS.

Вы, наверное, заметили, что мы везде используем стримы. Однако есть API совместимости, который позволяет легко переходить с HTTP / 1 на HTTP / 2. Вот как вы можете настроить обработчики запросов и ответов, как вы привыкли:

// ...
const onRequestHandler = (req, res) => {  
  const { socket: { alpnProtocol } } = req.httpVersion === '2.0' ? req.stream.session : req;
  res.writeHead(200, `Hi, and welcome to YLD blog! The server you are talking with supports ${alpnProtocol} `);
}
const server = http2.createSecureServer(  
  options,
  onRequestHandler
).listen(3000);

Обработчики запросов и ответов будут работать должным образом, несмотря на то, что у них уже есть дополнительная информация HTTP / 2, например, если соединение использует ALPN (используется только в HTTP / 2).

Одной из самых интересных функций HTTP / 2 является отправка файлов на сервер, и отправлять файлы довольно просто. В следующем примере мы видим, что каждый раз, когда запрашивается индексный маршрут, отправляется файл CSS:

const onRequestHandler = (req, res) => {  
  const currentUrl = url.parse(req.url);
  if (currentUrl.pathname === '/') {
    const cssFile = {
      path: '/style.css',
      filePath: './style.css',
      headers: {
        'content-type': 'text/css'
      }
    };
    pushAsset(res.stream, cssFile);
    // ...

и вы можете реализовать pushAsset следующим образом:

const pushAsset = (stream, file) => {  
  const filePath = path.join(__dirname, file.filePath);
  stream.pushStream({ [HTTP2_HEADER_PATH]: file.path }, (pushStream) => {
    pushStream.respondWithFile(filePath, file.headers);
  });
}

Фактически, API Node.js позволяет вам отправить файл с помощью responseWithFile или дескриптора файла с responseWithFD. file.path здесь весьма уместен, потому что это будет путь, который будет запрошен. например если файл запрашивается окном в /styles/style.css, путь нужно будет соответствующим образом изменить. В нашем случае это просто /style.css. Обратите внимание, что мы можем отправить столько файлов, сколько захотим, и вы можете отправить то, что, по вашему мнению, имеет отношение к странице индекса. Посмотрите полный пример.

Вы также можете протестировать с помощью Server Push и Service Workers, как мы делали в Оптимизация с помощью Server Push и Service Workers. Ознакомьтесь с примером использования базовой реализации HTTP / 2 Node.js.

Рамки и ожидания, следите за обновлениями!

Плохая новость в том, что такие фреймворки, как Express или Hapi.js еще не поддерживают HTTP / 2. Хорошей новостью является то, что это скоро будет реализовано, и оно должно быть очень похоже на реализацию, используемую для spdy или других старых модулей HTTP / 2 для Node.js.

Если вы хотите быть в курсе последних новостей, ознакомьтесь со следующими темами:

Выражать:

Hapi.js:

Хотите узнать больше?

Я выступал на эту тему на EmpireConf 13 октября. Если вам это интересно и если вы хотите узнать больше о HTTP / 2, посмотрите мой доклад Рост HTTP / 2, где я объясняю HTTP / 2 с помощью метафоры оркестра! Вы также можете найти примеры кода в репозитории github.com/sericaia/http2-examples-empireconf.

Опубликовано Даниэлой Матос де Карвалью - разработчиком программного обеспечения в YLD.