From 92b648fa678f878dfe5e4865308235d6849b63a6 Mon Sep 17 00:00:00 2001 From: anschrammh Date: Sun, 31 Mar 2019 19:02:40 +0200 Subject: [PATCH] Added new private methods and updated server capabilities --- src/app/WEBServerManager.cpp | 155 ++++++++++++++++++++++++++++++++++- src/app/WEBServerManager.h | 6 ++ 2 files changed, 158 insertions(+), 3 deletions(-) diff --git a/src/app/WEBServerManager.cpp b/src/app/WEBServerManager.cpp index 9058a28..6ce45a7 100644 --- a/src/app/WEBServerManager.cpp +++ b/src/app/WEBServerManager.cpp @@ -17,13 +17,13 @@ boolean WEBServerManager::runServer() if(_wifiClient) { _clientState = NEW; - _clientTimeout = millis(); #ifdef DEBUG Serial.println("Client connected !!!"); #endif } break; case NEW: + _clientTimeout = millis(); _clientState = NOT_HANDLED; break; case NOT_HANDLED: @@ -34,17 +34,21 @@ boolean WEBServerManager::runServer() Serial.println("Client timed out !!!"); #endif } + parseQuery(&_wifiClient); + break; case QUERY_PARSED: + #ifdef DEBUG + Serial.println("Sending response !!!"); + #endif + sendPageToClientFromSdCard(&_wifiClient); _clientState = RESPONSE_SENT; break; case RESPONSE_SENT: #ifdef DEBUG Serial.println("Client handled !!!"); #endif - _wifiClient.print(F("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n\r\n\r\n

Response !!!

")); - _clientState = HANDLED; break; case HANDLED: @@ -203,6 +207,151 @@ char *WEBServerManager::addChar(char *pointer, const char character) return pointer; } +boolean WEBServerManager::sendPageToClientFromSdCard(WiFiClient *wifiClient) +{ + if(_sdCardManager != NULL) + { + File pageToSend; + char readChar(0), *filePath(NULL), *header(NULL); + + //We check what kind of http verb it is + switch(_httpRequestData.HRM) + { + case GET: + filePath = getFilePathByHttpResource(_httpRequestData.httpResource); + if(filePath == NULL) + { + wifiClient->print(F("HTTP/1.1 500 OK\r\nContent-Type: text/html\r\n\r\n\r\n\r\n

Failed to malloc filePath

\r\n")); + return false; + } + + #ifdef DEBUG + Serial.print("FILE PATH : "); + Serial.println(filePath); + #endif + + pageToSend = _sdCardManager->open(filePath); + free(filePath);filePath = NULL; + + if(!pageToSend) + { + char *response(NULL); + response = (char *) malloc(sizeof(char) * (strlen("HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n\r\n\r\n

Page not found for :

\r\n

\r\n") + strlen(_httpRequestData.httpResource) + 1)); + if(response == NULL) + { + wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n\r\n\r\n

Failed to malloc filePath

\r\n")); + return false; + } + sprintf(response, "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n\r\n\r\n

Page not found for :

\r\n

%s

\r\n", _httpRequestData.httpResource); + wifiClient->print(response); + free(response);response = NULL; + return false; + } + + #ifdef DEBUG + Serial.print("FILE SIZE : "); + Serial.println(pageToSend.size()); + Serial.print("FILE NAME : "); + Serial.println(pageToSend.name()); + Serial.print("FILE EXTENSION : "); + Serial.println(getFileExtension(pageToSend.name())); + #endif + + header = getHTTPHeader(getMIMETypeByExtension(getFileExtension(pageToSend.name())), pageToSend.size()); + if(header == NULL) + { + wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n\r\n\r\n

Failed to malloc filePath

\r\n")); + pageToSend.close(); + return false; + } + + wifiClient->print(header); + free(header);header = NULL; + + while(pageToSend.available()) + { + readChar = (char) pageToSend.read(); + wifiClient->write(readChar); + } + + pageToSend.close(); + break; + default://If not supported + wifiClient->print(F("HTTP/1.1 405 Method Not Allowed\r\nContent-Type: text/html\r\n\r\n\r\n\r\n

Method Not Allowed

\r\n")); + break; + } + }else + { + //Test if it does correspond to a user defined API call + + wifiClient->print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\n\r\n\r\n

SDCardManager is NULL
Check code

\r\n")); + } + + return true; +} + +WEBServerManager::HttpMIMEType WEBServerManager::getMIMETypeByExtension(const char *extension) +{ + //TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT + if(strcmp(extension,"web") == 0) return TEXT_HTML; + else if(strcmp(extension,"css") == 0) return TEXT_CSS; + else if(strcmp(extension,"js") == 0) return TEXT_JAVASCRIPT; + else return TEXT_PLAIN; +} + +char *WEBServerManager::getHTTPHeader(HttpMIMEType httpMIMEType, unsigned long size) +{ + char *header = (char *) malloc(sizeof(char) + strlen("HTTP/1.1 200 OK\r\nContent-Type: \r\nContent-Length: \r\n\r\n") + 74/*Longest MIME-TYPE*/ + 10 /*Max unsigned long footprint*/ + 1); + + switch(httpMIMEType) + { + case TEXT_HTML: + sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/html",size); + break; + case TEXT_CSS: + sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/css",size); + break; + case TEXT_JAVASCRIPT: + sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/javascript",size); + break; + case TEXT_PLAIN: + sprintf(header,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %lu\r\n\r\n","text/plain",size); + break; + default: + break; + } + + return header; +} + +char *WEBServerManager::getFileExtension(char *name) +{ + if(name == NULL)return ""; + + char *ptr(name); + int index(0); + while(ptr[index] != '\0') + { + if(ptr[++index] == '.') + { + return (name + index +1); + } + } + return ""; +} + +char *WEBServerManager::getFilePathByHttpResource(const char *res) +{ + char *filePath = (char*) malloc( sizeof(char) * (strlen(WWW_DIR)+ strlen(strcmp(res, "/") == 0 ? "/index.web":res) + 1) ); //Do not forget \0 + + if(filePath == NULL) + return NULL; + + sprintf(filePath,"%s%s",WWW_DIR, strcmp(_httpRequestData.httpResource, "/") == 0 ? "/index.web":_httpRequestData.httpResource); + + return filePath; +} + WEBServerManager::HttpRequestMethod WEBServerManager::getHttpVerbEnumValue(const char *parseBuffer) { //UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH diff --git a/src/app/WEBServerManager.h b/src/app/WEBServerManager.h index eb15056..f33d299 100644 --- a/src/app/WEBServerManager.h +++ b/src/app/WEBServerManager.h @@ -19,6 +19,7 @@ class WEBServerManager enum HttpRequestMethod {UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH}; enum HttpVersion {UNKNOWN, HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0}; enum HttpParserStatus {INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_VER_SECTION, BODY_SECTION, IGNORED, ERROR}; + enum HttpMIMEType{TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT}; struct HttpRequestData{ HttpRequestMethod HRM; @@ -27,9 +28,14 @@ class WEBServerManager char *httpBody; }; boolean parseQuery(WiFiClient *wifiClient); + boolean sendPageToClientFromSdCard(WiFiClient *wifiClient); char *addChar(char *pointer, const char character); HttpRequestMethod getHttpVerbEnumValue(const char *parseBuffer); HttpVersion getHttpVersionEnumValue(const char *parseBuffer); + char *getFilePathByHttpResource(const char *res); + char *getFileExtension(char *name); + HttpMIMEType getMIMETypeByExtension(const char *extension); + char *getHTTPHeader(HttpMIMEType httpMIMEType, unsigned long size); WiFiServer _wifiServer; WiFiClient _wifiClient;//One client only, maybe replaced with a fifo in the future