ESP3D  3.0
Firmware for ESP boards connected to 3D Printer
http_server.cpp
Go to the documentation of this file.
1 /*
2  http_server.cpp - http server functions class
3 
4  Copyright (c) 2014 Luc Lebosse. All rights reserved.
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 
21 
22 #include "../../include/esp3d_config.h"
23 
24 #if defined (HTTP_FEATURE)
25 #if defined (ARDUINO_ARCH_ESP32)
26 #include <WebServer.h>
27 #endif //ARDUINO_ARCH_ESP32
28 #if defined (ARDUINO_ARCH_ESP8266)
29 #include <ESP8266WebServer.h>
30 #endif //ARDUINO_ARCH_ESP8266
31 #include "http_server.h"
32 #include "../authentication/authentication_service.h"
33 #include "../../core/settings_esp3d.h"
34 #include "../filesystem/esp_filesystem.h"
35 #include "../websocket/websocket_server.h"
36 
37 bool HTTP_Server::_started = false;
38 uint16_t HTTP_Server::_port = 0;
39 WEBSERVER * HTTP_Server::_webserver = nullptr;
40 uint8_t HTTP_Server::_upload_status = UPLOAD_STATUS_NONE;
41 
43 {
44 }
46 {
47  end();
48 }
49 
50 void HTTP_Server::init_handlers()
51 {
52  _webserver->on("/",HTTP_ANY, handle_root);
53  //Page not found handler
54  _webserver->onNotFound (handle_not_found);
55  //web commands
56  _webserver->on ("/command", HTTP_ANY, handle_web_command);
57  //config
58  _webserver->on ("/config", HTTP_ANY, handle_config);
59  //need to be there even no authentication to say to UI no authentication
60  _webserver->on("/login", HTTP_ANY, handle_login);
61 #ifdef FILESYSTEM_FEATURE
62  //FileSystem
63  _webserver->on ("/files", HTTP_ANY, handleFSFileList, FSFileupload);
64 #endif //FILESYSTEM_FEATURE
65 #ifdef SD_DEVICE
66  //SD
67  _webserver->on ("/sdfiles", HTTP_ANY, handleSDFileList, SDFileupload);
68 #endif //SD_DEVICE
69 #ifdef WEB_UPDATE_FEATURE
70  //web update
71  _webserver->on ("/updatefw", HTTP_ANY, handleUpdate, WebUpdateUpload);
72 #endif //WEB_UPDATE_FEATURE
73 #ifdef SSDP_FEATURE
74  if(WiFi.getMode() != WIFI_AP) {
75  _webserver->on("/description.xml", HTTP_GET, handle_SSDP);
76  }
77 #endif
78 #ifdef CAPTIVE_PORTAL_FEATURE
79  if(WiFi.getMode() == WIFI_AP) {
80  _webserver->on ("/generate_204", HTTP_ANY, handle_root);
81  _webserver->on ("/gconnectivitycheck.gstatic.com", HTTP_ANY, handle_root);
82  //do not forget the / at the end
83  _webserver->on ("/fwlink/", HTTP_ANY, handle_root);
84  }
85 #endif
86 }
87 
88 bool HTTP_Server::StreamFSFile(const char* filename, const char * contentType)
89 {
90  ESP_File datafile = ESP_FileSystem::open(filename);
91  if (!datafile) {
92  return false;
93  }
94  size_t totalFileSize = datafile.size();
95  size_t i = 0;
96  bool done = false;
97  _webserver->setContentLength(totalFileSize);
98  _webserver->send(200, contentType, "");
99  uint8_t buf[1024];
100  while (!done) {
101  Hal::wait(0);
102  int v = datafile.read(buf,1024);
103  if ((v == -1) || (v == 0)) {
104  done = true;
105  } else {
106  _webserver->client().write(buf,v);
107  i+=v;
108  }
109  if (i >= totalFileSize) {
110  done = true;
111  }
112  }
113  datafile.close();
114  if ( i != totalFileSize) {
115  return false;
116  }
117  return true;
118 }
119 
120 void HTTP_Server::pushError(int code, const char * st, bool web_error, uint16_t timeout)
121 {
122  if (websocket_terminal_server.started() && st) {
123  String s = "ERROR:" + String(code) + ":";
124  s+=st;
126  if (web_error != 0) {
127  if (_webserver) {
128  if (_webserver->client().available() > 0) {
129  _webserver->send (web_error, "text/xml", st);
130  }
131  }
132  }
133  uint32_t t = millis();
134  while (millis() - t < timeout) {
136  Hal::wait(10);
137  }
138  }
139 }
140 
141 void HTTP_Server::cancelUpload()
142 {
143  HTTPUpload& upload = _webserver->upload();
144  upload.status = UPLOAD_FILE_ABORTED;
145 #if defined ( ARDUINO_ARCH_ESP8266)
146  _webserver->client().stopAll();
147 #else
148  errno = ECONNABORTED;
149  _webserver->client().stop();
150 #endif
151  Hal::wait(100);
152 }
153 
154 
156 {
157  bool no_error = true;
158  end();
160  return no_error;
161  }
163  _webserver= new WEBSERVER(_port);
164  if (!_webserver) {
165  return false;
166  }
167 
168  init_handlers();
169 #ifdef AUTHENTICATION_FEATURE
170  //here the list of headers to be recorded
171  //Autrization is already added
172  const char * headerkeys[] = {"Cookie"} ;
173  size_t headerkeyssize = sizeof (headerkeys) / sizeof (char*);
174  //ask server to track these headers
175  _webserver->collectHeaders (headerkeys, headerkeyssize );
176 #endif
177  _webserver->begin();
178 #ifdef AUTHENTICATION_FEATURE
179  AuthenticationService::begin(_webserver);
180 #endif //AUTHENTICATION_FEATURE
181 
182  _started = no_error;
183  return no_error;
184 }
185 
187 {
188  _started = false;
189  _upload_status = UPLOAD_STATUS_NONE;
190 #ifdef AUTHENTICATION_FEATURE
191  AuthenticationService::end();
192 #endif //AUTHENTICATION_FEATURE
193  if (_webserver) {
194  _webserver->stop();
195  delete _webserver;
196  _webserver = NULL;
197  }
198 }
199 
201 {
202  if (_started) {
203  if (_webserver) {
204  _webserver->handleClient();
205  }
206  }
207 }
208 
209 const char * HTTP_Server::get_Splited_Value(String data, char separator, int index)
210 {
211  int found = 0;
212  int strIndex[] = {0, -1};
213  int maxIndex = data.length()-1;
214 
215  for(int i=0; i<=maxIndex && found<=index; i++) {
216  if(data.charAt(i)==separator || i==maxIndex) {
217  found++;
218  strIndex[0] = strIndex[1]+1;
219  strIndex[1] = (i == maxIndex) ? i+1 : i;
220  }
221  }
222 
223  return found>index ? data.substring(strIndex[0], strIndex[1]).c_str() : "";
224 }
225 
226 //helper to extract content type from file extension
227 //Check what is the content tye according extension file
228 const char* HTTP_Server::getContentType (const char* filename)
229 {
230  String file_name = filename;
231  file_name.toLowerCase();
232  if (file_name.endsWith (".htm") ) {
233  return "text/html";
234  } else if (file_name.endsWith (".html") ) {
235  return "text/html";
236  } else if (file_name.endsWith (".css") ) {
237  return "text/css";
238  } else if (file_name.endsWith (".js") ) {
239  return "application/javascript";
240  } else if (file_name.endsWith (".png") ) {
241  return "image/png";
242  } else if (file_name.endsWith (".gif") ) {
243  return "image/gif";
244  } else if (file_name.endsWith (".jpeg") ) {
245  return "image/jpeg";
246  } else if (file_name.endsWith (".jpg") ) {
247  return "image/jpeg";
248  } else if (file_name.endsWith (".ico") ) {
249  return "image/x-icon";
250  } else if (file_name.endsWith (".xml") ) {
251  return "text/xml";
252  } else if (file_name.endsWith (".pdf") ) {
253  return "application/x-pdf";
254  } else if (file_name.endsWith (".zip") ) {
255  return "application/x-zip";
256  } else if (file_name.endsWith (".gz") ) {
257  return "application/x-gzip";
258  } else if (file_name.endsWith (".txt") ) {
259  return "text/plain";
260  }
261  return "application/octet-stream";
262 }
263 
264 #endif // Enable HTTP
265 
ESP_File::close
void close()
ESP_HTTP_PORT
#define ESP_HTTP_PORT
Definition: settings_esp3d.h:52
Hal::wait
static void wait(uint32_t milliseconds)
Definition: hal.cpp:226
http_server.h
HTTP_Server::~HTTP_Server
~HTTP_Server()
Definition: http_server.cpp:45
WebSocket_Server::get_currentID
uint8_t get_currentID()
Definition: websocket_server.cpp:205
HTTP_Server::begin
static bool begin()
Definition: http_server.cpp:155
websocket_terminal_server
WebSocket_Server websocket_terminal_server
Definition: websocket_server.cpp:33
WebSocket_Server::started
bool started()
Definition: websocket_server.h:74
WebSocket_Server::pushMSG
void pushMSG(const char *data)
Definition: websocket_server.cpp:37
HTTP_Server::end
static void end()
Definition: http_server.cpp:186
ESP_HTTP_ON
#define ESP_HTTP_ON
Definition: settings_esp3d.h:65
UPLOAD_STATUS_NONE
@ UPLOAD_STATUS_NONE
Definition: http_server.h:38
ESP_File
Definition: esp_filesystem.h:30
ESP_File::read
int read()
Definition: esp_filesystem.cpp:172
Settings_ESP3D::read_uint32
static uint32_t read_uint32(int pos, bool *haserror=NULL)
Definition: settings_esp3d.cpp:919
HTTP_Server::HTTP_Server
HTTP_Server()
Definition: http_server.cpp:42
WebSocket_Server::handle
void handle()
Definition: websocket_server.cpp:295
Settings_ESP3D::read_byte
static uint8_t read_byte(int pos, bool *haserror=NULL)
Definition: settings_esp3d.cpp:715
ESP_File::size
size_t size()
Definition: esp_filesystem.cpp:138
HTTP_Server::handle
static void handle()
Definition: http_server.cpp:200
ESP_FileSystem::open
static ESP_File open(const char *path, uint8_t mode=ESP_FILE_READ)