Створюємо API для генерації QR Code зображень

В цій статі ми розглянемо, як за допомогою JavaScript та Node.js за 15 хвилин створити власний HTTP API, що повертатиме згенерований QR-код.

QR-код арт

Створюємо сайт

Саме API ми розгорнимо на безкоштовному сайті Wix.

Для початку зареєструмося на wix.com, можна через обліковий запис на Facebook або Google. Щоб створити сайт, перейдіть за посиланням на порожнiй шаблон, звідси ми потрапляємо прямісінько в редактор.

Після цього нам необхідно активувати Velo. Velo це розширення можливостей сайтів Wix, що дає нам змогу до написання скриптів як на frontend так і backend. У верхній частині едітора знаходимо пункт меню "Dev Mode", обираємо цей пункт і у розгорнутому підменю тиснемо на кнопку "Увімкнути Velo" (Turn on Dev Mode).

Ліворуч з'явиться файлова структура сайту (Site Structure): (Site Structure):

  • Pages
  • Public
  • Backend
  • node_modules
  • База даних
  • Мої додатки

Зараз нас цікавлять тільки дві текі, це Backend та node_modules. Почнемо з node_modules. Наводимо на цю теку і ліворуч з'являється коліщатко, тиснемо на нього й обираємо "Install a New Pakage", відкриється "Менеджер пакетів" (Package Manager). В полі "Пошук по пакетах" (Search packages) вводимо "qrcode" (саме за допомогою цієї бібліотеки ми будемо генерувати QR Code), обираємо "Встановити" (Install).

Залишилося тільки опублікувати сайт. В лівій верхній частині сайту тиснемо на кнопку "Опублікувати" (Publish). Обираємо назву для сайту і отримуємо таке посилання:

https://<USER_NAME>.wixsite.com/<SITE_NAME>

wix-http-functions

Тепер перейдемо до теки Backend. Тут нам потрібно створити JS-файл «Hовий файл .js» (New .js File) з назвою http-functions.js (назва має бути саме такою). У створеному файлі є код с прикладом, ми не будемо розглядати цей приклад, а послідовно створимо все з початку. Видаляємо зразок та починаємо.

Найменування функцій

Для створення роутингу в файлі http-functions.js, нам потрібно експортувати функції, назва яких складається з префіксу та назви роуту, розділених нижнім підкреслюванням.

 export function <prefix>_<functionName>(request) { }
  • <prefix> - це назва методу запиту (GET, POST, PUT ...) Докладніше на MDN
  • <functionName> - це назва роуту на який ми будимо відправляти запити.
  • request - це oб'єкт який містить параметри вхідних даних. Докладніше Velo Reference

Створімо роут для методу GET з назвою qrcode:

backend/http-functions.js

export function get_qrcode(request) {
  // TODO: ...
}

Зараз ми можемо відправляти GET-запити на _functions/qrcode. Повна адреса буде такою:

https://<USER_NAME>.wixsite.com/<SITE_NAME>/_functions/qrcode

Відповідь на запит

Для того щоб наше API мало змогу відповідати на запити, нам потрібно експортувати модуль wix-http-functions - це внутрішній модуль Wix сайтів що містить функціональність для роботи з HTTP. Ми будимо використовувати response:

backend/http-functions.js

import { response } from "wix-http-functions";

export function get_qrcode(request) {
  const text = "Hello";

  return response({
    status: 200,
    body: text,
  });
}

Тепер необхідно опублікувати наші зміни, тиснемо на кнопку "Опублікувати" (Publish) і переходимо за адресою:

https://<USER_NAME>.wixsite.com/<SITE_NAME>/_functions/qrcode

результат Hello.

Реалізуємо передачу тексту за допомогою параметрів запиту. Всі передані параметри ми можемо отримати через об'єкт request.query. Також нам необхідно декодувати переданий текст функцією decodeURIComponent(encodedURI)

backend/http-functions.js

import { response } from "wix-http-functions";

// ?text=Hello
export function get_qrcode(request) {
  // Текст передається як частина адреси запиту,
  // тому частина символів може буде задзеркальна в керовані послідовності UTF-8
  const text = decodeURIComponent(request.query.text);

  return response({
    status: 200,
    body: text,
  });
}
https://<USER_NAME>.wixsite.com/<SITE_NAME>/_functions/qrcode?text=Hello

QR Code

На початку ми додали бібліотеку qrcode за допомогою якої будемо генерувати зображення. Ми використаємо метод який поверне нам data:URL.

import QRCode  from "qrcode";

const text = "Hello";

QRCode.toDataURL(text).then((url) => {
  console.log(url); // data:URL
});

QRCode.toDataURL() - це асинхронна функія, вона приймає текст (з якого генеруватиметься QR Code) та повертає Promise.

Генерація QR Code виконується асинхронно, тому і роут потрібно перетворити на асинхронну функцію.

backend/http-functions.js

import { response } from "wix-http-functions";
import { toDataURL } from "qrcode";

// Додаємо оператор async
export async function get_qrcode({ query }) {
  const text = decodeURIComponent(query.text);
  // Чекаємо, коли виконається генерація зображення
  const dataURL = await toDataURL(text);

  return response({
    status: 200,
    body: dataURL,
  });
}

Не забуваємо опублікувати наші зміни. Зараз ми маємо API яке здатне повертати QR Code зображення у вигляди data:URL строки. Ми вже зараз можемо використовувати цей протокол щоб побачити QR Code зображення:

HTML

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAAAklEQVR4AewaftIAAAK0SURBVO3BSY7kQAwEQQ9C//+yTx95SkCQqhcOzeIX1hjFGqVYoxRrlGKNUqxRijVKsUYp1ijFGqVYoxRrlGKNUqxRijVKsUa5eCgJ30nlJAlPqHRJ+E4qTxRrlGKNUqxRLl6m8qYk3KFyRxLuUHlTEt5UrFGKNUqxRrn4sCTcoXJHEjqVLgmdypuScIfKJxVrlGKNUqxRLv5zKpMUa5RijVKsUS6GSUKncpKETuUvK9YoxRqlWKNcfJjKb5KETuUJld+kWKMUa5RijXLxsiT8JJUuCZ1Kl4RO5SQJv1mxRinWKMUa5eIhlb9M5UTlLynWKMUapVijXDyUhE6lS8KbVDqVLgmdSpeETuUkCW9S+aRijVKsUYo1ysVDKicqXRI6lSeS0KnckYQ7VE6ScEcSOpUnijVKsUYp1ijxCx+UhDepnCThRKVLQqfSJeFEpUvCHSpvKtYoxRqlWKNcfDOVkyR0Kl0STlS6JHRJOEnCicoTKp9UrFGKNUqxRolfeFES7lA5ScKbVLokdConSehUnkhCp/JEsUYp1ijFGuXiZSpvUjlJQqfyk5LQqZyovKlYoxRrlGKNEr/wQBK+k8pJEjqVLgmdSpeETuUkCZ1Kl4QTlTcVa5RijVKsUS5epvKmJJwkoVPpktCpnKicJOEkCT+pWKMUa5RijXLxYUm4Q+VNKl0SOpUuCZ1Kp9IloVM5ScInFWuUYo1SrFEuhklCp3KShJMknKh0SehUOpVPKtYoxRqlWKNc/GdUuiR0Kl0S7lDpktCpfFKxRinWKMUa5eLDVD5JpUvCSRJOknCi0iXhNynWKMUapVijXLwsCd8pCXeodEnoVJ5QOUlCp/KmYo1SrFGKNUr8whqjWKMUa5RijVKsUYo1SrFGKdYoxRqlWKMUa5RijVKsUYo1SrFGKdYo/wDUsBPle3QEgQAAAABJRU5ErkJggg==">

PNG

Hам залишилось тільки перетворити рядок data:URL у справжнє зображення. Щоб відповідь нашого API браузер розпізнавав як зображення, потрібно перетворити його на буферний масив бітів та додати заголовок у відповідь з типом контенту.

Почнемо

data:image/png;base64,<data>
  • data: — протокол;
  • image/png — MIME-тип контенту;
  • base64 — кодування;
  • <data> — закодоване зображення.

Нам потрібне лише саме зображення, тому відрізаємо всю метаінформацію до коми, перші 22 символи:

const base64 = dataURL.slice(22);

Щоб створити масив бітів у Node.js, використаємо Buffer.from(string[,encoding]):

Buffer.from(base64, "base64");

Також нам потрібно додати заголовки до відповіді:

{
  "Content-Type": "image/png",
}

Збираємо все до купи

backend/http-functions.js

/* eslint-env node */
import { response } from "wix-http-functions";
import { toDataURL } from "qrcode";

export async function get_qrcode({ query }) {
  const text = decodeURIComponent(query.text);
  const dataURL = await toDataURL(text);
  const base64 = dataURL.slice(22);

  return response({
    status: 200,
    headers: {
      "Content-Type": "image/png",
      "Cache-Control": "public, max-age=31556952, immutable",
    },
    body: Buffer.from(base64, "base64"),
  });
}

Прaцює!

<img
  src="https://shoonia.wixsite.com/blog/_functions/qrcode?text=Дякую%20за%20увагу!"
  width="200"
  height="200"
  loading="lazy"
  style="image-rendering: pixelated;"
  alt="Дякую за увагу!"
/>

Дякую за увагу!

Посилання