57
57
#define WEBDUINO_READ_TIMEOUT_IN_MS 1000
58
58
#endif
59
59
60
+ #ifndef WEBDUINO_URL_PATH_COMMAND_LENGTH
61
+ #define WEBDUINO_URL_PATH_COMMAND_LENGTH 8
62
+ #endif
63
+
60
64
#ifndef WEBDUINO_FAIL_MESSAGE
61
65
#define WEBDUINO_FAIL_MESSAGE " <h1>EPIC FAIL</h1>"
62
66
#endif
@@ -158,6 +162,13 @@ class WebServer: public Print
158
162
typedef void Command (WebServer &server, ConnectionType type,
159
163
char *url_tail, bool tail_complete);
160
164
165
+ // Prototype for the optional function which consumes the URL path itself.
166
+ // url_path contains pointers to the seperate parts of the URL path where '/'
167
+ // was used as the delimiter.
168
+ typedef void UrlPathCommand (WebServer &server, ConnectionType type,
169
+ char **url_path, char *url_tail,
170
+ bool tail_complete);
171
+
161
172
// constructor for webserver object
162
173
WebServer (const char *urlPrefix = " " , int port = 80 );
163
174
@@ -184,6 +195,11 @@ class WebServer: public Print
184
195
// add a new command to be run at the URL specified by verb
185
196
void addCommand (const char *verb, Command *cmd);
186
197
198
+ // Set command that's run if default command or URL specified commands do
199
+ // not run, uses extra url_path parameter to allow resolving the URL in the
200
+ // function.
201
+ void setUrlPathCommand (UrlPathCommand *cmd);
202
+
187
203
// utility function to output CRLF pair
188
204
void printCRLF ();
189
205
@@ -299,6 +315,7 @@ class WebServer: public Print
299
315
Command *cmd;
300
316
} m_commands[8 ];
301
317
char m_cmdCount;
318
+ UrlPathCommand *m_urlPathCmd;
302
319
303
320
void reset ();
304
321
void getRequest (WebServer::ConnectionType &type, char *request, int *length);
@@ -332,7 +349,8 @@ WebServer::WebServer(const char *urlPrefix, int port) :
332
349
m_cmdCount(0 ),
333
350
m_contentLength(0 ),
334
351
m_failureCmd(&defaultFailCmd),
335
- m_defaultCmd(&defaultFailCmd)
352
+ m_defaultCmd(&defaultFailCmd),
353
+ m_urlPathCmd(NULL )
336
354
{
337
355
}
338
356
@@ -360,6 +378,11 @@ void WebServer::addCommand(const char *verb, Command *cmd)
360
378
}
361
379
}
362
380
381
+ void WebServer::setUrlPathCommand (UrlPathCommand *cmd)
382
+ {
383
+ m_urlPathCmd = cmd;
384
+ }
385
+
363
386
size_t WebServer::write (uint8_t ch)
364
387
{
365
388
return m_client.write (ch);
@@ -475,6 +498,36 @@ bool WebServer::dispatchCommand(ConnectionType requestType, char *verb,
475
498
return true ;
476
499
}
477
500
}
501
+ // Check if UrlPathCommand is assigned.
502
+ if (m_urlPathCmd != NULL )
503
+ {
504
+ // Initialize with null bytes, so number of parts can be determined.
505
+ char *url_path[WEBDUINO_URL_PATH_COMMAND_LENGTH] = {0 };
506
+ int part = 0 ;
507
+
508
+ // URL path should be terminated with null byte.
509
+ *(verb + verb_len) = 0 ;
510
+
511
+ // First URL path part is at the start of verb.
512
+ url_path[part++] = verb;
513
+ // Replace all slashes ('/') with a null byte so every part of the URL
514
+ // path is a seperate string. Add every char following a '/' as a new
515
+ // part of the URL, even if that char is a '/' (which will be replaced
516
+ // with a null byte).
517
+ for (char * p = verb; p < verb + verb_len; p++)
518
+ {
519
+ if (*p == ' /' )
520
+ {
521
+ *p = 0 ;
522
+ url_path[part++] = p + 1 ;
523
+ // Don't try to assign out of array bounds.
524
+ if (part == WEBDUINO_URL_PATH_COMMAND_LENGTH) break ;
525
+ }
526
+ }
527
+ m_urlPathCmd (*this , requestType, url_path,
528
+ verb + verb_len + qm_offset, tail_complete);
529
+ return true ;
530
+ }
478
531
}
479
532
return false ;
480
533
}
0 commit comments