Skip to content

Commit b5ca4fe

Browse files
committed
Merge pull request esp8266#1055 from me-no-dev/http-uploads
Http uploads
2 parents 4b8fb20 + bc48022 commit b5ca4fe

File tree

9 files changed

+89
-50
lines changed

9 files changed

+89
-50
lines changed

libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp

+4-7
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,9 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server)
3636
_server->sendHeader("Access-Control-Allow-Origin", "*");
3737
_server->send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
3838
ESP.restart();
39-
});
40-
41-
// handler for the file upload, get's the sketch bytes, and writes
42-
// them through the Update object.
43-
_server->onFileUpload([&](){
44-
if(_server->uri() != "/update") return;
39+
},[&](){
40+
// handler for the file upload, get's the sketch bytes, and writes
41+
// them through the Update object
4542
HTTPUpload& upload = _server->upload();
4643
if(upload.status == UPLOAD_FILE_START){
4744
if (_serial_output)
@@ -70,6 +67,6 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server)
7067
Update.end();
7168
if (_serial_output) Serial.println("Update was aborted");
7269
}
73-
yield();
70+
delay(0);
7471
});
7572
}

libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino

+3-4
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,9 @@ void setup(void){
207207
server.on("/edit", HTTP_PUT, handleFileCreate);
208208
//delete file
209209
server.on("/edit", HTTP_DELETE, handleFileDelete);
210-
//called after file upload
211-
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); });
212-
//called when a file is received inside POST data
213-
server.onFileUpload(handleFileUpload);
210+
//first callback is called after the request has ended with all parsed arguments
211+
//second callback handles file uploads at that location
212+
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload);
214213

215214
//called when the url is not defined here
216215
//use it to load content from SPIFFS

libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino

+1-2
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,8 @@ void setup(void){
256256
server.on("/list", HTTP_GET, printDirectory);
257257
server.on("/edit", HTTP_DELETE, handleDelete);
258258
server.on("/edit", HTTP_PUT, handleCreate);
259-
server.on("/edit", HTTP_POST, [](){ returnOK(); });
259+
server.on("/edit", HTTP_POST, [](){ returnOK(); }, handleFileUpload);
260260
server.onNotFound(handleNotFound);
261-
server.onFileUpload(handleFileUpload);
262261

263262
server.begin();
264263
DBG_OUTPUT_PORT.println("HTTP server started");

libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino

+6-8
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ void setup(void){
2727
server.sendHeader("Access-Control-Allow-Origin", "*");
2828
server.send(200, "text/html", serverIndex);
2929
});
30-
server.onFileUpload([](){
31-
if(server.uri() != "/update") return;
30+
server.on("/update", HTTP_POST, [](){
31+
server.sendHeader("Connection", "close");
32+
server.sendHeader("Access-Control-Allow-Origin", "*");
33+
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
34+
ESP.restart();
35+
},[](){
3236
HTTPUpload& upload = server.upload();
3337
if(upload.status == UPLOAD_FILE_START){
3438
Serial.setDebugOutput(true);
@@ -52,12 +56,6 @@ void setup(void){
5256
}
5357
yield();
5458
});
55-
server.on("/update", HTTP_POST, [](){
56-
server.sendHeader("Connection", "close");
57-
server.sendHeader("Access-Control-Allow-Origin", "*");
58-
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
59-
ESP.restart();
60-
});
6159
server.begin();
6260
MDNS.addService("http", "tcp", 80);
6361

libraries/ESP8266WebServer/src/ESP8266WebServer.cpp

+10-8
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
3535
: _server(addr, port)
36+
, _currentHandler(0)
3637
, _firstHandler(0)
3738
, _lastHandler(0)
3839
, _currentArgCount(0)
@@ -44,6 +45,7 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
4445

4546
ESP8266WebServer::ESP8266WebServer(int port)
4647
: _server(port)
48+
, _currentHandler(0)
4749
, _firstHandler(0)
4850
, _lastHandler(0)
4951
, _currentArgCount(0)
@@ -74,7 +76,11 @@ void ESP8266WebServer::on(const char* uri, ESP8266WebServer::THandlerFunction ha
7476
}
7577

7678
void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn) {
77-
_addRequestHandler(new FunctionRequestHandler(fn, uri, method));
79+
on(uri, method, fn, _fileUploadHandler);
80+
}
81+
82+
void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn, ESP8266WebServer::THandlerFunction ufn) {
83+
_addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method));
7884
}
7985

8086
void ESP8266WebServer::addHandler(RequestHandler* handler) {
@@ -352,13 +358,7 @@ void ESP8266WebServer::onNotFound(THandlerFunction fn) {
352358
}
353359

354360
void ESP8266WebServer::_handleRequest() {
355-
RequestHandler* handler;
356-
for (handler = _firstHandler; handler; handler = handler->next()) {
357-
if (handler->handle(*this, _currentMethod, _currentUri))
358-
break;
359-
}
360-
361-
if (!handler){
361+
if (!_currentHandler){
362362
#ifdef DEBUG
363363
DEBUG_OUTPUT.println("request handler not found");
364364
#endif
@@ -369,6 +369,8 @@ void ESP8266WebServer::_handleRequest() {
369369
else {
370370
send(404, "text/plain", String("Not found: ") + _currentUri);
371371
}
372+
} else {
373+
_currentHandler->handle(*this, _currentMethod, _currentUri);
372374
}
373375

374376
uint16_t maxWait = HTTP_MAX_CLOSE_WAIT;

libraries/ESP8266WebServer/src/ESP8266WebServer.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,6 @@ enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END,
4040

4141
class ESP8266WebServer;
4242

43-
#include "detail/RequestHandler.h"
44-
45-
namespace fs {
46-
class FS;
47-
}
48-
4943
typedef struct {
5044
HTTPUploadStatus status;
5145
String filename;
@@ -56,6 +50,12 @@ typedef struct {
5650
uint8_t buf[HTTP_UPLOAD_BUFLEN];
5751
} HTTPUpload;
5852

53+
#include "detail/RequestHandler.h"
54+
55+
namespace fs {
56+
class FS;
57+
}
58+
5959
class ESP8266WebServer
6060
{
6161
public:
@@ -69,6 +69,7 @@ class ESP8266WebServer
6969
typedef std::function<void(void)> THandlerFunction;
7070
void on(const char* uri, THandlerFunction handler);
7171
void on(const char* uri, HTTPMethod method, THandlerFunction fn);
72+
void on(const char* uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn);
7273
void addHandler(RequestHandler* handler);
7374
void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header = NULL );
7475
void onNotFound(THandlerFunction fn); //called when handler is not assigned
@@ -155,6 +156,7 @@ template<typename T> size_t streamFile(T &file, const String& contentType){
155156

156157
String _hostHeader;
157158

159+
RequestHandler* _currentHandler;
158160
RequestHandler* _firstHandler;
159161
RequestHandler* _lastHandler;
160162
THandlerFunction _notFoundHandler;

libraries/ESP8266WebServer/src/Parsing.cpp

+18-5
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
8181
DEBUG_OUTPUT.println(searchStr);
8282
#endif
8383

84+
//attach handler
85+
RequestHandler* handler;
86+
for (handler = _firstHandler; handler; handler = handler->next()) {
87+
if (handler->canHandle(_currentMethod, _currentUri))
88+
break;
89+
}
90+
_currentHandler = handler;
91+
8492
String formData;
8593
// below is needed only when POST type request
8694
if (method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH || method == HTTP_DELETE){
@@ -279,7 +287,8 @@ void ESP8266WebServer::_parseArguments(String data) {
279287

280288
void ESP8266WebServer::_uploadWriteByte(uint8_t b){
281289
if (_currentUpload.currentSize == HTTP_UPLOAD_BUFLEN){
282-
if (_fileUploadHandler) _fileUploadHandler();
290+
if(_currentHandler && _currentHandler->canUpload(_currentUri))
291+
_currentHandler->upload(*this, _currentUri, _currentUpload);
283292
_currentUpload.totalSize += _currentUpload.currentSize;
284293
_currentUpload.currentSize = 0;
285294
}
@@ -397,7 +406,8 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
397406
DEBUG_OUTPUT.print(" Type: ");
398407
DEBUG_OUTPUT.println(_currentUpload.type);
399408
#endif
400-
if (_fileUploadHandler) _fileUploadHandler();
409+
if(_currentHandler && _currentHandler->canUpload(_currentUri))
410+
_currentHandler->upload(*this, _currentUri, _currentUpload);
401411
_currentUpload.status = UPLOAD_FILE_WRITE;
402412
uint8_t argByte = _uploadReadByte(client);
403413
readfile:
@@ -433,10 +443,12 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
433443
client.readBytes(endBuf, boundary.length());
434444

435445
if (strstr((const char*)endBuf, boundary.c_str()) != NULL){
436-
if (_fileUploadHandler) _fileUploadHandler();
446+
if(_currentHandler && _currentHandler->canUpload(_currentUri))
447+
_currentHandler->upload(*this, _currentUri, _currentUpload);
437448
_currentUpload.totalSize += _currentUpload.currentSize;
438449
_currentUpload.status = UPLOAD_FILE_END;
439-
if (_fileUploadHandler) _fileUploadHandler();
450+
if(_currentHandler && _currentHandler->canUpload(_currentUri))
451+
_currentHandler->upload(*this, _currentUri, _currentUpload);
440452
#ifdef DEBUG
441453
DEBUG_OUTPUT.print("End File: ");
442454
DEBUG_OUTPUT.print(_currentUpload.filename);
@@ -503,6 +515,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
503515

504516
bool ESP8266WebServer::_parseFormUploadAborted(){
505517
_currentUpload.status = UPLOAD_FILE_ABORTED;
506-
if (_fileUploadHandler) _fileUploadHandler();
518+
if(_currentHandler && _currentHandler->canUpload(_currentUri))
519+
_currentHandler->upload(*this, _currentUri, _currentUpload);
507520
return false;
508521
}

libraries/ESP8266WebServer/src/detail/RequestHandler.h

+3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
class RequestHandler {
55
public:
6+
virtual bool canHandle(HTTPMethod method, String uri) { return false; }
7+
virtual bool canUpload(String uri) { return false; }
68
virtual bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) { return false; }
9+
virtual void upload(ESP8266WebServer& server, String requestUri, HTTPUpload& upload) {}
710

811
RequestHandler* next() { return _next; }
912
void next(RequestHandler* r) { _next = r; }

libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h

+36-10
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,49 @@
55

66
class FunctionRequestHandler : public RequestHandler {
77
public:
8-
FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method)
8+
FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, ESP8266WebServer::THandlerFunction ufn, const char* uri, HTTPMethod method)
99
: _fn(fn)
10+
, _ufn(ufn)
1011
, _uri(uri)
1112
, _method(method)
1213
{
1314
}
1415

15-
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
16+
bool canHandle(HTTPMethod requestMethod, String requestUri) override {
1617
if (_method != HTTP_ANY && _method != requestMethod)
1718
return false;
1819

1920
if (requestUri != _uri)
2021
return false;
2122

23+
return true;
24+
}
25+
26+
bool canUpload(String requestUri) override {
27+
if (!_ufn || !canHandle(HTTP_POST, requestUri))
28+
return false;
29+
30+
return true;
31+
}
32+
33+
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
34+
if (!canHandle(requestMethod, requestUri))
35+
return false;
36+
2237
_fn();
2338
return true;
2439
}
2540

41+
void upload(ESP8266WebServer& server, String requestUri, HTTPUpload& upload) override {
42+
if (canUpload(requestUri))
43+
_ufn();
44+
}
45+
2646
protected:
2747
String _uri;
2848
HTTPMethod _method;
2949
ESP8266WebServer::THandlerFunction _fn;
50+
ESP8266WebServer::THandlerFunction _ufn;
3051
};
3152

3253
class StaticRequestHandler : public RequestHandler {
@@ -41,12 +62,22 @@ class StaticRequestHandler : public RequestHandler {
4162
DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header);
4263
_baseUriLength = _uri.length();
4364
}
44-
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
65+
66+
bool canHandle(HTTPMethod requestMethod, String requestUri) override {
4567
if (requestMethod != HTTP_GET)
4668
return false;
47-
DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
48-
if (!requestUri.startsWith(_uri))
69+
70+
if (_isFile && requestUri != _uri || !requestUri.startsWith(_uri))
71+
return false;
72+
73+
return true;
74+
}
75+
76+
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
77+
if (!canHandle(requestMethod, requestUri))
4978
return false;
79+
80+
DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
5081

5182
String path(_path);
5283

@@ -57,11 +88,6 @@ class StaticRequestHandler : public RequestHandler {
5788
// URI in request to get the file path.
5889
path += requestUri.substring(_baseUriLength);
5990
}
60-
61-
else if (requestUri != _uri) {
62-
// Base URI points to a file but request doesn't match this URI exactly
63-
return false;
64-
}
6591
DEBUGV("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile);
6692

6793
String contentType = getContentType(path);

0 commit comments

Comments
 (0)