#include #include #include #include // WEB HANDLER IMPLEMENTATION class SPIFFSEditor: public AsyncWebHandler { private: String _username; String _password; bool _uploadAuthenticated; public: SPIFFSEditor(String username=String(), String password=String()):_username(username),_password(password),_uploadAuthenticated(false){} bool canHandle(AsyncWebServerRequest *request){ if(request->method() == HTTP_GET && request->url() == "/edit" && (SPIFFS.exists("/edit.htm") || SPIFFS.exists("/edit.htm.gz"))) return true; else if(request->method() == HTTP_GET && request->url() == "/list") return true; else if(request->method() == HTTP_GET && (request->url().endsWith("/") || SPIFFS.exists(request->url()) || (!request->hasParam("download") && SPIFFS.exists(request->url()+".gz")))) return true; else if(request->method() == HTTP_POST && request->url() == "/edit") return true; else if(request->method() == HTTP_DELETE && request->url() == "/edit") return true; else if(request->method() == HTTP_PUT && request->url() == "/edit") return true; return false; } void handleRequest(AsyncWebServerRequest *request){ if(_username.length() && (request->method() != HTTP_GET || request->url() == "/edit" || request->url() == "/list") && !request->authenticate(_username.c_str(),_password.c_str())) return request->requestAuthentication(); if(request->method() == HTTP_GET && request->url() == "/edit"){ request->send(SPIFFS, "/edit.htm"); } else if(request->method() == HTTP_GET && request->url() == "/list"){ if(request->hasParam("dir")){ String path = request->getParam("dir")->value(); Dir dir = SPIFFS.openDir(path); path = String(); String output = "["; while(dir.next()){ File entry = dir.openFile("r"); if (output != "[") output += ','; bool isDir = false; output += "{\"type\":\""; output += (isDir)?"dir":"file"; output += "\",\"name\":\""; output += String(entry.name()).substring(1); output += "\"}"; entry.close(); } output += "]"; request->send(200, "text/json", output); output = String(); } else request->send(400); } else if(request->method() == HTTP_GET){ String path = request->url(); if(path.endsWith("/")) path += "index.htm"; request->send(SPIFFS, path, String(), request->hasParam("download")); } else if(request->method() == HTTP_DELETE){ if(request->hasParam("path", true)){ SPIFFS.remove(request->getParam("path", true)->value()); request->send(200, "", "DELETE: "+request->getParam("path", true)->value()); } else request->send(404); } else if(request->method() == HTTP_POST){ if(request->hasParam("data", true, true) && SPIFFS.exists(request->getParam("data", true, true)->value())) request->send(200, "", "UPLOADED: "+request->getParam("data", true, true)->value()); else request->send(500); } else if(request->method() == HTTP_PUT){ if(request->hasParam("path", true)){ String filename = request->getParam("path", true)->value(); if(SPIFFS.exists(filename)){ request->send(200); } else { File f = SPIFFS.open(filename, "w"); if(f){ f.write(0x00); f.close(); request->send(200, "", "CREATE: "+filename); } else { request->send(500); } } } else request->send(400); } } void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ if(!index){ if(!_username.length() || request->authenticate(_username.c_str(),_password.c_str())) _uploadAuthenticated = true; request->_tempFile = SPIFFS.open(filename, "w"); } if(_uploadAuthenticated && request->_tempFile && len){ request->_tempFile.write(data,len); } if(_uploadAuthenticated && final) if(request->_tempFile) request->_tempFile.close(); } }; // SKETCH BEGIN AsyncWebServer server(80); AsyncWebSocket ws("/ws"); void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ if(type == WS_EVT_CONNECT){ os_printf("ws[%s][%u] connect\n", server->url(), client->id()); client->printf("Hello Client %u :)", client->id()); client->ping(); } else if(type == WS_EVT_DISCONNECT){ os_printf("ws[%s][%u] disconnect: %u\n", server->url(), client->id()); } else if(type == WS_EVT_ERROR){ os_printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); } else if(type == WS_EVT_PONG){ os_printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:""); } else if(type == WS_EVT_DATA){ AwsFrameInfo * info = (AwsFrameInfo*)arg; if(info->final && info->index == 0 && info->len == len){ //the whole message is in a single frame and we got all of it's data os_printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len); if(info->opcode == WS_TEXT){ data[len] = 0; os_printf("%s\n", (char*)data); } else { for(size_t i=0; i < info->len; i++){ os_printf("%02x ", data[i]); } os_printf("\n"); } if(info->opcode == WS_TEXT) client->text("I got your text message"); else client->binary("I got your binary message"); } else { //message is comprised of multiple frames or the frame is split into multiple packets if(info->index == 0){ if(info->num == 0) os_printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); os_printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); } os_printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len); if(info->message_opcode == WS_TEXT){ data[len] = 0; os_printf("%s\n", (char*)data); } else { for(size_t i=0; i < len; i++){ os_printf("%02x ", data[i]); } os_printf("\n"); } if((info->index + len) == info->len){ os_printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); if(info->final){ os_printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); if(info->message_opcode == WS_TEXT) client->text("I got your text message"); else client->binary("I got your binary message"); } } } } } const char* ssid = "**********"; const char* password = "************"; const char* http_username = "admin"; const char* http_password = "admin"; void setup(){ Serial.begin(115200); Serial.setDebugOutput(true); SPIFFS.begin(); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); if(WiFi.waitForConnectResult() != WL_CONNECTED){ Serial.printf("WiFi Failed!\n"); } ws.onEvent(onEvent); server.addHandler(&ws); server.serveStatic("/fs", SPIFFS, "/"); server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(200, "text/plain", String(ESP.getFreeHeap())); }); server.addHandler(new SPIFFSEditor(http_username,http_password)); server.onNotFound([](AsyncWebServerRequest *request){ os_printf("NOT_FOUND: "); if(request->method() == HTTP_GET) os_printf("GET"); else if(request->method() == HTTP_POST) os_printf("POST"); else if(request->method() == HTTP_DELETE) os_printf("DELETE"); else if(request->method() == HTTP_PUT) os_printf("PUT"); else if(request->method() == HTTP_PATCH) os_printf("PATCH"); else if(request->method() == HTTP_HEAD) os_printf("HEAD"); else if(request->method() == HTTP_OPTIONS) os_printf("OPTIONS"); else os_printf("UNKNOWN"); os_printf(" http://%s%s\n", request->host().c_str(), request->url().c_str()); if(request->contentLength()){ os_printf("_CONTENT_TYPE: %s\n", request->contentType().c_str()); os_printf("_CONTENT_LENGTH: %u\n", request->contentLength()); } int headers = request->headers(); int i; for(i=0;igetHeader(i); os_printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); } int params = request->params(); for(i=0;igetParam(i); if(p->isFile()){ os_printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); } else if(p->isPost()){ os_printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); } else { os_printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); } } request->send(404); }); server.onFileUpload([](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ if(!index) os_printf("UploadStart: %s\n", filename.c_str()); os_printf("%s", (const char*)data); if(final) os_printf("UploadEnd: %s (%u)\n", filename.c_str(), index+len); }); server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ if(!index) os_printf("BodyStart: %u\n", total); os_printf("%s", (const char*)data); if(index + len == total) os_printf("BodyEnd: %u\n", total); }); server.begin(); } void loop(){}