在Arduino上解析传入的HTTP发布请求的最佳方法? [英] Best way to parse out incoming HTTP post request on Arduino?
问题描述
我正在
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屋!