托管网站加载 <body> 中的错误不在代码中
Hosted Website loads with errors in <body> that are not in the code
阿霍伊,
我正在用我的“Olimex ESP-32 POE”托管一个小型 debug-website。目标是通过 JSON 发送一些内部数据,而不必使用 Arduino IDE 的 Serial-Output(背后的原因无关紧要)。
#include "Arduino.h"
#include <WiFiClient.h>
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
#include <string>
const char* ssid = "SSID";
const char* password = "password";
int looper = 0;
int looperSpeed = 0;
int looperMode = 0;
int looperDestination = 0;
int looperETC = 0;
WebServer webserver(80);
void initWebServer();
void getSettings() {
String response = "{";
response+= "\"speed\": \""+(String) looperSpeed+"\"";
response+= ",\"mode\": \""+(String) looperMode+"\"";
response+= ",\"dest\": \""+(String) looperDestination+"\"";
response+= ",\"etc\": \""+(String) looperETC+"\"";
if (webserver.arg("signalStrength")== "true"){
response+= ",\"signalStrengh\": \""+String(WiFi.RSSI())+"\"";
}
response+="}";
webserver.send(200, "text/json", response);
}
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += webserver.uri();
message += "\nMethod: ";
message += (webserver.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += webserver.args();
message += "\n";
for (uint8_t i = 0; i < webserver.args(); i++) {
message += " " + webserver.argName(i) + ": " + webserver.arg(i) + "\n";
}
webserver.send(404, "text/plain", message);
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
initWebServer();
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Set not found response
webserver.onNotFound(handleNotFound);
// Start server
webserver.begin();
Serial.println("HTTP server started");
}
void loop() {
webserver.handleClient();
//Some test values are changed here periodically (looperXYZ)
}
}
以及创建网站的部分:
std::string online_output = "Test";
const char* serverIndex() {
const char* o = online_output.c_str();
const char* r =
(std::string("") +
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>" +
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>" +
"<input type='file' name='update'>" +
"<input type='submit' value='Update'>" +
"</form>" +
"<div id='prg'>Progress: 0%</div>" +
"<div id='output' style=\"font-family: monospace; border: 1px solid black; width: 350px;min-height:398px;\">" +
"</div>" +
"<script>" +
"var id = 0;" +
"var removeId = 0;" +
"setInterval(function(){" +
/*"var xhReq = new XMLHttpRequest();" +
"xhReq.open('GET', '/JSON', false);" +
"xhReq.send(null);" +
"var jsonObject = JSON.parse(xhReq.responseText);" +*/
"var data = {};" +
"$.ajax({" +
"type: 'GET'," +
"url: '/JSON'," +
"data: data," +
"async: true," +
"beforeSend: function (xhr) {" +
"if (xhr && xhr.overrideMimeType) {" +
"xhr.overrideMimeType('application/json;charset=utf-8');" +
"}" +
"}," +
"dataType: 'json'," +
"success: function (data) {" +
"document.getElementById('output').innerHTML = \"<p id=\" + id + \" style='margin:0;padding:0px;'>\" + \"Mode: \" + fill(data.mode,2) + \" | Speed: \" + fill(data.speed,4) + \" | Dest: \" + fill(data.dest,4) + \" | ETC: \" + fill(data.etc,5) + \"</p>\" + document.getElementById('output').innerHTML;" +
// "if (document.getElementById('output').offsetHeight > 400) document.getElementById('output').innerHTML = \"<p style='margin:0;padding:0px;'>\" + data.name + \"</p>\";" +
"if (document.getElementById('output').offsetHeight > 400) { document.getElementById(removeId).remove(); removeId++;}" +
"id++;" +
"console.log(data);" +
"}" +
"});" +
"}, 50);" +
"function fill(n,m) { " +
"var pre=\"\";" +
"var dec=10;" +
"for(var i=1;i<m;i++) { if(n<dec) { pre+=\".\"; } dec*=10; }" +
"pre = pre + n;" +
"return pre; }" +
"$('form').submit(function(e){" +
"e.preventDefault();" +
"var form = $('#upload_form')[0];" +
"var data = new FormData(form);" +
" $.ajax({" +
"url: '/update'," +
"type: 'POST'," +
"data: data," +
"contentType: false," +
"processData:false," +
"xhr: function() {" +
"var xhr = new window.XMLHttpRequest();" +
"xhr.upload.addEventListener('progress', function(evt) {" +
"if (evt.lengthComputable) {" +
"var per = evt.loaded / evt.total;" +
"$('#prg').html('progress: ' + Math.round(per*100) + '%');" +
"}" +
"}, false);" +
"return xhr;" +
"}," +
"success:function(d, s) {" +
"console.log('success!')" +
"}," +
"error: function (a, b, c) {" +
"}" +
"});" +
"});" +
"</script>").c_str();
return r;
}
const char* host = "esp32";
void initWebServer() {
if (!MDNS.begin(host)) { //http://esp32.local
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
/*return index page which is stored in serverIndex */
webserver.on("/", HTTP_GET, []() {
webserver.sendHeader("Connection", "close");
webserver.send(200, "text/html", serverIndex());
});
webserver.on("/JSON", HTTP_GET, []() {
getSettings();
});
/*handling uploading firmware file */
webserver.on("/update", HTTP_POST, []() {
webserver.sendHeader("Connection", "close");
webserver.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& upload = webserver.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
}
});
webserver.begin();
}
这是测试代码,因此之前的测试可能有 left-overs - 仅供参考。
加载网站时(目前我正在使用 Chrome)有时它可以工作,有时什么也没有加载(这个网站不工作,然后是一个空页面)有时我得到如下结果:xVºùÿý?øÿý?;">
这是屏幕上唯一的输出。
详细显示如下:
<html><head></head><body>xV­ºùÿý?øÿý?;"><script>var id = 0; [...the rest of the <script> part is loaded properly...]
我刚刚注意到在这些奇怪的字符前面有 364 个中心点 (·) 但我实际上无法复制它们,除了 Chrome->Inspect->"Sources"- 没有编辑器显示它们选项卡
所以基本上body坏了,出现了这些字符,目前也没有改变。
有人可以指出我自己解决这个问题的方向,以便网站始终正确加载或知道错误是什么吗?
错误似乎在以下行:
const char* r = (std::string("") + “...”).c_str();
您正在创建 std::string
,它在堆上分配原始 C 字符串。然后,您将获得带有 .c_str()
的字符串的 c 表示形式。问题是字符串被释放,因为您没有将字符串分配给 std::string
类型的变量。结果,您正在访问不属于您的内存。当它的内存还没有被重用时,它工作了,但是想要被另一个程序重用,它失败了,因为你从内存中得到了基本上随机的字节。
您可以通过添加以下内容来解决问题:
auto my_str = std::string("") + “...”;
因为你不需要原始指针。
对于服务器索引函数,它应该是这样的:
std::string serverIndex() {
对于您的初始化网络服务器功能:
webserver.on("/", HTTP_GET, []() {
webserver.sendHeader("Connection", "close");
auto r = serverIndex();
webserver.send(200, "text/html", r.c_str());
});
免责声明:此代码未经过测试,因为它仅在应用程序中编写。
阿霍伊,
我正在用我的“Olimex ESP-32 POE”托管一个小型 debug-website。目标是通过 JSON 发送一些内部数据,而不必使用 Arduino IDE 的 Serial-Output(背后的原因无关紧要)。
#include "Arduino.h"
#include <WiFiClient.h>
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
#include <string>
const char* ssid = "SSID";
const char* password = "password";
int looper = 0;
int looperSpeed = 0;
int looperMode = 0;
int looperDestination = 0;
int looperETC = 0;
WebServer webserver(80);
void initWebServer();
void getSettings() {
String response = "{";
response+= "\"speed\": \""+(String) looperSpeed+"\"";
response+= ",\"mode\": \""+(String) looperMode+"\"";
response+= ",\"dest\": \""+(String) looperDestination+"\"";
response+= ",\"etc\": \""+(String) looperETC+"\"";
if (webserver.arg("signalStrength")== "true"){
response+= ",\"signalStrengh\": \""+String(WiFi.RSSI())+"\"";
}
response+="}";
webserver.send(200, "text/json", response);
}
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += webserver.uri();
message += "\nMethod: ";
message += (webserver.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += webserver.args();
message += "\n";
for (uint8_t i = 0; i < webserver.args(); i++) {
message += " " + webserver.argName(i) + ": " + webserver.arg(i) + "\n";
}
webserver.send(404, "text/plain", message);
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
initWebServer();
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Set not found response
webserver.onNotFound(handleNotFound);
// Start server
webserver.begin();
Serial.println("HTTP server started");
}
void loop() {
webserver.handleClient();
//Some test values are changed here periodically (looperXYZ)
}
}
以及创建网站的部分:
std::string online_output = "Test";
const char* serverIndex() {
const char* o = online_output.c_str();
const char* r =
(std::string("") +
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>" +
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>" +
"<input type='file' name='update'>" +
"<input type='submit' value='Update'>" +
"</form>" +
"<div id='prg'>Progress: 0%</div>" +
"<div id='output' style=\"font-family: monospace; border: 1px solid black; width: 350px;min-height:398px;\">" +
"</div>" +
"<script>" +
"var id = 0;" +
"var removeId = 0;" +
"setInterval(function(){" +
/*"var xhReq = new XMLHttpRequest();" +
"xhReq.open('GET', '/JSON', false);" +
"xhReq.send(null);" +
"var jsonObject = JSON.parse(xhReq.responseText);" +*/
"var data = {};" +
"$.ajax({" +
"type: 'GET'," +
"url: '/JSON'," +
"data: data," +
"async: true," +
"beforeSend: function (xhr) {" +
"if (xhr && xhr.overrideMimeType) {" +
"xhr.overrideMimeType('application/json;charset=utf-8');" +
"}" +
"}," +
"dataType: 'json'," +
"success: function (data) {" +
"document.getElementById('output').innerHTML = \"<p id=\" + id + \" style='margin:0;padding:0px;'>\" + \"Mode: \" + fill(data.mode,2) + \" | Speed: \" + fill(data.speed,4) + \" | Dest: \" + fill(data.dest,4) + \" | ETC: \" + fill(data.etc,5) + \"</p>\" + document.getElementById('output').innerHTML;" +
// "if (document.getElementById('output').offsetHeight > 400) document.getElementById('output').innerHTML = \"<p style='margin:0;padding:0px;'>\" + data.name + \"</p>\";" +
"if (document.getElementById('output').offsetHeight > 400) { document.getElementById(removeId).remove(); removeId++;}" +
"id++;" +
"console.log(data);" +
"}" +
"});" +
"}, 50);" +
"function fill(n,m) { " +
"var pre=\"\";" +
"var dec=10;" +
"for(var i=1;i<m;i++) { if(n<dec) { pre+=\".\"; } dec*=10; }" +
"pre = pre + n;" +
"return pre; }" +
"$('form').submit(function(e){" +
"e.preventDefault();" +
"var form = $('#upload_form')[0];" +
"var data = new FormData(form);" +
" $.ajax({" +
"url: '/update'," +
"type: 'POST'," +
"data: data," +
"contentType: false," +
"processData:false," +
"xhr: function() {" +
"var xhr = new window.XMLHttpRequest();" +
"xhr.upload.addEventListener('progress', function(evt) {" +
"if (evt.lengthComputable) {" +
"var per = evt.loaded / evt.total;" +
"$('#prg').html('progress: ' + Math.round(per*100) + '%');" +
"}" +
"}, false);" +
"return xhr;" +
"}," +
"success:function(d, s) {" +
"console.log('success!')" +
"}," +
"error: function (a, b, c) {" +
"}" +
"});" +
"});" +
"</script>").c_str();
return r;
}
const char* host = "esp32";
void initWebServer() {
if (!MDNS.begin(host)) { //http://esp32.local
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
/*return index page which is stored in serverIndex */
webserver.on("/", HTTP_GET, []() {
webserver.sendHeader("Connection", "close");
webserver.send(200, "text/html", serverIndex());
});
webserver.on("/JSON", HTTP_GET, []() {
getSettings();
});
/*handling uploading firmware file */
webserver.on("/update", HTTP_POST, []() {
webserver.sendHeader("Connection", "close");
webserver.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& upload = webserver.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
}
});
webserver.begin();
}
这是测试代码,因此之前的测试可能有 left-overs - 仅供参考。
加载网站时(目前我正在使用 Chrome)有时它可以工作,有时什么也没有加载(这个网站不工作,然后是一个空页面)有时我得到如下结果:xVºùÿý?øÿý?;">
这是屏幕上唯一的输出。
详细显示如下:
<html><head></head><body>xV­ºùÿý?øÿý?;"><script>var id = 0; [...the rest of the <script> part is loaded properly...]
我刚刚注意到在这些奇怪的字符前面有 364 个中心点 (·) 但我实际上无法复制它们,除了 Chrome->Inspect->"Sources"- 没有编辑器显示它们选项卡
所以基本上body坏了,出现了这些字符,目前也没有改变。
有人可以指出我自己解决这个问题的方向,以便网站始终正确加载或知道错误是什么吗?
错误似乎在以下行:
const char* r = (std::string("") + “...”).c_str();
您正在创建 std::string
,它在堆上分配原始 C 字符串。然后,您将获得带有 .c_str()
的字符串的 c 表示形式。问题是字符串被释放,因为您没有将字符串分配给 std::string
类型的变量。结果,您正在访问不属于您的内存。当它的内存还没有被重用时,它工作了,但是想要被另一个程序重用,它失败了,因为你从内存中得到了基本上随机的字节。
您可以通过添加以下内容来解决问题:
auto my_str = std::string("") + “...”;
因为你不需要原始指针。
对于服务器索引函数,它应该是这样的:
std::string serverIndex() {
对于您的初始化网络服务器功能:
webserver.on("/", HTTP_GET, []() {
webserver.sendHeader("Connection", "close");
auto r = serverIndex();
webserver.send(200, "text/html", r.c_str());
});
免责声明:此代码未经过测试,因为它仅在应用程序中编写。