Espruino:Примеры/Обработка POST-данных, присланных через HTML-форму: различия между версиями
Myagkij (обсуждение | вклад) (Новая страница: «{{Espruino/Панель перехода}} {{Перевод от Сubewriter}} {{Myagkij-редактор}} =<ref>[ www.espruino.com - ]</ref>= <syntaxhighligh...») |
Myagkij (обсуждение | вклад) Нет описания правки |
||
Строка 3: | Строка 3: | ||
{{Myagkij-редактор}} | {{Myagkij-редактор}} | ||
=<ref>[ www.espruino.com - ]</ref>= | =Обработка POST-данных, присланных через HTML-форму<ref>[https://www.espruino.com/Posting+Forms www.espruino.com - Handling POSTed data from Forms]</ref>= | ||
В [https://www.espruino.com/Internet этом руководстве] рассказывается о простом способе отправки данных в URL веб-страницы. Но этот способ может оказаться ненадёжным, если что-нибудь, находящееся между вашим браузером и Espruino, решит закэшировать отправленные данные. | |||
<syntaxhighlight lang=" | Для решения этой проблемы в протоколе 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-запросе). | |||
== Вам понадобятся == | |||
Устройство, которое можно подключить к [https://www.espruino.com/Internet интернету] – вроде связки [https://www.espruino.com/Pico Espruino Pico] + ESP8266 или [https://www.espruino.com/WiFi Espruino WiFi] (без «компаньона»). | |||
== Код == | |||
Просто скопируйте и вставьте код ниже в Web IDE, затем укажите в переменных WIFI_NAME и WIFI_KEY значения, соответствующие вашей WiFi-сети, и удалите ненужную функцию onInit(). То есть, если вы используете Espruino Pico и ESP8266, удалите onInit() для Espruino WiFi, и наоборот. | |||
Если вы используете какое-то другое устройство, загляните в его документацию и создайте собственную функцию onInit(). | |||
Наконец, кликните в Web IDE на кнопку загрузки кода. | |||
<syntaxhighlight lang="javascript" enclose="div"> | |||
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(); | |||
</syntaxhighlight> | |||
Спустя несколько секунд после загрузки вы должны увидеть строчку вроде: | |||
<syntaxhighlight lang="javascript" enclose="div"> | |||
Подключились к http://192.168.1.85 | |||
</syntaxhighlight> | |||
Если кликнуть на этот URL или скопировать и вставить его в браузер, у вас должно получиться примерно следующее: | |||
[Картинка] | |||
Теперь попробуйте поставить какую-нибудь из галочек и кликнуть на Submit – это включит светодиод (или светодиоды), соответствующий выбранной галочке. | |||
Более подробную информацию о самом коде смотрите в комментариях к нему, а о формах – в [https://developer.mozilla.org/en-US/docs/Learn/Forms этой отличной статье на MDN]. | |||
=См.также= | =См.также= |
Версия от 14:22, 6 марта 2021
Обработка 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.
См.также
Внешние ссылки