解析Arduino上传入HTTP帖子请求的最佳方式



我正在我的Arduino Uno Wifi Rev2上编写一个简单的HTTP Web服务器,以处理JSON格式的传入HTTP POST请求。

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

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

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

POST /myEndpoint HTTP/1.1rnHost: 192.168.4.1rnUser-Agent: curl/7.54.0rnAccept: */*rnContent-Type: application/jsonrnContent-Length: 34rnrn{n    "A": "B",n    "C": "D"    n}

我使用Nick Gammon的Arduino Regexp库来解析这个请求,验证它并提取JSON数据。

这是可行的,但以这种方式解析HTTP请求是非常脆弱的,而且感觉很粗糙。如果另一个客户端重新订购/省略标头或跳过回车字符,它可能很容易中断。这是我用来验证的糟糕透顶的正则表达式:

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请求?这一定是其他人已经遇到并解决的问题。如果可能的话,请发布一个解决这个问题的代码片段。

作为启动程序:
首先发送正确的(语法!(测试请求

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

如果你搜索,有很多优秀的例子

arduino网络服务器以太网库

在你最喜欢的搜索引擎上
其中之一是:https://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/
或者你使用esp8266中的Web服务器库并对其进行调整(不是很难(
你会在Arduino上做一些类似于
的事情

webServer.on("/myroute/lighton", HTTP_POST, readJson);
char jsonField[64] = ''; //This is a predefined buffer for data handilng

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

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] = '';
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 Web服务器场景中使用Arduino String类。String类会断开你的堆并崩溃你的Arduino。在我的例子中,我使用了固定的字符,这些字符被编译到堆栈中,让你的内存保持愉快。

链接的Regexp库基于Lua,它有一个有趣的模式匹配操作符

%b((平衡嵌套对(…(…(…(

然后,要在HTTP请求的末尾捕获一个平衡的大括号表达式,请使用表达式

"(%b{})%s*$"

正如评论中所指出的,这并不意味着捕获是有效的JSON。下一步是将捕获的子字符串传递给JSON解析器进行验证。

最新更新