• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь POST запрос, регистрация платы esp32s[Node32s]

patriot_red_ru

New member
Пытаюсь зарегистрировать плату на специальном сервере.
Для этого использую POST запрос.
Пример как должен выглядеть запрос:
Код:
POST /auth/esp/register HTTP/1.1
Host: myhost
Content-Type: application/json
Cache-Control: no-cache

{"ESPIdentifier": "000:111:222:333:444"}

Код на Lua который я использую:
Код:
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "SSID";
const char* password =  "Pass_wifi";

const char* host = "myhost";
const int httpsPort = 443;

void setup() {
     
      Serial.begin(115200);
 
  Serial.print("connecting to ");
  Serial.println(ssid);
  Serial.println();
  WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
  Serial.print("MAC: ");
  Serial.println(WiFi.macAddress());

      Serial.print("connecting to ");
      Serial.println(host);
      //Провека работы сервера
          if (!client.connect(host, httpsPort)) {
            Serial.println("connection failed");
          }
              else
          {
            Serial.println("OK");
          }
     
        while (WiFi.status() != WL_CONNECTED)
     
      delay(500);
      Serial.println("Waiting for connection...");





if(WiFi.status()== WL_CONNECTED){ //Проверка соединения wifi

      HTTPClient http;
      http.begin("ССЫЛКА НА РЕГИСРАЦИЮ");
      http.addHeader("Host", "myhost");
      http.addHeader("Content-Type", "application/json");
      http.writeToStream(&Serial);
      http.end();


      int httpResponseCode = http.POST("POST /auth/esp/register HTTP/1.1\r\n{\"ESPIdentifier\": \"000:123:265:312:484\"}");
    if (httpResponseCode > 0) { //Возвращаемое значение
        String payload = http.getString();
        Serial.println(httpResponseCode);
        Serial.println(payload);
      }
    else {
      Serial.println("Error on HTTP request");
    }
    http.end(); //Освобождение ресурсов
    }
else
   {
       
    Serial.print("Error in Wifi connection");
       
   }
     
      delay(30000); //Отправка запроса и проверка каждые 30 секунд
}

void loop() {


}
Сервер возвращает:
400 - не правильное оформление запроса

Было испытано большое количество вариантов оформления запросов...

Как правильно оформить запрос?
Что не так?
 

Алексей.

Active member
patriot_red_ru,
Одной и причин может быть проверка заголовка Host на сервере.
Может аутентификация не выполнена и сервер вместо 401-й ошибки возвращает 400-ю.

Не используя плату, на обычном ПК, не пробовали выполнять запрос?
 

patriot_red_ru

New member
patriot_red_ru,
Одной и причин может быть проверка заголовка Host на сервере.
Может аутентификация не выполнена и сервер вместо 401-й ошибки возвращает 400-ю.

Не используя плату, на обычном ПК, не пробовали выполнять запрос?
Пробовал, всё работает.
 

Алексей.

Active member
Вы при вызове http.POST передаете в пайлоаде (в теле сообщения) ещё и метод, зачем?
Клиента Вы уже инициализировали http.begin http.addHeader,
не понятно правда зачем ещё выполнили http.end
После инициализации выполняете явно метод POST, сервер скорее всего ожидает в пост-запросе джейсон, а Вы ему метод с урлом перед джейсоном шлете.
Передайте просто http.POST("{\"ESPIdentifier\": \"000:123:265:312:484\"}");

П.С.
Надеюсь вы не используете http.begin("ССЫЛКА НА РЕГИСРАЦИЮ") :)
а используете что то типа http.begin("https://myhost/auth/esp/register")
 
Последнее редактирование:

patriot_red_ru

New member
Вы при вызове http.POST передаете в пайлоаде (в теле сообщения) ещё и метод, зачем?
Клиента Вы уже инициализировали http.begin http.addHeader,
не понятно правда зачем ещё выполнили http.end
После инициализации выполняете явно метод POST, сервер скорее всего ожидает в пост-запросе джейсон, а Вы ему метод с урлом перед джейсоном шлете.
Передайте просто http.POST("{\"ESPIdentifier\": \"000:123:265:312:484\"}");

П.С.
Надеюсь вы не используете http.begin("ССЫЛКА НА РЕГИСРАЦИЮ") :)
а используете что то типа http.begin("https://myhost/auth/esp/register")

Я сделал по другому.

Код:
      HTTPClient http;
      http.begin("https://СЕРВАК/auth/esp/register");
      String postRequest =
      "POST /auth/esp/register HTTP/1.1 Host: myhost Content-Type: application/json {\"ESPIdentifier\": \"000:548:222:123:454\"}";
//так же пробовал
//"POST /auth/esp/register HTTP/1.1\r\nHost: myhost\r\nContent-Type: application/json\r\n{\"ESPIdentifier\": \"000:548:222:123:454\"}"\r\n;
//"POST /auth/esp/register HTTP/1.1\r\nHost: myhost\r\nContent-Type: application/json\r\nCache-Control: no-cache\r\n{\"ESPIdentifier\": \"000:548:222:123:454\"}"\r\n;
//"POST /auth/esp/register HTTP/1.1\r\nHost: myhost\r\nContent-Type: application/json\r\nCache-Control: no-cache\r\nESPIdentifier: 000:548:222:123:454"\r\n;
     int httpResponseCode = http.POST(postRequest);
Сервер возвращает:
Код:
415
{"Message":"The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource."}
Так же я попробовал через этот ресурс Послать POST/GET запрос - Инструментарий Web и JavaScript разработчика отправить POST запрос и вставить ИДЕпс: ИД прямо в хед как показано на рисунке.

И регистрация прошла успешно...

НО С ЕСПЕШКИ ТАК НЕ РАБОТАЕТ!
 

Вложения

Алексей.

Active member
patriot_red_ru, Завидное упорство,
в последнем примере Вы инициализируете клиента урлом, не добавляете никаких заголовков и в тело запроса по прежнему включаете и метод и иногда заголовки, их не должно быть в теле, сервер Вам однозначно ответил "запрос содержит сущность тела но нет заголовка Content-Type".
Непонятно почему вы не хотилте оставить первый пример, в котором был добавлен заголовок http.addHeader("Content-Type", "application/json") и убрать из тела название метода, оставив только джейсон.

В той ссылке которую вы использовали для проверки, ESPIdentifier в тело сообщения как
Код:
POST /auth/esp/register HTTP/1.1
Host: myhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://seriyps.ru/postget/
Content-Type: application/x-www-form-urlencoded
Content-Length: 108
Connection: keep-alive
Upgrade-Insecure-Requests: 1

Host=myhost&Content-Type=application0.000000json&Cache-Control=no-cache&ESPIdentifier=0000X0.0000000000003P-10221110X0.07FFC554145BFP-10222220X0.07FFC5541466P-10223330X0P+0444
это не то что вы хотели в начале
Код:
POST /auth/esp/register HTTP/1.1
Host: myhost
Content-Type: application/json
Cache-Control: no-cache

{"ESPIdentifier": "000:111:222:333:444"}
 
Последнее редактирование:

patriot_red_ru

New member
Непонятно почему вы не хотилте оставить первый пример, в котором был добавлен заголовок http.addHeader("Content-Type", "application/json") и убрать из тела название метода, оставив только джейсон.
Не могли бы вы показать, как я должен оформить запрос на Lua?
Просто я пробую как вы говорите, но возможно я вас не правильно понял.
 

Алексей.

Active member
patriot_red_ru, На луа я не умею :)
Я из Вашего примера выкинул проверку соединения в начале, выкинул добавления заголовка Host, клиент сам его добавляет и в теле сообщения оставил только джейсон.
Код:
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "****";
const char* password = "****";
void setup() {
  Serial.begin(115200);

  Serial.print("connecting to ");
  Serial.println(ssid);
  Serial.println();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
  Serial.print("MAC: ");
  Serial.println(WiFi.macAddress());
  HTTPClient http;
  http.begin("http://192.168.4.1/auth/esp/register");
  http.addHeader("Content-Type", "application/json");
 
  int httpResponseCode = http.POST("{\"ESPIdentifier\": \"000:123:265:312:484\"}");
  if (httpResponseCode == 200) { //Возвращаемое значение
    String payload = http.getString();
    Serial.println(httpResponseCode);
    Serial.println(payload);
  } else {
    Serial.println("Error on HTTP request");
  }
  http.end(); //Освобождение ресурсов
}
void loop() {
}
Вот какой запрос был отправлен на сервер
Код:
POST /auth/esp/register HTTP/1.1
Host: 192.168.4.1
User-Agent: ESP32HTTPClient
Connection: close
Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0
Content-Type: application/json
Content-Length: 40

{"ESPIdentifier": "000:123:265:312:484"}
 

newnew

New member
patriot_red_ru, На луа я не умею :)
Я из Вашего примера выкинул проверку соединения в начале, выкинул добавления заголовка Host, клиент сам его добавляет и в теле сообщения оставил только джейсон.
Код:
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "****";
const char* password = "****";
void setup() {
  Serial.begin(115200);

  Serial.print("connecting to ");
  Serial.println(ssid);
  Serial.println();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
  Serial.print("MAC: ");
  Serial.println(WiFi.macAddress());
  HTTPClient http;
  http.begin("http://192.168.4.1/auth/esp/register");
  http.addHeader("Content-Type", "application/json");
 
  int httpResponseCode = http.POST("{\"ESPIdentifier\": \"000:123:265:312:484\"}");
  if (httpResponseCode == 200) { //Возвращаемое значение
    String payload = http.getString();
    Serial.println(httpResponseCode);
    Serial.println(payload);
  } else {
    Serial.println("Error on HTTP request");
  }
  http.end(); //Освобождение ресурсов
}
void loop() {
}
Вот какой запрос был отправлен на сервер
Код:
POST /auth/esp/register HTTP/1.1
Host: 192.168.4.1
User-Agent: ESP32HTTPClient
Connection: close
Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0
Content-Type: application/json
Content-Length: 40

{"ESPIdentifier": "000:123:265:312:484"}
День добрый!
Извините если не в тему...
А запросы http.get() и http.post() можно использовать для обмена клиента на ESP и сервера?
Пробую следующую конструкцию:

do
cf={
web_url="http://mysite.ru/test.php",
var1=1,
var2=250,
var3=1
}

http.post(cf['web_url'],
'Content-Type: application/x-www-form-urlencoded\r\n',
'Term='..cf['var2']..'&Rele='..cf['var3']..'&ID='..cf['var1'],
function (http_code,http_data)
if(http_code < 0) then
print("HTTP request failed.")
else
print("Sent to the web OK")
--print (cf['web_url'])
end
end)
end

В ESPlorer получаю ответ:

Sent to the web OK.
Я так понимаю запрос на сервер отправлен?..
На страничке mysite.test.php содержащей
<?php

if(isset($_POST['ID'])&&!empty($_POST['ID'])){echo $_POST['ID']; }else{echo 'MISTAKE <br />\n';};
?>

печатается MISTAKE....

Не подскажете , что не так и как проверить уходит и приходит ли запрос...
 

Алексей.

Active member
newnew,
как то не понятно вы строите в запросе body
'Term='..cf['var2']..'&Rele='..cf['var3']..'&ID='..cf['var1']
печатается MISTAKE....
пых-пых пытается найти не пустой ID и не находит, посмотрите на сервере что в запросе приходит, может сразу станет понятно
вы сообщаете ему что тип контента application/x-www-form-urlencoded и он ожидает контент типа Term=250&Rele=1&ID=1

Не подскажете , что не так и как проверить уходит и приходит ли запрос...
если получаете "Sent to the web OK." значит запрос отправлен и получен ответ, правда совсем не понятно для чего вы это выводите на печать, чем не устроила печать кода ответа и данных ответа из примера не ясно, видимо так задумано :)
 

newnew

New member
newnew,
как то не понятно вы строите в запросе body
'Term='..cf['var2']..'&Rele='..cf['var3']..'&ID='..cf['var1']

пых-пых пытается найти не пустой ID и не находит, посмотрите на сервере что в запросе приходит, может сразу станет понятно
вы сообщаете ему что тип контента application/x-www-form-urlencoded и он ожидает контент типа Term=250&Rele=1&ID=1


если получаете "Sent to the web OK." значит запрос отправлен и получен ответ, правда совсем не понятно для чего вы это выводите на печать, чем не устроила печать кода ответа и данных ответа из примера не ясно, видимо так задумано :)
День добрый Алексей!
Спасибо за ответ.
На самом деле конструкция 'Term='..cf['var2']..'&Rele='..cf['var3']..'&ID='..cf['var1'] и есть в результате
Term=250&Rele=1&ID=1...
Использую YANDEX браузер, средства разработчика. Не вижу обмена с моим IP. В том то и дело.
Скрипт на страничке сайта работает. Принимает запросы из строки браузера вида http://mysite.ru/test.php?ID=1 . Уверенно печатает 1. Остаётся понять с кем обменивается POST запросом ESP шка...
 

Алексей.

Active member
Принимает запросы из строки браузера вида http://mysite.ru/test.php?ID=1 . Уверенно печатает 1
если уверенно печатает 1 то пых-пых этот ID берет из урла, а есп обменивается с тем же http://mysite.ru больше не с кем.
Можете попробовать на есп передать ID в урле.
 

newnew

New member
если уверенно печатает 1 то пых-пых этот ID берет из урла, а есп обменивается с тем же http://mysite.ru больше не с кем.
Можете попробовать на есп передать ID в урле.[/QU

Приветствую ещё раз!
Получил текст ответа от сервера... В ESPlorer.(Благодаря Вашей подсказке использовать код из примера..).
Ошибка 403....
Попробую разобраться с техподдержкой сайта.
Интересно, почему инструменты разработчика в браузере не выводят ответ сервера..
 

Алексей.

Active member
Серверу, который заворачивает запросы на пых-пых, похоже не нравится в запросе заголовок User-Agent, и он говорит 403 - типа вам туда нельзя, а у броузера User-Agent типа "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
 

newnew

New member
Серверу, который заворачивает запросы на пых-пых, похоже не нравится в запросе заголовок User-Agent, и он говорит 403 - типа вам туда нельзя, а у броузера User-Agent типа "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
Приветствую!
С сервером разобрались, тех поддержка сняла какие-то ограничения...В общем тупо предложили перейти на платный хостинг..(beget.tech).
Теперь ответ в ESPlorer :
200 12501�мя: Term Сообщение: 250 �мя: Rele Сообщение: 1 �мя: ID Сообщение: 1
http://mysite.ru/test.php/
Главное, как я понимаю, число 200 в начале строки. С абракадаброй разберусь позже.
Всё же остался главный вопрос- как извлечь данные из запроса..
Скрипт PHP по прежyему выдаёт MISTAKE. Массив $_POST[] по прежнему пустой..
 

Алексей.

Active member
newnew,
Вы бы локально сначала проверили бы, а потом и с хостером отношения выясняли.
На локальный сервер запросы бы по отправляли и посмотрели бы чем отличаются
Я стараюсь не пользоваться для отправки простых запросов всякими там инструментами, достаточно командной строки.
Bash:
#!/bin/bash
exec 7<>/dev/tcp/mysite.ru/80
echo -e "POST /test.php HTTP/1.1\r\nHost: mysite.ru\r\nContent-Type: application/x-www-form-urlencoded\r\nCache-Control: no-cache\r\nConnection: Close\r\nContent-Length: 20\r\n\r\nTerm=250&Rele=1&ID=1" >&7
cat <&7
отправил запрос скриптом и получил адекватный ответ
HTML:
HTTP/1.1 200 OK
Date: Thu, 19 Apr 2018 09:28:54 GMT
Server: Apache/2.4.18 (Ubuntu)
Content-Length: 1
Connection: close
Content-Type: text/html; charset=UTF-8

1
 

newnew

New member
newnew,
Вы бы локально сначала проверили бы, а потом и с хостером отношения выясняли.
На локальный сервер запросы бы по отправляли и посмотрели бы чем отличаются
Я стараюсь не пользоваться для отправки простых запросов всякими там инструментами, достаточно командной строки.
Bash:
#!/bin/bash
exec 7<>/dev/tcp/mysite.ru/80
echo -e "POST /test.php HTTP/1.1\r\nHost: mysite.ru\r\nContent-Type: application/x-www-form-urlencoded\r\nCache-Control: no-cache\r\nConnection: Close\r\nContent-Length: 20\r\n\r\nTerm=250&Rele=1&ID=1" >&7
cat <&7
отправил запрос скриптом и получил адекватный ответ
HTML:
HTTP/1.1 200 OK
Date: Thu, 19 Apr 2018 09:28:54 GMT
Server: Apache/2.4.18 (Ubuntu)
Content-Length: 1
Connection: close
Content-Type: text/html; charset=UTF-8

1
Приветствую!
Спасибо за ответы и советы!
Вроде процесс пошёл. Просто первый проект с web...
бывает, что упрёшься во что нибудь и не видишь очевидных вещей...
Ну и пунктик-чё то никак к С душа не лежит.. В своё время ассемблером в основном пользовался.
Может(наверное точно) с С было бы проще..
Не возражаете, если в стену упрусь попрошу совета?
 

pvvx

Активный участник сообщества
Вот какой запрос был отправлен на сервер
Код:
POST /auth/esp/register HTTP/1.1
Host: 192.168.4.1
User-Agent: ESP32HTTPClient
Connection: close
Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0
Content-Type: application/json
Content-Length: 40

{"ESPIdentifier": "000:123:265:312:484"}
А где символы от 'chunked' и как совокупляются 'Content-Length: 40', 'chunked' и chunked + GZIP On по умолчанию у HTTP/1.1?
Специализированно заточенным сервером, адаптированным под данный неверный запрос?

C 'chunked' серверу ещё как-то понятно, т.к. правило гласит последовательный разбор директив, а последняя там 'Content-Length: 40', которая отменяет 'chunked'. Ответ придет загадочный – должен быть сжат GZIP или с 'chunked', т.к. указан HTTP/1.1.
Ответ ТС и получил в виде "абракадабры" :)
 
Последнее редактирование:
Сверху Снизу