mirror of https://github.com/arendst/Tasmota.git
Ufs serve fix - makes it work better on esp32cam (ai thinker style) (#21486)
* Add yield() in file listing, so watchdog does not trigger with very large folders * update UFSServe function to be like download function. This removes the use of server.streamFile, and provides a much more reliable download. Make UFSServe always use this function, regardless of auth requirement. (i.e. no use of the original in the original class, as it still uses streaming.) Note that UFSServe is enab;ed with #define UFILESYS_STATIC_SERVING
This commit is contained in:
parent
e5521bb763
commit
3e0b70af10
|
@ -889,15 +889,20 @@ void UFSRename(void) {
|
||||||
*/
|
*/
|
||||||
#include "detail/RequestHandlersImpl.h"
|
#include "detail/RequestHandlersImpl.h"
|
||||||
|
|
||||||
|
//#define SERVING_DEBUG
|
||||||
|
|
||||||
// class to allow us to request auth when required.
|
// class to allow us to request auth when required.
|
||||||
// StaticRequestHandler is in the above header
|
// StaticRequestHandler is in the above header
|
||||||
class StaticRequestHandlerAuth : public StaticRequestHandler {
|
class StaticRequestHandlerAuth : public StaticRequestHandler {
|
||||||
public:
|
public:
|
||||||
StaticRequestHandlerAuth(FS& fs, const char* path, const char* uri, const char* cache_header):
|
StaticRequestHandlerAuth(FS& fs, const char* path, const char* uri, const char* cache_header, bool requireAuth):
|
||||||
StaticRequestHandler(fs, path, uri, cache_header)
|
StaticRequestHandler(fs, path, uri, cache_header)
|
||||||
{
|
{
|
||||||
|
_requireAuth = requireAuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _requireAuth;
|
||||||
|
|
||||||
// we replace the handle method,
|
// we replace the handle method,
|
||||||
// and look for authentication only if we would serve the file.
|
// and look for authentication only if we would serve the file.
|
||||||
// if we check earlier, then we will reject as unauth even though a later
|
// if we check earlier, then we will reject as unauth even though a later
|
||||||
|
@ -906,8 +911,10 @@ public:
|
||||||
if (!canHandle(requestMethod, requestUri))
|
if (!canHandle(requestMethod, requestUri))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
log_v("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
|
//log_v("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
|
||||||
|
#ifdef SERVING_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handle: request=%s _uri=%s"), requestUri.c_str(), _uri.c_str());
|
||||||
|
#endif
|
||||||
String path(_path);
|
String path(_path);
|
||||||
|
|
||||||
if (!_isFile) {
|
if (!_isFile) {
|
||||||
|
@ -919,8 +926,9 @@ public:
|
||||||
// Append whatever follows this URI in request to get the file path.
|
// Append whatever follows this URI in request to get the file path.
|
||||||
path += requestUri.substring(_baseUriLength);
|
path += requestUri.substring(_baseUriLength);
|
||||||
}
|
}
|
||||||
log_v("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile);
|
#ifdef SERVING_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handle: path=%s, isFile=%d"), path.c_str(), _isFile);
|
||||||
|
#endif
|
||||||
String contentType = getContentType(path);
|
String contentType = getContentType(path);
|
||||||
|
|
||||||
// look for gz file, only if the original specified path is not a gz. So part only works to send gzip via content encoding when a non compressed is asked for
|
// look for gz file, only if the original specified path is not a gz. So part only works to send gzip via content encoding when a non compressed is asked for
|
||||||
|
@ -932,11 +940,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
File f = _fs.open(path, "r");
|
File f = _fs.open(path, "r");
|
||||||
if (!f || !f.available())
|
if (!f || !f.available()){
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler missing file?"));
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (!WebAuthenticate()) {
|
#ifdef SERVING_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler file open %d"), f.available());
|
||||||
|
#endif
|
||||||
|
if (_requireAuth && !WebAuthenticate()) {
|
||||||
|
#ifdef SERVING_DEBUG
|
||||||
AddLog(LOG_LEVEL_ERROR, PSTR("UFS: serv of %s denied"), requestUri.c_str());
|
AddLog(LOG_LEVEL_ERROR, PSTR("UFS: serv of %s denied"), requestUri.c_str());
|
||||||
|
#endif
|
||||||
server.requestAuthentication();
|
server.requestAuthentication();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -944,7 +958,45 @@ public:
|
||||||
if (_cache_header.length() != 0)
|
if (_cache_header.length() != 0)
|
||||||
server.sendHeader("Cache-Control", _cache_header);
|
server.sendHeader("Cache-Control", _cache_header);
|
||||||
|
|
||||||
server.streamFile(f, contentType);
|
#ifdef SERVING_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler sending"));
|
||||||
|
#endif
|
||||||
|
uint8_t buff[512];
|
||||||
|
uint32_t bread;
|
||||||
|
uint32_t flen = f.available();
|
||||||
|
WiFiClient download_Client = server.client();
|
||||||
|
server.setContentLength(flen);
|
||||||
|
server.send(200, contentType, "");
|
||||||
|
|
||||||
|
// transfer is about 150kb/s
|
||||||
|
uint32_t cnt = 0;
|
||||||
|
while (f.available()) {
|
||||||
|
bread = f.read(buff, sizeof(buff));
|
||||||
|
cnt += bread;
|
||||||
|
#ifdef SERVING_DEBUG
|
||||||
|
//AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler sending %d/%d"), cnt, flen);
|
||||||
|
#endif
|
||||||
|
uint32_t bw = download_Client.write((const char*)buff, bread);
|
||||||
|
if (!bw) { break; }
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
#ifdef SERVING_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler sent %d/%d"), cnt, flen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (cnt != flen){
|
||||||
|
AddLog(LOG_LEVEL_ERROR, PSTR("UFS: ::handler incomplete file send: sent %d/%d"), cnt, flen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It does seem that on lesser ESP32, this causes a problem? A lockup...
|
||||||
|
//server.streamFile(f, contentType);
|
||||||
|
|
||||||
|
f.close();
|
||||||
|
download_Client.stop();
|
||||||
|
|
||||||
|
#ifdef SERVING_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler done"));
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -959,9 +1011,9 @@ void UFSServe(void) {
|
||||||
if (Webserver) { // fail if no Webserver yet.
|
if (Webserver) { // fail if no Webserver yet.
|
||||||
StaticRequestHandlerAuth *staticHandler;
|
StaticRequestHandlerAuth *staticHandler;
|
||||||
if (noauth && *noauth == '1'){
|
if (noauth && *noauth == '1'){
|
||||||
staticHandler = (StaticRequestHandlerAuth *) new StaticRequestHandler(*ffsp, fpath, url, (char *)nullptr);
|
staticHandler = new StaticRequestHandlerAuth(*ffsp, fpath, url, (char *)nullptr, false);
|
||||||
} else {
|
} else {
|
||||||
staticHandler = new StaticRequestHandlerAuth(*ffsp, fpath, url, (char *)nullptr);
|
staticHandler = new StaticRequestHandlerAuth(*ffsp, fpath, url, (char *)nullptr, true);
|
||||||
}
|
}
|
||||||
if (staticHandler) {
|
if (staticHandler) {
|
||||||
//Webserver->serveStatic(url, *ffsp, fpath);
|
//Webserver->serveStatic(url, *ffsp, fpath);
|
||||||
|
@ -1319,6 +1371,8 @@ void UfsListDir(char *path, uint8_t depth) {
|
||||||
HtmlEscape(name).c_str(), tstr.c_str(), entry.size(), delpath, editpath);
|
HtmlEscape(name).c_str(), tstr.c_str(), entry.size(), delpath, editpath);
|
||||||
}
|
}
|
||||||
entry.close();
|
entry.close();
|
||||||
|
|
||||||
|
yield(); // trigger watchdog reset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dir.close();
|
dir.close();
|
||||||
|
|
Loading…
Reference in New Issue