我正在我的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解析器进行验证。