1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-22 21:23:07 +03:00

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
This commit is contained in:
Me No Dev 2016-06-28 09:35:12 +03:00 committed by Ivan Grokhotkov
parent 6d3109e8c7
commit 6390cf6bd6
5 changed files with 66 additions and 21 deletions

View File

@ -33,14 +33,18 @@ void handleLogin(){
} }
if (server.hasArg("DISCONNECT")){ if (server.hasArg("DISCONNECT")){
Serial.println("Disconnection"); 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.sendHeader("Location","/login");
server.sendContent(header); server.sendHeader("Cache-Control","no-cache");
server.sendHeader("Set-Cookie","ESPSESSIONID=0");
server.send(301);
return; return;
} }
if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){ if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){
if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin" ){ 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.sendHeader("Location","/");
server.sendContent(header); server.sendHeader("Cache-Control","no-cache");
server.sendHeader("Set-Cookie","ESPSESSIONID=1");
server.send(301);
Serial.println("Log in Successful"); Serial.println("Log in Successful");
return; return;
} }
@ -60,8 +64,9 @@ void handleRoot(){
Serial.println("Enter handleRoot"); Serial.println("Enter handleRoot");
String header; String header;
if (!is_authentified()){ if (!is_authentified()){
String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n"; server.sendHeader("Location","/login");
server.sendContent(header); server.sendHeader("Cache-Control","no-cache");
server.send(301);
return; return;
} }
String content = "<html><body><H2>hello, you successfully connected to esp8266!</H2><br>"; String content = "<html><body><H2>hello, you successfully connected to esp8266!</H2><br>";

View File

@ -24,12 +24,10 @@ void setup(void){
MDNS.begin(host); MDNS.begin(host);
server.on("/", HTTP_GET, [](){ server.on("/", HTTP_GET, [](){
server.sendHeader("Connection", "close"); server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/html", serverIndex); server.send(200, "text/html", serverIndex);
}); });
server.on("/update", HTTP_POST, [](){ server.on("/update", HTTP_POST, [](){
server.sendHeader("Connection", "close"); server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK"); server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
ESP.restart(); ESP.restart();
},[](){ },[](){

View File

@ -41,6 +41,7 @@ const char * AUTHORIZATION_HEADER = "Authorization";
ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port) ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
: _server(addr, port) : _server(addr, port)
, _currentMethod(HTTP_ANY) , _currentMethod(HTTP_ANY)
, _currentVersion(0)
, _currentHandler(0) , _currentHandler(0)
, _firstHandler(0) , _firstHandler(0)
, _lastHandler(0) , _lastHandler(0)
@ -49,12 +50,14 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
, _headerKeysCount(0) , _headerKeysCount(0)
, _currentHeaders(0) , _currentHeaders(0)
, _contentLength(0) , _contentLength(0)
, _chunked(false)
{ {
} }
ESP8266WebServer::ESP8266WebServer(int port) ESP8266WebServer::ESP8266WebServer(int port)
: _server(port) : _server(port)
, _currentMethod(HTTP_ANY) , _currentMethod(HTTP_ANY)
, _currentVersion(0)
, _currentHandler(0) , _currentHandler(0)
, _firstHandler(0) , _firstHandler(0)
, _lastHandler(0) , _lastHandler(0)
@ -63,6 +66,7 @@ ESP8266WebServer::ESP8266WebServer(int port)
, _headerKeysCount(0) , _headerKeysCount(0)
, _currentHeaders(0) , _currentHeaders(0)
, _contentLength(0) , _contentLength(0)
, _chunked(false)
{ {
} }
@ -246,7 +250,7 @@ void ESP8266WebServer::setContentLength(size_t contentLength) {
} }
void ESP8266WebServer::_prepareHeader(String& response, int code, const char* content_type, 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 += String(code);
response += " "; response += " ";
response += _responseCodeToString(code); response += _responseCodeToString(code);
@ -260,9 +264,13 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co
sendHeader("Content-Length", String(contentLength)); sendHeader("Content-Length", String(contentLength));
} else if (_contentLength != CONTENT_LENGTH_UNKNOWN) { } else if (_contentLength != CONTENT_LENGTH_UNKNOWN) {
sendHeader("Content-Length", String(_contentLength)); 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");
} }
sendHeader("Connection", "close"); sendHeader("Connection", "close");
sendHeader("Access-Control-Allow-Origin", "*");
response += _responseHeaders; response += _responseHeaders;
response += "\r\n"; response += "\r\n";
@ -271,8 +279,12 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co
void ESP8266WebServer::send(int code, const char* content_type, const String& content) { void ESP8266WebServer::send(int code, const char* content_type, const String& content) {
String header; String header;
// 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()); _prepareHeader(header, code, content_type, content.length());
sendContent(header); _currentClient.write(header.c_str(), header.length());
if(content.length())
sendContent(content); sendContent(content);
} }
@ -287,7 +299,7 @@ void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content) {
char type[64]; char type[64];
memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type)); memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type));
_prepareHeader(header, code, (const char* )type, contentLength); _prepareHeader(header, code, (const char* )type, contentLength);
sendContent(header); _currentClient.write(header.c_str(), header.length());
sendContent_P(content); sendContent_P(content);
} }
@ -309,15 +321,40 @@ void ESP8266WebServer::send(int code, const String& content_type, const String&
} }
void ESP8266WebServer::sendContent(const String& content) { void ESP8266WebServer::sendContent(const String& content) {
_currentClient.write(content.c_str(), content.length()); const char * footer = "\r\n";
size_t len = content.length();
if(_chunked) {
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(_chunked){
_currentClient.write(footer, 2);
}
} }
void ESP8266WebServer::sendContent_P(PGM_P content) { 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) { void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) {
const char * footer = "\r\n";
if(_chunked) {
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); _currentClient.write_P(content, size);
if(_chunked){
_currentClient.write(footer, 2);
}
} }

View File

@ -156,6 +156,7 @@ protected:
WiFiClient _currentClient; WiFiClient _currentClient;
HTTPMethod _currentMethod; HTTPMethod _currentMethod;
String _currentUri; String _currentUri;
uint8_t _currentVersion;
HTTPClientStatus _currentStatus; HTTPClientStatus _currentStatus;
unsigned long _statusChange; unsigned long _statusChange;
@ -175,6 +176,7 @@ protected:
String _responseHeaders; String _responseHeaders;
String _hostHeader; String _hostHeader;
bool _chunked;
}; };

View File

@ -86,6 +86,8 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
String methodStr = req.substring(0, addr_start); String methodStr = req.substring(0, addr_start);
String url = req.substring(addr_start + 1, addr_end); String url = req.substring(addr_start + 1, addr_end);
String versionEnd = req.substring(addr_end + 8);
_currentVersion = atoi(versionEnd.c_str());
String searchStr = ""; String searchStr = "";
int hasSearch = url.indexOf('?'); int hasSearch = url.indexOf('?');
if (hasSearch != -1){ if (hasSearch != -1){
@ -93,6 +95,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
url = url.substring(0, hasSearch); url = url.substring(0, hasSearch);
} }
_currentUri = url; _currentUri = url;
_chunked = false;
HTTPMethod method = HTTP_GET; HTTPMethod method = HTTP_GET;
if (methodStr == "POST") { if (methodStr == "POST") {