From f607b6a4e143a08b8c6529c77558b429b6e955ac Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Mon, 27 Jun 2016 21:51:06 +0300 Subject: [PATCH 1/4] Add chunked encoding example: ```cpp server.on("/chunked", HTTP_GET, [](){ server.send(200, "text/html", String()); server.sendContent("Chunked Test"); server.sendContent("

Chunk 1

"); server.sendContent("

Chunk 2

"); server.sendContent("

Chunk 3

"); server.sendContent("

Chunk 4

"); server.sendContent("

Chunk 5

"); server.sendContent("

Chunk 6

"); server.sendContent(""); server.sendContent("");//end of chunked }); ``` --- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 47 ++++++++++++++++--- .../ESP8266WebServer/src/ESP8266WebServer.h | 1 + libraries/ESP8266WebServer/src/Parsing.cpp | 2 + 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index ed06b73476..68a9624230 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -41,6 +41,7 @@ const char * AUTHORIZATION_HEADER = "Authorization"; ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port) : _server(addr, port) , _currentMethod(HTTP_ANY) +, _currentVersion(0) , _currentHandler(0) , _firstHandler(0) , _lastHandler(0) @@ -55,6 +56,7 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port) ESP8266WebServer::ESP8266WebServer(int port) : _server(port) , _currentMethod(HTTP_ANY) +, _currentVersion(0) , _currentHandler(0) , _firstHandler(0) , _lastHandler(0) @@ -246,7 +248,7 @@ void ESP8266WebServer::setContentLength(size_t contentLength) { } void ESP8266WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) { - response = "HTTP/1.1 "; + response = "HTTP/1."+String(_currentVersion)+" "; response += String(code); response += " "; response += _responseCodeToString(code); @@ -260,9 +262,12 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co sendHeader("Content-Length", String(contentLength)); } else if (_contentLength != CONTENT_LENGTH_UNKNOWN) { sendHeader("Content-Length", String(_contentLength)); + } else if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ //HTTP/1.1 or above client + //let's do chunked + sendHeader("Accept-Ranges","none"); + sendHeader("Transfer-Encoding","chunked"); } sendHeader("Connection", "close"); - sendHeader("Access-Control-Allow-Origin", "*"); response += _responseHeaders; response += "\r\n"; @@ -271,9 +276,12 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co void ESP8266WebServer::send(int code, const char* content_type, const String& content) { String header; + if(content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET) + _contentLength = CONTENT_LENGTH_UNKNOWN; _prepareHeader(header, code, content_type, content.length()); - sendContent(header); - sendContent(content); + _currentClient.write(header.c_str(), header.length()); + if(content.length()) + sendContent(content); } void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content) { @@ -287,7 +295,7 @@ void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content) { char type[64]; memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type)); _prepareHeader(header, code, (const char* )type, contentLength); - sendContent(header); + _currentClient.write(header.c_str(), header.length()); sendContent_P(content); } @@ -309,15 +317,40 @@ void ESP8266WebServer::send(int code, const String& content_type, const String& } void ESP8266WebServer::sendContent(const String& content) { - _currentClient.write(content.c_str(), content.length()); + const char * footer = "\r\n"; + size_t len = content.length(); + if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion) { + char * chunkSize = (char *)malloc(11); + if(chunkSize){ + sprintf(chunkSize, "%x%s", len, footer); + _currentClient.write(chunkSize, strlen(chunkSize)); + free(chunkSize); + } + } + _currentClient.write(content.c_str(), len); + if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ + _currentClient.write(footer, 2); + } } void ESP8266WebServer::sendContent_P(PGM_P content) { - _currentClient.write_P(content, strlen_P(content)); + sendContent_P(content, strlen_P(content)); } void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) { + const char * footer = "\r\n"; + if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion) { + char * chunkSize = (char *)malloc(11); + if(chunkSize){ + sprintf(chunkSize, "%x%s", size, footer); + _currentClient.write(chunkSize, strlen(chunkSize)); + free(chunkSize); + } + } _currentClient.write_P(content, size); + if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ + _currentClient.write(footer, 2); + } } diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index e1db841cd2..595e4e7359 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -156,6 +156,7 @@ template size_t streamFile(T &file, const String& contentType){ WiFiClient _currentClient; HTTPMethod _currentMethod; String _currentUri; + uint8_t _currentVersion; HTTPClientStatus _currentStatus; unsigned long _statusChange; diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index f4fff1765f..3928125077 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -86,6 +86,8 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { String methodStr = req.substring(0, addr_start); String url = req.substring(addr_start + 1, addr_end); + String versionEnd = req.substring(addr_end + 8); + _currentVersion = atoi(versionEnd.c_str()); String searchStr = ""; int hasSearch = url.indexOf('?'); if (hasSearch != -1){ From ff651e667bf95239001f7cc42af0182d1aba2df3 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Mon, 27 Jun 2016 22:36:05 +0300 Subject: [PATCH 2/4] update examples, keep setContentLength and add bool _chunked --- .../SimpleAuthentification.ino | 23 +++++++++++-------- .../examples/WebUpdate/WebUpdate.ino | 8 +++---- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 17 +++++++++----- .../ESP8266WebServer/src/ESP8266WebServer.h | 1 + 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/libraries/ESP8266WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino b/libraries/ESP8266WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino index 19fc69c7d7..10c15f6453 100644 --- a/libraries/ESP8266WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino +++ b/libraries/ESP8266WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino @@ -10,7 +10,7 @@ ESP8266WebServer server(80); //Check if header is present and correct bool is_authentified(){ Serial.println("Enter is_authentified"); - if (server.hasHeader("Cookie")){ + if (server.hasHeader("Cookie")){ Serial.print("Found cookie: "); String cookie = server.header("Cookie"); Serial.println(cookie); @@ -20,27 +20,31 @@ bool is_authentified(){ } } Serial.println("Authentification Failed"); - return false; + return false; } //login page, also called for disconnect void handleLogin(){ String msg; - if (server.hasHeader("Cookie")){ + if (server.hasHeader("Cookie")){ Serial.print("Found cookie: "); String cookie = server.header("Cookie"); Serial.println(cookie); } if (server.hasArg("DISCONNECT")){ Serial.println("Disconnection"); - String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=0\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n"; - server.sendContent(header); + server.sendHeader("Location","/login"); + server.sendHeader("Cache-Control","no-cache"); + server.sendHeader("Set-Cookie","ESPSESSIONID=1"); + server.send(301); return; } if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){ if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin" ){ - String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=1\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n"; - server.sendContent(header); + server.sendHeader("Location","/"); + server.sendHeader("Cache-Control","no-cache"); + server.sendHeader("Set-Cookie","ESPSESSIONID=1"); + server.send(301); Serial.println("Log in Successful"); return; } @@ -60,8 +64,9 @@ void handleRoot(){ Serial.println("Enter handleRoot"); String header; if (!is_authentified()){ - String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n"; - server.sendContent(header); + server.sendHeader("Location","/login"); + server.sendHeader("Cache-Control","no-cache"); + server.send(301); return; } String content = "

hello, you successfully connected to esp8266!


"; diff --git a/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino b/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino index c5e67ef33a..fd11759a42 100644 --- a/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino +++ b/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino @@ -24,12 +24,10 @@ void setup(void){ MDNS.begin(host); server.on("/", HTTP_GET, [](){ server.sendHeader("Connection", "close"); - server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/html", serverIndex); }); server.on("/update", HTTP_POST, [](){ server.sendHeader("Connection", "close"); - server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK"); ESP.restart(); },[](){ @@ -58,14 +56,14 @@ void setup(void){ }); server.begin(); MDNS.addService("http", "tcp", 80); - + Serial.printf("Ready! Open http://%s.local in your browser\n", host); } else { Serial.println("WiFi Failed"); } } - + void loop(void){ server.handleClient(); delay(1); -} +} diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 68a9624230..35d68cecfd 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -50,6 +50,7 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port) , _headerKeysCount(0) , _currentHeaders(0) , _contentLength(0) +, _chunked(false) { } @@ -65,6 +66,7 @@ ESP8266WebServer::ESP8266WebServer(int port) , _headerKeysCount(0) , _currentHeaders(0) , _contentLength(0) +, _chunked(false) { } @@ -257,6 +259,7 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co if (!content_type) content_type = "text/html"; + _chunked = false; sendHeader("Content-Type", content_type, true); if (_contentLength == CONTENT_LENGTH_NOT_SET) { sendHeader("Content-Length", String(contentLength)); @@ -264,6 +267,7 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co sendHeader("Content-Length", String(_contentLength)); } else if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ //HTTP/1.1 or above client //let's do chunked + _chunked = true; sendHeader("Accept-Ranges","none"); sendHeader("Transfer-Encoding","chunked"); } @@ -276,8 +280,9 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co void ESP8266WebServer::send(int code, const char* content_type, const String& content) { String header; - if(content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET) - _contentLength = CONTENT_LENGTH_UNKNOWN; + // Can we asume the following? + //if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET) + // _contentLength = CONTENT_LENGTH_UNKNOWN; _prepareHeader(header, code, content_type, content.length()); _currentClient.write(header.c_str(), header.length()); if(content.length()) @@ -319,7 +324,7 @@ void ESP8266WebServer::send(int code, const String& content_type, const String& void ESP8266WebServer::sendContent(const String& content) { const char * footer = "\r\n"; size_t len = content.length(); - if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion) { + if(_chunked) { char * chunkSize = (char *)malloc(11); if(chunkSize){ sprintf(chunkSize, "%x%s", len, footer); @@ -328,7 +333,7 @@ void ESP8266WebServer::sendContent(const String& content) { } } _currentClient.write(content.c_str(), len); - if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ + if(_chunked){ _currentClient.write(footer, 2); } } @@ -339,7 +344,7 @@ void ESP8266WebServer::sendContent_P(PGM_P content) { void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) { const char * footer = "\r\n"; - if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion) { + if(_chunked) { char * chunkSize = (char *)malloc(11); if(chunkSize){ sprintf(chunkSize, "%x%s", size, footer); @@ -348,7 +353,7 @@ void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) { } } _currentClient.write_P(content, size); - if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ + if(_chunked){ _currentClient.write(footer, 2); } } diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 595e4e7359..1583ecc43f 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -176,6 +176,7 @@ template size_t streamFile(T &file, const String& contentType){ String _responseHeaders; String _hostHeader; + bool _chunked; }; From aadf633fb1ef7163b179b53bdaea15af445b635c Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Mon, 27 Jun 2016 22:41:42 +0300 Subject: [PATCH 3/4] fix wrong session id --- .../examples/SimpleAuthentification/SimpleAuthentification.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino b/libraries/ESP8266WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino index 10c15f6453..d4762e1be1 100644 --- a/libraries/ESP8266WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino +++ b/libraries/ESP8266WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino @@ -35,7 +35,7 @@ void handleLogin(){ Serial.println("Disconnection"); server.sendHeader("Location","/login"); server.sendHeader("Cache-Control","no-cache"); - server.sendHeader("Set-Cookie","ESPSESSIONID=1"); + server.sendHeader("Set-Cookie","ESPSESSIONID=0"); server.send(301); return; } From 85a9f0872fac221dee8022f13e65198d5f484b83 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Mon, 27 Jun 2016 23:22:21 +0300 Subject: [PATCH 4/4] set _chunked to false earlier for cases where users use only sendContent --- libraries/ESP8266WebServer/src/ESP8266WebServer.cpp | 1 - libraries/ESP8266WebServer/src/Parsing.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 35d68cecfd..cc2e6d81b6 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -259,7 +259,6 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co if (!content_type) content_type = "text/html"; - _chunked = false; sendHeader("Content-Type", content_type, true); if (_contentLength == CONTENT_LENGTH_NOT_SET) { sendHeader("Content-Length", String(contentLength)); diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 3928125077..c35a270e4a 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -95,6 +95,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { url = url.substring(0, hasSearch); } _currentUri = url; + _chunked = false; HTTPMethod method = HTTP_GET; if (methodStr == "POST") {