Espruino:Примеры/Обработка POST-данных, присланных через HTML-форму

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Обработка POST-данных, присланных через HTML-форму[1]

В этом руководстве рассказывается о простом способе отправки данных в URL веб-страницы. Но этот способ может оказаться ненадёжным, если что-нибудь, находящееся между вашим браузером и Espruino, решит закэшировать отправленные данные.

Для решения этой проблемы в протоколе HTTP есть запросы типа POST, которые отличаются от обычных запросов GET тем, что всегда сообщают о необходимости отправить данные обратно на сервер. Код ниже – это пример использования запроса POST для включения и выключения двух светодиодов при помощи HTML-формы.

Код ниже состоит из 5 главных частей:

  • onInit() – запускается в самом начале и инициализирует WiFi.
  • onConnected() – запускается при создании WiFi-соединения. Печатает IP-адрес и запускает веб-сервер.
  • onPageRequest() – обрабатывает запрос веб-страницы или отправляет ошибку «404 Page Not Found» (в ситуации с неизвестной URL-ссылкой).
  • handlePOST() – вызывается, когда Espruino получает данные POST-запроса. Она принимает данные, разделяет и расшифровывает их, (исходя из присланных данных) включает/выключает светодиоды, а затем вызывает функцию обратного вызова
  • sendPage() – создаёт веб-страницу с HTML-формой

Функция handlePOST() может обработать все данные, присланные в POST-запросе, уже после закрытия соединения (обычно так и делается). Но нам нужно отправить обратно веб-страницу, показывающую текущее состояние двух управляемых нами светодиодов. Это значит, что при получении POST-запроса мы должны повременить с отправкой веб-страницы (с помощью sendPage()), пока handlePOST() не примет и не обработает все данные, заданные в HTML-форме (индикатором этого служит событие end в HTTP-запросе).

Вам понадобятся

Устройство, которое можно подключить к интернету – вроде связки Espruino Pico + ESP8266 или Espruino WiFi (без «компаньона»).

Код

Просто скопируйте и вставьте код ниже в Web IDE, затем укажите в переменных WIFI_NAME и WIFI_KEY значения, соответствующие вашей WiFi-сети, и удалите ненужную функцию onInit(). То есть, если вы используете Espruino Pico и ESP8266, удалите onInit() для Espruino WiFi, и наоборот.

Если вы используете какое-то другое устройство, загляните в его документацию и создайте собственную функцию onInit().

Наконец, кликните в Web IDE на кнопку загрузки кода.

var WIFI_NAME = "";
var WIFI_KEY = "";
var wifi;
// Данные, которые были присланы через POST-запрос в прошлый раз:
var postData = {};

// Эта функция для создания веб-страницы:
function sendPage(res) {
  // Мы используем здесь шаблонные литералы ES6,
  // чтобы код было максимально удобно читать:
  var d = `
<html>
 <body>
  <form action="#" method="post">
    <label for="mytext">Some text to send:</label>
    <input type="text" id="mytext" name="mytext" value="Testing"/><br/>
    <label for="led1">LED1 (red):</label>
    <input type="checkbox" id="led1" name="led1" value="1" ${postData.led1?"checked":""}><br/>
    <label for="led2">LED2 (green):</label>
    <input type="checkbox" id="led2" name="led2" value="1" ${postData.led2?"checked":""}><br/>
    <button>Submit</button>
  </form>
 </body>
</html>`;
  res.writeHead(200, {'Content-Type': 'text/html', 'Content-Length':d.length});
  res.end(d);
}  

// Эта функция обрабатывает сам HTTP-запрос
// и генерирует веб-страницу или страницу с ошибкой «404»:
function onPageRequest(req, res) {
  var a = url.parse(req.url, true);
  if (a.pathname=="/") {
    // Обрабатываем '/' (корневую) страницу...
    // Если получили POST-запрос, обрабатываем присланные данные:
    if (req.method=="POST" &&
        req.headers["Content-Type"]=="application/x-www-form-urlencoded")
      handlePOST(req, function() { sendPage(res); });
    else
      sendPage(res);
  } else {
    // Страница не найдена – возвращаем ошибку «404»:
    res.writeHead(404, {'Content-Type': 'text/plain'});
    res.end("404: Page "+a.pathname+" not found");
  }
}

// Эта функция обрабатывает все данные, присланные в POST-запросе:
function handlePOST(req, callback) {
  var data = "";
  req.on('data', function(d) { data += d; });
  req.on('end', function() {
    // Получили все данные от клиента,
    // так что начинаем обрабатывать данные, зашифрованные в URL.
    // При использовании «close» HTTP-запрос будет закрыт,
    // и мы не сможем отправить страницу с результатом.
    postData = {};
    data.split("&").forEach(function(el) {
      var els = el.split("=");
      postData[els[0]] = decodeURIComponent(els[1]);
    });
    // Наконец, наши данные в «postData»:
    console.log(postData);
    // Записываем данные из «postData»:
    console.log("Мы отправили текст ", postData.mytext);
    digitalWrite(LED1, postData.led1);
    digitalWrite(LED2, postData.led2);
    // Запускаем функцию обратного вызова
    // (чтобы отправить HTML-результат):
    callback();
  });
}

// Эта функция вызывается при создании интернет-соединения:
function onConnected() {
  console.log("Подключено!");
  wifi.getIP(function(err, ip) {
    console.log("Подключились к http://"+ip.ip);
    require("http").createServer(onPageRequest).listen(80);
  });
}

// Инициализация (ТОЛЬКО для Espruino WiFi):
function onInit() {
  wifi = require("EspruinoWiFi");
  wifi.connect(WIFI_NAME, { password : WIFI_KEY }, function(err) {
    if (err) {
      console.log("Ошибка подключения: "+err);
      return;
    }
    onConnected();
  });
}

// Инициализация (ТОЛЬКО для Espruino Pico + ESP8266)
function onInit() {
  Serial1.setup(115200, { tx: B6, rx : B7 });
  wifi = require("ESP8266WiFi_0v25").connect(Serial1, function(err) {
    if (err) throw err;
    console.log("Подключаемся по WiFi");
    wifi.connect(WIFI_NAME, WIFI_KEY, function(err) {
      if (err) {
        console.log("Ошибка подключения: "+err);
        return;
      }
      onConnected();
    });
  });
}

// Закройте комментариями эту строчку,
// если планируете сохранить свой код:
onInit();

Спустя несколько секунд после загрузки вы должны увидеть строчку вроде:

Подключились к http://192.168.1.85

Если кликнуть на этот URL или скопировать и вставить его в браузер, у вас должно получиться примерно следующее:

Теперь попробуйте поставить какую-нибудь из галочек и кликнуть на Submit – это включит светодиод (или светодиоды), соответствующий выбранной галочке.

Более подробную информацию о самом коде смотрите в комментариях к нему, а о формах – в этой отличной статье на MDN.

См.также

Внешние ссылки