Skip to content

Commit 2c2a85e

Browse files
me-no-devigrr
authored andcommitted
Chunked encoding (#2199)
* Add chunked encoding example: ```cpp server.on("/chunked", HTTP_GET, [](){ server.send(200, "text/html", String()); server.sendContent("<!DOCTYPE html><html><head><title>Chunked Test</title></head><body>"); server.sendContent("<p>Chunk 1</p>"); server.sendContent("<p>Chunk 2</p>"); server.sendContent("<p>Chunk 3</p>"); server.sendContent("<p>Chunk 4</p>"); server.sendContent("<p>Chunk 5</p>"); server.sendContent("<p>Chunk 6</p>"); server.sendContent("</html>"); server.sendContent("");//end of chunked }); ``` * update examples, keep setContentLength and add bool _chunked * fix wrong session id * set _chunked to false earlier for cases where users use only sendContent
1 parent a2403f1 commit 2c2a85e

File tree

5 files changed

+66
-21
lines changed

5 files changed

+66
-21
lines changed

examples/SimpleAuthentification/SimpleAuthentification.ino

+14-9
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ ESP8266WebServer server(80);
1010
//Check if header is present and correct
1111
bool is_authentified(){
1212
Serial.println("Enter is_authentified");
13-
if (server.hasHeader("Cookie")){
13+
if (server.hasHeader("Cookie")){
1414
Serial.print("Found cookie: ");
1515
String cookie = server.header("Cookie");
1616
Serial.println(cookie);
@@ -20,27 +20,31 @@ bool is_authentified(){
2020
}
2121
}
2222
Serial.println("Authentification Failed");
23-
return false;
23+
return false;
2424
}
2525

2626
//login page, also called for disconnect
2727
void handleLogin(){
2828
String msg;
29-
if (server.hasHeader("Cookie")){
29+
if (server.hasHeader("Cookie")){
3030
Serial.print("Found cookie: ");
3131
String cookie = server.header("Cookie");
3232
Serial.println(cookie);
3333
}
3434
if (server.hasArg("DISCONNECT")){
3535
Serial.println("Disconnection");
36-
String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=0\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
37-
server.sendContent(header);
36+
server.sendHeader("Location","/login");
37+
server.sendHeader("Cache-Control","no-cache");
38+
server.sendHeader("Set-Cookie","ESPSESSIONID=0");
39+
server.send(301);
3840
return;
3941
}
4042
if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){
4143
if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin" ){
42-
String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=1\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n";
43-
server.sendContent(header);
44+
server.sendHeader("Location","/");
45+
server.sendHeader("Cache-Control","no-cache");
46+
server.sendHeader("Set-Cookie","ESPSESSIONID=1");
47+
server.send(301);
4448
Serial.println("Log in Successful");
4549
return;
4650
}
@@ -60,8 +64,9 @@ void handleRoot(){
6064
Serial.println("Enter handleRoot");
6165
String header;
6266
if (!is_authentified()){
63-
String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
64-
server.sendContent(header);
67+
server.sendHeader("Location","/login");
68+
server.sendHeader("Cache-Control","no-cache");
69+
server.send(301);
6570
return;
6671
}
6772
String content = "<html><body><H2>hello, you successfully connected to esp8266!</H2><br>";

examples/WebUpdate/WebUpdate.ino

+3-5
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@ void setup(void){
2424
MDNS.begin(host);
2525
server.on("/", HTTP_GET, [](){
2626
server.sendHeader("Connection", "close");
27-
server.sendHeader("Access-Control-Allow-Origin", "*");
2827
server.send(200, "text/html", serverIndex);
2928
});
3029
server.on("/update", HTTP_POST, [](){
3130
server.sendHeader("Connection", "close");
32-
server.sendHeader("Access-Control-Allow-Origin", "*");
3331
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
3432
ESP.restart();
3533
},[](){
@@ -58,14 +56,14 @@ void setup(void){
5856
});
5957
server.begin();
6058
MDNS.addService("http", "tcp", 80);
61-
59+
6260
Serial.printf("Ready! Open http://%s.local in your browser\n", host);
6361
} else {
6462
Serial.println("WiFi Failed");
6563
}
6664
}
67-
65+
6866
void loop(void){
6967
server.handleClient();
7068
delay(1);
71-
}
69+
}

src/ESP8266WebServer.cpp

+44-7
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const char * AUTHORIZATION_HEADER = "Authorization";
4141
ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
4242
: _server(addr, port)
4343
, _currentMethod(HTTP_ANY)
44+
, _currentVersion(0)
4445
, _currentHandler(0)
4546
, _firstHandler(0)
4647
, _lastHandler(0)
@@ -49,12 +50,14 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
4950
, _headerKeysCount(0)
5051
, _currentHeaders(0)
5152
, _contentLength(0)
53+
, _chunked(false)
5254
{
5355
}
5456

5557
ESP8266WebServer::ESP8266WebServer(int port)
5658
: _server(port)
5759
, _currentMethod(HTTP_ANY)
60+
, _currentVersion(0)
5861
, _currentHandler(0)
5962
, _firstHandler(0)
6063
, _lastHandler(0)
@@ -63,6 +66,7 @@ ESP8266WebServer::ESP8266WebServer(int port)
6366
, _headerKeysCount(0)
6467
, _currentHeaders(0)
6568
, _contentLength(0)
69+
, _chunked(false)
6670
{
6771
}
6872

@@ -246,7 +250,7 @@ void ESP8266WebServer::setContentLength(size_t contentLength) {
246250
}
247251

248252
void ESP8266WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) {
249-
response = "HTTP/1.1 ";
253+
response = "HTTP/1."+String(_currentVersion)+" ";
250254
response += String(code);
251255
response += " ";
252256
response += _responseCodeToString(code);
@@ -260,9 +264,13 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co
260264
sendHeader("Content-Length", String(contentLength));
261265
} else if (_contentLength != CONTENT_LENGTH_UNKNOWN) {
262266
sendHeader("Content-Length", String(_contentLength));
267+
} else if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ //HTTP/1.1 or above client
268+
//let's do chunked
269+
_chunked = true;
270+
sendHeader("Accept-Ranges","none");
271+
sendHeader("Transfer-Encoding","chunked");
263272
}
264273
sendHeader("Connection", "close");
265-
sendHeader("Access-Control-Allow-Origin", "*");
266274

267275
response += _responseHeaders;
268276
response += "\r\n";
@@ -271,9 +279,13 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co
271279

272280
void ESP8266WebServer::send(int code, const char* content_type, const String& content) {
273281
String header;
282+
// Can we asume the following?
283+
//if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET)
284+
// _contentLength = CONTENT_LENGTH_UNKNOWN;
274285
_prepareHeader(header, code, content_type, content.length());
275-
sendContent(header);
276-
sendContent(content);
286+
_currentClient.write(header.c_str(), header.length());
287+
if(content.length())
288+
sendContent(content);
277289
}
278290

279291
void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content) {
@@ -287,7 +299,7 @@ void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content) {
287299
char type[64];
288300
memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type));
289301
_prepareHeader(header, code, (const char* )type, contentLength);
290-
sendContent(header);
302+
_currentClient.write(header.c_str(), header.length());
291303
sendContent_P(content);
292304
}
293305

@@ -309,15 +321,40 @@ void ESP8266WebServer::send(int code, const String& content_type, const String&
309321
}
310322

311323
void ESP8266WebServer::sendContent(const String& content) {
312-
_currentClient.write(content.c_str(), content.length());
324+
const char * footer = "\r\n";
325+
size_t len = content.length();
326+
if(_chunked) {
327+
char * chunkSize = (char *)malloc(11);
328+
if(chunkSize){
329+
sprintf(chunkSize, "%x%s", len, footer);
330+
_currentClient.write(chunkSize, strlen(chunkSize));
331+
free(chunkSize);
332+
}
333+
}
334+
_currentClient.write(content.c_str(), len);
335+
if(_chunked){
336+
_currentClient.write(footer, 2);
337+
}
313338
}
314339

315340
void ESP8266WebServer::sendContent_P(PGM_P content) {
316-
_currentClient.write_P(content, strlen_P(content));
341+
sendContent_P(content, strlen_P(content));
317342
}
318343

319344
void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) {
345+
const char * footer = "\r\n";
346+
if(_chunked) {
347+
char * chunkSize = (char *)malloc(11);
348+
if(chunkSize){
349+
sprintf(chunkSize, "%x%s", size, footer);
350+
_currentClient.write(chunkSize, strlen(chunkSize));
351+
free(chunkSize);
352+
}
353+
}
320354
_currentClient.write_P(content, size);
355+
if(_chunked){
356+
_currentClient.write(footer, 2);
357+
}
321358
}
322359

323360

src/ESP8266WebServer.h

+2
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ template<typename T> size_t streamFile(T &file, const String& contentType){
156156
WiFiClient _currentClient;
157157
HTTPMethod _currentMethod;
158158
String _currentUri;
159+
uint8_t _currentVersion;
159160
HTTPClientStatus _currentStatus;
160161
unsigned long _statusChange;
161162

@@ -175,6 +176,7 @@ template<typename T> size_t streamFile(T &file, const String& contentType){
175176
String _responseHeaders;
176177

177178
String _hostHeader;
179+
bool _chunked;
178180

179181
};
180182

src/Parsing.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,16 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
8686

8787
String methodStr = req.substring(0, addr_start);
8888
String url = req.substring(addr_start + 1, addr_end);
89+
String versionEnd = req.substring(addr_end + 8);
90+
_currentVersion = atoi(versionEnd.c_str());
8991
String searchStr = "";
9092
int hasSearch = url.indexOf('?');
9193
if (hasSearch != -1){
9294
searchStr = url.substring(hasSearch + 1);
9395
url = url.substring(0, hasSearch);
9496
}
9597
_currentUri = url;
98+
_chunked = false;
9699

97100
HTTPMethod method = HTTP_GET;
98101
if (methodStr == "POST") {

0 commit comments

Comments
 (0)