| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -117,7 +117,7 @@ void setup() { | |||
| 117 | 117 | ResourceNode * nodeDirectory = new ResourceNode("/public", "GET", &handleDirectory); | |
| 118 | 118 | ResourceNode * nodeFile = new ResourceNode("/public/*", "GET", &handleFile); | |
| 119 | 119 | ||
| 120 | - // 404 node has no URL as it is used for all requests that don't match anything else | ||
| 120 | + // 404 node has no URL as it is used for all requests that don't match anything else | ||
| 121 | 121 | ResourceNode * node404 = new ResourceNode("", "GET", &handle404); | |
| 122 | 122 | ||
| 123 | 123 | // Add the root nodes to the server | |
@@ -135,182 +135,186 @@ void setup() { | |||
| 135 | 135 | Serial.println("Starting server..."); | |
| 136 | 136 | secureServer.start(); | |
| 137 | 137 | if (secureServer.isRunning()) { | |
| 138 | - Serial.println("Server ready."); | ||
| 138 | + Serial.println("Server ready."); | ||
| 139 | 139 | } | |
| 140 | 140 | } | |
| 141 | 141 | ||
| 142 | 142 | void loop() { | |
| 143 | - // This call will let the server do its work | ||
| 144 | - secureServer.loop(); | ||
| 143 | + // This call will let the server do its work | ||
| 144 | + secureServer.loop(); | ||
| 145 | 145 | ||
| 146 | - // Other code would go here... | ||
| 147 | - delay(1); | ||
| 146 | + // Other code would go here... | ||
| 147 | + delay(1); | ||
| 148 | 148 | } | |
| 149 | 149 | ||
| 150 | 150 | void handleRoot(HTTPRequest * req, HTTPResponse * res) { | |
| 151 | - // Status code is 200 OK by default. | ||
| 152 | - // We want to deliver a simple HTML page, so we send a corresponding content type: | ||
| 153 | - res->setHeader("Content-Type", "text/html"); | ||
| 154 | - | ||
| 155 | - // The response implements the Print interface, so you can use it just like | ||
| 156 | - // you would write to Serial etc. | ||
| 157 | - res->println("<!DOCTYPE html>"); | ||
| 158 | - res->println("<html>"); | ||
| 159 | - res->println("<head><title>Very simple file server</title></head>"); | ||
| 160 | - res->println("<body>"); | ||
| 161 | - res->println("<h1>Very simple file server</h1>"); | ||
| 162 | - res->println("<p>This is a very simple file server to demonstrate the use of POST forms. </p>"); | ||
| 163 | - res->println("<h2>List existing files</h2>"); | ||
| 164 | - res->println("<p>See <a href=\"/public\">/public</a> to list existing files and retrieve or edit them.</p>"); | ||
| 165 | - res->println("<h2>Upload new file</h2>"); | ||
| 166 | - res->println("<p>This form allows you to upload files (text, jpg and png supported best). It demonstrates multipart/form-data.</p>"); | ||
| 167 | - res->println("<form method=\"POST\" action=\"/upload\" enctype=\"multipart/form-data\">"); | ||
| 168 | - res->println("file: <input type=\"file\" name=\"file\"><br>"); | ||
| 169 | - res->println("<input type=\"submit\" value=\"Upload\">"); | ||
| 170 | - res->println("</form>"); | ||
| 171 | - res->println("</body>"); | ||
| 172 | - res->println("</html>"); | ||
| 151 | + // Status code is 200 OK by default. | ||
| 152 | + // We want to deliver a simple HTML page, so we send a corresponding content type: | ||
| 153 | + res->setHeader("Content-Type", "text/html"); | ||
| 154 | + | ||
| 155 | + // The response implements the Print interface, so you can use it just like | ||
| 156 | + // you would write to Serial etc. | ||
| 157 | + res->println("<!DOCTYPE html>"); | ||
| 158 | + res->println("<html>"); | ||
| 159 | + res->println("<head><title>Very simple file server</title></head>"); | ||
| 160 | + res->println("<body>"); | ||
| 161 | + res->println("<h1>Very simple file server</h1>"); | ||
| 162 | + res->println("<p>This is a very simple file server to demonstrate the use of POST forms. </p>"); | ||
| 163 | + res->println("<h2>List existing files</h2>"); | ||
| 164 | + res->println("<p>See <a href=\"/public\">/public</a> to list existing files and retrieve or edit them.</p>"); | ||
| 165 | + res->println("<h2>Upload new file</h2>"); | ||
| 166 | + res->println("<p>This form allows you to upload files (text, jpg and png supported best). It demonstrates multipart/form-data.</p>"); | ||
| 167 | + res->println("<form method=\"POST\" action=\"/upload\" enctype=\"multipart/form-data\">"); | ||
| 168 | + res->println("file: <input type=\"file\" name=\"file\"><br>"); | ||
| 169 | + res->println("<input type=\"submit\" value=\"Upload\">"); | ||
| 170 | + res->println("</form>"); | ||
| 171 | + res->println("</body>"); | ||
| 172 | + res->println("</html>"); | ||
| 173 | 173 | } | |
| 174 | 174 | ||
| 175 | 175 | void handleFormUpload(HTTPRequest * req, HTTPResponse * res) { | |
| 176 | - // First, we need to check the encoding of the form that we have received. | ||
| 177 | - // The browser will set the Content-Type request header, so we can use it for that purpose. | ||
| 178 | - // Then we select the body parser based on the encoding. | ||
| 179 | - // Actually we do this only for documentary purposes, we know the form is going | ||
| 180 | - // to be multipart/form-data. | ||
| 181 | - HTTPBodyParser *parser; | ||
| 182 | - std::string contentType = req->getHeader("Content-Type"); | ||
| 183 | - size_t semicolonPos = contentType.find(";"); | ||
| 184 | - if (semicolonPos != std::string::npos) contentType = contentType.substr(0, semicolonPos); | ||
| 185 | - if (contentType == "multipart/form-data") { | ||
| 186 | - parser = new HTTPMultipartBodyParser(req); | ||
| 187 | - } else { | ||
| 188 | - Serial.printf("Unknown POST Content-Type: %s\n", contentType.c_str()); | ||
| 189 | - return; | ||
| 190 | - } | ||
| 191 | - // We iterate over the fields. Any field with a filename is uploaded | ||
| 192 | - res->println("<html><head><title>File Upload</title></head><body><h1>File Upload</h1>"); | ||
| 193 | - bool didwrite = false; | ||
| 194 | - while(parser->nextField()) { | ||
| 195 | - std::string name = parser->getFieldName(); | ||
| 196 | - std::string filename = parser->getFieldFilename(); | ||
| 197 | - std::string mimeType = parser->getFieldMimeType(); | ||
| 198 | - Serial.printf("handleFormUpload: field name='%s', filename='%s', mimetype='%s'\n", name.c_str(), filename.c_str(), mimeType.c_str()); | ||
| 199 | - // Double check that it is what we expect | ||
| 200 | - if (name != "file") { | ||
| 201 | - Serial.println("Skipping unexpected field"); | ||
| 202 | - break; | ||
| 203 | - } | ||
| 204 | - // Should check file name validity and all that, but we skip that. | ||
| 205 | - std::string pathname = "/public/" + filename; | ||
| 206 | - File file = SPIFFS.open(pathname.c_str(), "w"); | ||
| 207 | - size_t fileLength = 0; | ||
| 208 | - didwrite = true; | ||
| 209 | - while (!parser->endOfField()) { | ||
| 210 | - byte buf[512]; | ||
| 211 | - size_t readLength = parser->read(buf, 512); | ||
| 212 | - file.write(buf, readLength); | ||
| 213 | - fileLength += readLength; | ||
| 214 | - } | ||
| 215 | - file.close(); | ||
| 216 | - res->printf("<p>Saved %d bytes to %s</p>", (int)fileLength, pathname.c_str()); | ||
| 217 | - } | ||
| 218 | - if (!didwrite) res->println("<p>Did not write any file</p>"); | ||
| 219 | - res->println("</body></html>"); | ||
| 220 | - delete parser; | ||
| 176 | + // First, we need to check the encoding of the form that we have received. | ||
| 177 | + // The browser will set the Content-Type request header, so we can use it for that purpose. | ||
| 178 | + // Then we select the body parser based on the encoding. | ||
| 179 | + // Actually we do this only for documentary purposes, we know the form is going | ||
| 180 | + // to be multipart/form-data. | ||
| 181 | + HTTPBodyParser *parser; | ||
| 182 | + std::string contentType = req->getHeader("Content-Type"); | ||
| 183 | + size_t semicolonPos = contentType.find(";"); | ||
| 184 | + if (semicolonPos != std::string::npos) { | ||
| 185 | + contentType = contentType.substr(0, semicolonPos); | ||
| 186 | + } | ||
| 187 | + if (contentType == "multipart/form-data") { | ||
| 188 | + parser = new HTTPMultipartBodyParser(req); | ||
| 189 | + } else { | ||
| 190 | + Serial.printf("Unknown POST Content-Type: %s\n", contentType.c_str()); | ||
| 191 | + return; | ||
| 192 | + } | ||
| 193 | + // We iterate over the fields. Any field with a filename is uploaded | ||
| 194 | + res->println("<html><head><title>File Upload</title></head><body><h1>File Upload</h1>"); | ||
| 195 | + bool didwrite = false; | ||
| 196 | + while(parser->nextField()) { | ||
| 197 | + std::string name = parser->getFieldName(); | ||
| 198 | + std::string filename = parser->getFieldFilename(); | ||
| 199 | + std::string mimeType = parser->getFieldMimeType(); | ||
| 200 | + Serial.printf("handleFormUpload: field name='%s', filename='%s', mimetype='%s'\n", name.c_str(), filename.c_str(), mimeType.c_str()); | ||
| 201 | + // Double check that it is what we expect | ||
| 202 | + if (name != "file") { | ||
| 203 | + Serial.println("Skipping unexpected field"); | ||
| 204 | + break; | ||
| 205 | + } | ||
| 206 | + // Should check file name validity and all that, but we skip that. | ||
| 207 | + std::string pathname = "/public/" + filename; | ||
| 208 | + File file = SPIFFS.open(pathname.c_str(), "w"); | ||
| 209 | + size_t fileLength = 0; | ||
| 210 | + didwrite = true; | ||
| 211 | + while (!parser->endOfField()) { | ||
| 212 | + byte buf[512]; | ||
| 213 | + size_t readLength = parser->read(buf, 512); | ||
| 214 | + file.write(buf, readLength); | ||
| 215 | + fileLength += readLength; | ||
| 216 | + } | ||
| 217 | + file.close(); | ||
| 218 | + res->printf("<p>Saved %d bytes to %s</p>", (int)fileLength, pathname.c_str()); | ||
| 219 | + } | ||
| 220 | + if (!didwrite) { | ||
| 221 | + res->println("<p>Did not write any file</p>"); | ||
| 222 | + } | ||
| 223 | + res->println("</body></html>"); | ||
| 224 | + delete parser; | ||
| 221 | 225 | } | |
| 222 | 226 | ||
| 223 | 227 | void handleFormEdit(HTTPRequest * req, HTTPResponse * res) { | |
| 224 | 228 | if (req->getMethod() == "GET") { | |
| 225 | - // Initial request. Get filename from request parameters and return form. | ||
| 226 | - auto params = req->getParams(); | ||
| 227 | - std::string filename; | ||
| 228 | - bool hasFilename = params->getQueryParameter("filename", filename); | ||
| 229 | - std::string pathname = std::string("/public/") + filename; | ||
| 230 | - res->println("<html><head><title>Edit File</title><head><body>"); | ||
| 231 | - File file = SPIFFS.open(pathname.c_str()); | ||
| 232 | - if (!hasFilename) { | ||
| 233 | - res->println("<p>No filename specified.</p>"); | ||
| 234 | - } else | ||
| 235 | - if (!file.available()) { | ||
| 236 | - res->printf("<p>File not found: %s</p>\n", pathname.c_str()); | ||
| 237 | - } else { | ||
| 238 | - res->printf("<h2>Edit content of %s</h2>\n", pathname.c_str()); | ||
| 239 | - res->println("<form method=\"POST\" enctype=\"application/x-www-form-urlencoded\">"); | ||
| 240 | - res->printf("<input name=\"filename\" type=\"hidden\" value=\"%s\">", filename.c_str()); | ||
| 241 | - res->print("<textarea name=\"content\" rows=\"24\" cols=\"80\">"); | ||
| 242 | - // Read the file and write it to the response | ||
| 243 | - size_t length = 0; | ||
| 244 | - do { | ||
| 245 | - char buffer[256]; | ||
| 246 | - length = file.read((uint8_t *)buffer, 256); | ||
| 247 | - std::string bufferString(buffer, length); | ||
| 248 | - bufferString = htmlEncode(bufferString); | ||
| 249 | - res->write((uint8_t *)bufferString.c_str(), bufferString.size()); | ||
| 250 | - } while (length > 0); | ||
| 251 | - res->println("</textarea><br>"); | ||
| 252 | - res->println("<input type=\"submit\" value=\"Save\">"); | ||
| 253 | - res->println("</form>"); | ||
| 254 | - } | ||
| 255 | - res->println("</body></html>"); | ||
| 256 | - } else { | ||
| 257 | - // Assume POST request. Contains submitted data. | ||
| 258 | - res->println("<html><head><title>File Edited</title><head><body><h1>File Edited</h1>"); | ||
| 259 | - HTTPURLEncodedBodyParser parser(req); | ||
| 260 | - std::string filename; | ||
| 261 | - bool savedFile = false; | ||
| 262 | - while(parser.nextField()) { | ||
| 263 | - std::string name = parser.getFieldName(); | ||
| 264 | - if (name == "filename") { | ||
| 265 | - char buf[512]; | ||
| 266 | - size_t readLength = parser.read((byte *)buf, 512); | ||
| 267 | - filename = std::string("/public/") + std::string(buf, readLength); | ||
| 268 | - } else | ||
| 269 | - if (name == "content") { | ||
| 270 | - if (filename == "") { | ||
| 271 | - res->println("<p>Error: form contained content before filename.</p>"); | ||
| 272 | - break; | ||
| 273 | - } | ||
| 274 | - size_t fieldLength = 0; | ||
| 275 | - File file = SPIFFS.open(filename.c_str(), "w"); | ||
| 276 | - savedFile = true; | ||
| 277 | - while (!parser.endOfField()) { | ||
| 278 | - byte buf[512]; | ||
| 279 | - size_t readLength = parser.read(buf, 512); | ||
| 280 | - file.write(buf, readLength); | ||
| 281 | - fieldLength += readLength; | ||
| 282 | - } | ||
| 283 | - file.close(); | ||
| 284 | - res->printf("<p>Saved %d bytes to %s</p>", int(fieldLength), filename.c_str()); | ||
| 285 | - } else { | ||
| 286 | - res->printf("<p>Unexpected field %s</p>", name.c_str()); | ||
| 287 | - } | ||
| 288 | - } | ||
| 289 | - if (!savedFile) res->println("<p>No file to save...</p>"); | ||
| 290 | - res->println("</body></html>"); | ||
| 229 | + // Initial request. Get filename from request parameters and return form. | ||
| 230 | + auto params = req->getParams(); | ||
| 231 | + std::string filename; | ||
| 232 | + bool hasFilename = params->getQueryParameter("filename", filename); | ||
| 233 | + std::string pathname = std::string("/public/") + filename; | ||
| 234 | + res->println("<html><head><title>Edit File</title><head><body>"); | ||
| 235 | + File file = SPIFFS.open(pathname.c_str()); | ||
| 236 | + if (!hasFilename) { | ||
| 237 | + res->println("<p>No filename specified.</p>"); | ||
| 238 | + } else if (!file.available()) { | ||
| 239 | + res->printf("<p>File not found: %s</p>\n", pathname.c_str()); | ||
| 240 | + } else { | ||
| 241 | + res->printf("<h2>Edit content of %s</h2>\n", pathname.c_str()); | ||
| 242 | + res->println("<form method=\"POST\" enctype=\"application/x-www-form-urlencoded\">"); | ||
| 243 | + res->printf("<input name=\"filename\" type=\"hidden\" value=\"%s\">", filename.c_str()); | ||
| 244 | + res->print("<textarea name=\"content\" rows=\"24\" cols=\"80\">"); | ||
| 245 | + // Read the file and write it to the response | ||
| 246 | + size_t length = 0; | ||
| 247 | + do { | ||
| 248 | + char buffer[256]; | ||
| 249 | + length = file.read((uint8_t *)buffer, 256); | ||
| 250 | + std::string bufferString(buffer, length); | ||
| 251 | + bufferString = htmlEncode(bufferString); | ||
| 252 | + res->write((uint8_t *)bufferString.c_str(), bufferString.size()); | ||
| 253 | + } while (length > 0); | ||
| 254 | + res->println("</textarea><br>"); | ||
| 255 | + res->println("<input type=\"submit\" value=\"Save\">"); | ||
| 256 | + res->println("</form>"); | ||
| 257 | + } | ||
| 258 | + res->println("</body></html>"); | ||
| 259 | + } else { // method != GET | ||
| 260 | + // Assume POST request. Contains submitted data. | ||
| 261 | + res->println("<html><head><title>File Edited</title><head><body><h1>File Edited</h1>"); | ||
| 262 | + HTTPURLEncodedBodyParser parser(req); | ||
| 263 | + std::string filename; | ||
| 264 | + bool savedFile = false; | ||
| 265 | + while(parser.nextField()) { | ||
| 266 | + std::string name = parser.getFieldName(); | ||
| 267 | + if (name == "filename") { | ||
| 268 | + char buf[512]; | ||
| 269 | + size_t readLength = parser.read((byte *)buf, 512); | ||
| 270 | + filename = std::string("/public/") + std::string(buf, readLength); | ||
| 271 | + } else if (name == "content") { | ||
| 272 | + if (filename == "") { | ||
| 273 | + res->println("<p>Error: form contained content before filename.</p>"); | ||
| 274 | + break; | ||
| 275 | + } | ||
| 276 | + size_t fieldLength = 0; | ||
| 277 | + File file = SPIFFS.open(filename.c_str(), "w"); | ||
| 278 | + savedFile = true; | ||
| 279 | + while (!parser.endOfField()) { | ||
| 280 | + byte buf[512]; | ||
| 281 | + size_t readLength = parser.read(buf, 512); | ||
| 282 | + file.write(buf, readLength); | ||
| 283 | + fieldLength += readLength; | ||
| 284 | + } | ||
| 285 | + file.close(); | ||
| 286 | + res->printf("<p>Saved %d bytes to %s</p>", int(fieldLength), filename.c_str()); | ||
| 287 | + } else { | ||
| 288 | + res->printf("<p>Unexpected field %s</p>", name.c_str()); | ||
| 289 | + } | ||
| 290 | + } | ||
| 291 | + if (!savedFile) { | ||
| 292 | + res->println("<p>No file to save...</p>"); | ||
| 293 | + } | ||
| 294 | + res->println("</body></html>"); | ||
| 291 | 295 | } | |
| 292 | 296 | } | |
| 293 | 297 | ||
| 294 | 298 | void handleDirectory(HTTPRequest * req, HTTPResponse * res) { | |
| 295 | 299 | res->println("<html><head><title>File Listing</title><head><body>"); | |
| 296 | 300 | File d = SPIFFS.open("/public"); | |
| 297 | 301 | if (!d.isDirectory()) { | |
| 298 | - res->println("<p>No files found.</p>"); | ||
| 302 | + res->println("<p>No files found.</p>"); | ||
| 299 | 303 | } else { | |
| 300 | - res->println("<h1>File Listing</h1>"); | ||
| 301 | - res->println("<ul>"); | ||
| 302 | - File f = d.openNextFile(); | ||
| 303 | - while (f) { | ||
| 304 | - std::string pathname(f.name()); | ||
| 305 | - res->printf("<li><a href=\"%s\">%s</a>", pathname.c_str(), pathname.c_str()); | ||
| 306 | - if (pathname.rfind(".txt") != std::string::npos) { | ||
| 307 | - std::string filename = pathname.substr(8); // Remove /public/ | ||
| 308 | - res->printf(" <a href=\"/edit?filename=%s\">[edit]</a>", filename.c_str()); | ||
| 309 | - } | ||
| 310 | - res->println("</li>"); | ||
| 311 | - f = d.openNextFile(); | ||
| 312 | - } | ||
| 313 | - res->println("</ul>"); | ||
| 304 | + res->println("<h1>File Listing</h1>"); | ||
| 305 | + res->println("<ul>"); | ||
| 306 | + File f = d.openNextFile(); | ||
| 307 | + while (f) { | ||
| 308 | + std::string pathname(f.name()); | ||
| 309 | + res->printf("<li><a href=\"%s\">%s</a>", pathname.c_str(), pathname.c_str()); | ||
| 310 | + if (pathname.rfind(".txt") != std::string::npos) { | ||
| 311 | + std::string filename = pathname.substr(8); // Remove /public/ | ||
| 312 | + res->printf(" <a href=\"/edit?filename=%s\">[edit]</a>", filename.c_str()); | ||
| 313 | + } | ||
| 314 | + res->println("</li>"); | ||
| 315 | + f = d.openNextFile(); | ||
| 316 | + } | ||
| 317 | + res->println("</ul>"); | ||
| 314 | 318 | } | |
| 315 | 319 | res->println("</body></html>"); | |
| 316 | 320 | } | |
@@ -353,21 +357,21 @@ void handleFile(HTTPRequest * req, HTTPResponse * res) { | |||
| 353 | 357 | } | |
| 354 | 358 | ||
| 355 | 359 | void handle404(HTTPRequest * req, HTTPResponse * res) { | |
| 356 | - // Discard request body, if we received any | ||
| 357 | - // We do this, as this is the default node and may also server POST/PUT requests | ||
| 358 | - req->discardRequestBody(); | ||
| 359 | - | ||
| 360 | - // Set the response status | ||
| 361 | - res->setStatusCode(404); | ||
| 362 | - res->setStatusText("Not Found"); | ||
| 363 | - | ||
| 364 | - // Set content type of the response | ||
| 365 | - res->setHeader("Content-Type", "text/html"); | ||
| 366 | - | ||
| 367 | - // Write a tiny HTML page | ||
| 368 | - res->println("<!DOCTYPE html>"); | ||
| 369 | - res->println("<html>"); | ||
| 370 | - res->println("<head><title>Not Found</title></head>"); | ||
| 371 | - res->println("<body><h1>404 Not Found</h1><p>The requested resource was not found on this server.</p></body>"); | ||
| 372 | - res->println("</html>"); | ||
| 360 | + // Discard request body, if we received any | ||
| 361 | + // We do this, as this is the default node and may also server POST/PUT requests | ||
| 362 | + req->discardRequestBody(); | ||
| 363 | + | ||
| 364 | + // Set the response status | ||
| 365 | + res->setStatusCode(404); | ||
| 366 | + res->setStatusText("Not Found"); | ||
| 367 | + | ||
| 368 | + // Set content type of the response | ||
| 369 | + res->setHeader("Content-Type", "text/html"); | ||
| 370 | + | ||
| 371 | + // Write a tiny HTML page | ||
| 372 | + res->println("<!DOCTYPE html>"); | ||
| 373 | + res->println("<html>"); | ||
| 374 | + res->println("<head><title>Not Found</title></head>"); | ||
| 375 | + res->println("<body><h1>404 Not Found</h1><p>The requested resource was not found on this server.</p></body>"); | ||
| 376 | + res->println("</html>"); | ||
| 373 | 377 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments