@@ -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
}
0 commit comments