在Arduino上解析传入的HTTP发布请求的最佳方法? [英] Best way to parse out incoming HTTP post request on Arduino?

查看:125
本文介绍了在Arduino上解析传入的HTTP发布请求的最佳方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 Arduino Uno Wifi Rev2 处理JSON格式的传入HTTP POST请求.

I'm writing a simple HTTP webserver on my Arduino Uno Wifi Rev2 to handle an incoming HTTP POST Request in JSON format.

这是我从客户端发送HTTP请求(带有JSON)的方式:

This is how I'm sending the HTTP request (with JSON) from my client:

curl \
--request POST \
--header "Content-Type: application/json" \
--data '{
    "A": "B",
    "C": "D"    
}' \
"http://192.168.4.1/myEndpoint"

这是Arduino网络服务器收到的字符串:

This is the string the Arduino web-server receives:

POST /myEndpoint HTTP/1.1\r\nHost: 192.168.4.1\r\nUser-Agent: curl/7.54.0\r\nAccept: */*\r\nContent-Type: application/json\r\nContent-Length: 34\r\n\r\n{\n    "A": "B",\n    "C": "D"    \n}

我正在使用 Nick Gammon的Arduino Regexp库来解析此请求,对其进行验证并提取JSON数据.

I'm using Nick Gammon's Arduino Regexp library to parse this request, validate it and extract the JSON data.

这是可行的,但是以这种方式解析HTTP请求非常脆弱并且让人感觉很hack.如果其他客户端重新排序/省略标题或跳过回车符,则很容易中断.这是我用来验证的令人讨厌的regexp:

This works, but parsing the HTTP request in this way is extremely brittle and feels hacky. It could easily break if a different client re-orders/omits a header or skips the carriage return characters. This is the god-awful regexp I'm using for validation:

    httpRegexp = "POST /myEndpoint HTTP/[%d%.]+%\r%\nHost: 192%.168%.4%.1%\r%\nUser%-Agent: curl/[%d%.]+%\r%\nAccept: %*/%*%\r%\nContent%-Type: application/json%\r%\nContent%-Length: %d+%\r%\n%\r%\n{%s*\"[A-Za-z]+\"%s*:%s*\".+\"%s*,%s*\"[A-Za-z]+\"%s*:%s*\".+\"%s*}";

我是否有更好/建议的方式来验证和解析HTTP请求?这一定是其他人已经遇到并解决的问题.如果可能,请发布解决此问题的代码片段.

Is there a better/recommended way for me to validate and parse the HTTP request? This must be a problem that others have already encountered and solved. Please post a code fragment solving this issue if possible.

推荐答案

入门:
首先发送正确的(语法!)测试请求

As a starter:
First send a correct (syntax!) test request

curl \
 request POST \
header "Content-Type:application/json" \
data '{"A":"B","C":"D"}' \
"http://192.168.4.1/myEndpoint"

如果您进行以下搜索,就有很多优秀的例子:

there are tons of excellent examples if you do a search for :

arduino Web服务器以太网库

arduino webserver ethernet library

在您最喜欢的搜索引擎上.
一个是: https://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/
或者您使用esp8266的网络服务器库并对其进行改编(不是很难的恕我直言)
您将在Arduino上执行类似

on your favorite search enginne.
One would be: https://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/
or you use the webserver library from esp8266 and adapt it (not really hard imho)
you would do on the Arduino something like

webServer.on("/myroute/lighton", HTTP_POST, readJson);

char jsonField[64] = '\0'; //This is a predefined buffer for data handilng

函数看起来像(部分工作代码,部分伪代码)

the function would look like (partly working code, partly pseudo code )

bool readJson(){
 if (webserver.args() == 0) return false;  // we could do in the caller an error handling on that
 strcpy (jsonField, webserver.arg(1).c_str());  // here we copy the json to a buffer

 /** Get rid of starting and finishing bracket and copy to */
   strncpy(jsonField , jsonField + 1, strlen(jsonField) - 2);
  jsonField[strlen(jsonField) - 2] = '\0';
   uint16_t maxIndex = strlen(jsonField); // number of characters received - without the brackets
     uint16_t index = 0;
  int16_t nextIndex = 0;
  uint8_t  i = 0;
  // In this routine we get the value pairs e.g. "A":"B"
  while ((nextIndex != -1) && (nextIndex < maxIndex)) {
    nextIndex = indexOf(jsonField, ',', index);

    ... the next step would be to process the value pairs by stripping the " and split on the ':' delimiter --
    if you need just the values = content in your example B and D its easy, 
    you could do 
    if (strcmp (firstValofPair ,'A')==0) valueB = atoi(B); // given B is a number and we have to convert from char to int

    .... some more logic and you have a simple reliable JSON Parser for all kind of web server usage

  }
 return true; // success parsing
}

我已经在某些实际场景中实现了这种逻辑,并且几年来所有这些工作都可靠,稳定地工作.最后提示:
切勿在Arduino网络服务器场景中使用Arduino String类.String类会破坏您的堆并使Arduino崩溃.在我的示例中,我使用固定字符,这些字符会被编译到堆栈中,并保持内存愉快.

I have implemented this kind of logic in some real live scenarios and all work reliable and stable for some years now. A final tip:
Never use the Arduino String class in Arduino webserver scenarios. The String class fractures your heap and crashes your Arduino. In my example I use fixed chars which are compiled to the stack and keeps your memory happy.

这篇关于在Arduino上解析传入的HTTP发布请求的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆