Subversion Repositories ESP8266_P1_Meter

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 raymond 1
// SPDX-License-Identifier: LGPL-3.0-or-later
2
// Copyright 2016-2026 Hristo Gochkov, Mathieu Carbou, Emil Muratov, Will Miles
3
 
4
#include "ESPAsyncWebServer.h"
5
#include "WebHandlerImpl.h"
6
 
7
#include <string>
8
#include <utility>
9
 
10
#if defined(ESP32) || defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_RP2040) || defined(PICO_RP2350) || defined(LIBRETINY) || defined(HOST)
11
#include <WiFi.h>
12
#elif defined(ESP8266)
13
#include <ESP8266WiFi.h>
14
#else
15
#error Platform not supported
16
#endif
17
 
18
using namespace asyncsrv;
19
 
20
bool ON_STA_FILTER(AsyncWebServerRequest *request) {
21
#if ASYNCWEBSERVER_WIFI_SUPPORTED
22
  return WiFi.localIP() == request->client()->localIP();
23
#else
24
  return false;
25
#endif
26
}
27
 
28
bool ON_AP_FILTER(AsyncWebServerRequest *request) {
29
#if ASYNCWEBSERVER_WIFI_SUPPORTED
30
  return WiFi.localIP() != request->client()->localIP();
31
#else
32
  return false;
33
#endif
34
}
35
 
36
#ifndef HAVE_FS_FILE_OPEN_MODE
37
const char *fs::FileOpenMode::read = "r";
38
const char *fs::FileOpenMode::write = "w";
39
const char *fs::FileOpenMode::append = "a";
40
#endif
41
 
42
AsyncWebServer::AsyncWebServer(uint16_t port) : _server(port) {
43
  _catchAllHandler = new AsyncCallbackWebHandler();
44
  _server.onClient(
45
    [](void *s, AsyncClient *c) {
46
      if (c == NULL) {
47
        return;
48
      }
49
      c->setRxTimeout(3);
50
      AsyncWebServerRequest *r = new AsyncWebServerRequest((AsyncWebServer *)s, c);
51
      if (r == NULL) {
52
        c->abort();
53
        delete c;
54
      }
55
    },
56
    this
57
  );
58
}
59
 
60
AsyncWebServer::~AsyncWebServer() {
61
  reset();
62
  end();
63
  delete _catchAllHandler;
64
  _catchAllHandler = nullptr;  // Prevent potential use-after-free
65
}
66
 
67
AsyncWebRewrite &AsyncWebServer::addRewrite(std::shared_ptr<AsyncWebRewrite> rewrite) {
68
  _rewrites.emplace_back(rewrite);
69
  return *_rewrites.back().get();
70
}
71
 
72
AsyncWebRewrite &AsyncWebServer::addRewrite(AsyncWebRewrite *rewrite) {
73
  _rewrites.emplace_back(rewrite);
74
  return *_rewrites.back().get();
75
}
76
 
77
bool AsyncWebServer::removeRewrite(AsyncWebRewrite *rewrite) {
78
  return removeRewrite(rewrite->from().c_str(), rewrite->toUrl().c_str());
79
}
80
 
81
bool AsyncWebServer::removeRewrite(const char *from, const char *to) {
82
  for (auto r = _rewrites.begin(); r != _rewrites.end(); ++r) {
83
    if (r->get()->from() == from && r->get()->toUrl() == to) {
84
      _rewrites.erase(r);
85
      return true;
86
    }
87
  }
88
  return false;
89
}
90
 
91
AsyncWebRewrite &AsyncWebServer::rewrite(const char *from, const char *to) {
92
  _rewrites.emplace_back(std::make_shared<AsyncWebRewrite>(from, to));
93
  return *_rewrites.back().get();
94
}
95
 
96
AsyncWebHandler &AsyncWebServer::addHandler(AsyncWebHandler *handler) {
97
  _handlers.emplace_back(handler);
98
  return *(_handlers.back().get());
99
}
100
 
101
bool AsyncWebServer::removeHandler(AsyncWebHandler *handler) {
102
  for (auto i = _handlers.begin(); i != _handlers.end(); ++i) {
103
    if (i->get() == handler) {
104
      _handlers.erase(i);
105
      return true;
106
    }
107
  }
108
  return false;
109
}
110
 
111
void AsyncWebServer::begin() {
112
  _server.setNoDelay(true);
113
  _server.begin();
114
}
115
 
116
void AsyncWebServer::end() {
117
  _server.end();
118
}
119
 
120
#if ASYNC_TCP_SSL_ENABLED
121
void AsyncWebServer::onSslFileRequest(AcSSlFileHandler cb, void *arg) {
122
  _server.onSslFileRequest(cb, arg);
123
}
124
 
125
void AsyncWebServer::beginSecure(const char *cert, const char *key, const char *password) {
126
  _server.beginSecure(cert, key, password);
127
}
128
#endif
129
 
130
void AsyncWebServer::_handleDisconnect(AsyncWebServerRequest *request) {
131
  delete request;
132
}
133
 
134
void AsyncWebServer::_rewriteRequest(AsyncWebServerRequest *request) {
135
  // the last rewrite that matches the request will be used
136
  // we do not break the loop to allow for multiple rewrites to be applied and only the last one to be used (allows overriding)
137
  for (const auto &r : _rewrites) {
138
    if (r->match(request)) {
139
      request->_url = r->toUrl();
140
      request->_addGetParams(r->params());
141
    }
142
  }
143
}
144
 
145
void AsyncWebServer::_attachHandler(AsyncWebServerRequest *request) {
146
  for (auto &h : _handlers) {
147
    if (h->filter(request) && h->canHandle(request)) {
148
      request->setHandler(h.get());
149
      return;
150
    }
151
  }
152
  // ESP_LOGD("AsyncWebServer", "No handler found for %s, using _catchAllHandler pointer: %p", request->url().c_str(), _catchAllHandler);
153
  request->setHandler(_catchAllHandler);
154
}
155
 
156
AsyncCallbackWebHandler &AsyncWebServer::on(
157
  AsyncURIMatcher uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody
158
) {
159
  AsyncCallbackWebHandler *handler = new AsyncCallbackWebHandler();
160
  handler->setUri(std::move(uri));
161
  handler->setMethod(std::move(method));
162
  handler->onRequest(onRequest);
163
  handler->onUpload(onUpload);
164
  handler->onBody(onBody);
165
  addHandler(handler);
166
  return *handler;
167
}
168
 
169
#if ASYNC_JSON_SUPPORT == 1
170
AsyncCallbackJsonWebHandler &AsyncWebServer::on(AsyncURIMatcher uri, WebRequestMethodComposite method, ArJsonRequestHandlerFunction onBody) {
171
  AsyncCallbackJsonWebHandler *handler = new AsyncCallbackJsonWebHandler(std::move(uri), onBody);
172
  handler->setMethod(std::move(method));
173
  addHandler(handler);
174
  return *handler;
175
}
176
#endif
177
 
178
AsyncStaticWebHandler &AsyncWebServer::serveStatic(const char *uri, fs::FS &fs, const char *path, const char *cache_control) {
179
  AsyncStaticWebHandler *handler = new AsyncStaticWebHandler(uri, fs, path, cache_control);
180
  addHandler(handler);
181
  return *handler;
182
}
183
 
184
void AsyncWebServer::onNotFound(ArRequestHandlerFunction fn) {
185
  _catchAllHandler->onRequest(fn);
186
}
187
 
188
void AsyncWebServer::onFileUpload(ArUploadHandlerFunction fn) {
189
  _catchAllHandler->onUpload(fn);
190
}
191
 
192
void AsyncWebServer::onRequestBody(ArBodyHandlerFunction fn) {
193
  _catchAllHandler->onBody(fn);
194
}
195
 
196
AsyncWebHandler &AsyncWebServer::catchAllHandler() const {
197
  return *_catchAllHandler;
198
}
199
 
200
void AsyncWebServer::reset() {
201
  _rewrites.clear();
202
  _handlers.clear();
203
 
204
  _catchAllHandler->onRequest(NULL);
205
  _catchAllHandler->onUpload(NULL);
206
  _catchAllHandler->onBody(NULL);
207
}
208
 
209
AsyncURIMatcher::AsyncURIMatcher(String uri, uint16_t modifiers) : _value(std::move(uri)) {
210
#ifdef ASYNCWEBSERVER_REGEX
211
  if (_value.startsWith("^") && _value.endsWith("$")) {
212
    pattern = new std::regex(_value.c_str(), (modifiers & CaseInsensitive) ? (std::regex::icase | std::regex::optimize) : (std::regex::optimize));
213
    return;  // no additional processing - flags are overwritten by pattern pointer
214
  }
215
#endif
216
  if (modifiers & CaseInsensitive) {
217
    _value.toLowerCase();
218
  }
219
  // Inspect _value to set flags
220
  // empty URI matches everything
221
  if (!_value.length()) {
222
    _flags = _toFlags(Type::All, modifiers);
223
  } else if (_value.endsWith("*")) {
224
    // wildcard match with * at the end
225
    _flags = _toFlags(Type::Prefix, modifiers);
226
    _value = _value.substring(0, _value.length() - 1);
227
  } else if (_value.lastIndexOf("/*.") >= 0) {
228
    // prefix match with /*.ext
229
    // matches any path ending with .ext
230
    // e.g. /images/*.png will match /images/pic.png and /images/2023/pic.png but not /img/pic.png
231
    _flags = _toFlags(Type::Extension, modifiers);
232
  } else {
233
    // backward compatible use case: exact match or prefix with trailing /
234
    _flags = _toFlags(Type::BackwardCompatible, modifiers);
235
  }
236
}
237
 
238
AsyncURIMatcher::AsyncURIMatcher(String uri, Type type, uint16_t modifiers) : _value(std::move(uri)), _flags(_toFlags(type, modifiers)) {
239
#ifdef ASYNCWEBSERVER_REGEX
240
  if (type == Type::Regex) {
241
    pattern = new std::regex(_value.c_str(), (modifiers & CaseInsensitive) ? (std::regex::icase | std::regex::optimize) : (std::regex::optimize));
242
    return;  // no additional processing - flags are overwritten by pattern pointer
243
  }
244
#endif
245
  if (modifiers & CaseInsensitive) {
246
    _value.toLowerCase();
247
  }
248
}
249
 
250
#ifdef ASYNCWEBSERVER_REGEX
251
 
252
AsyncURIMatcher::AsyncURIMatcher(const AsyncURIMatcher &c) : _value(c._value), _flags(c._flags) {
253
  if (_isRegex()) {
254
    pattern = new std::regex(*pattern);
255
  }
256
}
257
 
258
AsyncURIMatcher::AsyncURIMatcher(AsyncURIMatcher &&c) : _value(std::move(c._value)), _flags(c._flags) {
259
  c._flags = _toFlags(Type::None, None);
260
}
261
 
262
AsyncURIMatcher::~AsyncURIMatcher() {
263
  if (_isRegex()) {
264
    delete pattern;
265
  }
266
}
267
 
268
AsyncURIMatcher &AsyncURIMatcher::operator=(const AsyncURIMatcher &r) {
269
  _value = r._value;
270
  if (r._isRegex()) {
271
    // Allocate first before we delete our current state
272
    auto p = new std::regex(*r.pattern);
273
    // Safely reassign our pattern
274
    if (_isRegex()) {
275
      delete pattern;
276
    }
277
    pattern = p;
278
  } else {
279
    if (_isRegex()) {
280
      delete pattern;
281
    }
282
    _flags = r._flags;
283
  }
284
  return *this;
285
}
286
 
287
AsyncURIMatcher &AsyncURIMatcher::operator=(AsyncURIMatcher &&r) {
288
  _value = std::move(r._value);
289
  if (_isRegex()) {
290
    delete pattern;
291
  }
292
  _flags = r._flags;
293
  if (r._isRegex()) {
294
    // We have adopted it
295
    r._flags = _toFlags(Type::None, None);
296
  }
297
  return *this;
298
}
299
 
300
#endif
301
 
302
bool AsyncURIMatcher::matches(AsyncWebServerRequest *request) const {
303
#ifdef ASYNCWEBSERVER_REGEX
304
  if (_isRegex()) {
305
    // when type == Type::Regex, or when _value was auto-detected as regex
306
    std::smatch matches;
307
    std::string s(request->url().c_str());
308
    if (std::regex_search(s, matches, *pattern)) {
309
      for (size_t i = 1; i < matches.size(); ++i) {
310
        request->_pathParams.emplace_back(matches[i].str().c_str());
311
      }
312
      return true;
313
    }
314
    return false;
315
  }
316
#endif
317
 
318
  // extract matcher type from _flags
319
  Type type;
320
  uint16_t modifiers;
321
  std::tie(type, modifiers) = _fromFlags(_flags);
322
 
323
  // apply modifiers
324
  String path = request->url();
325
  if (modifiers & CaseInsensitive) {
326
    path.toLowerCase();
327
  }
328
 
329
  switch (type) {
330
    case Type::All:    return true;
331
    case Type::None:   return false;
332
    case Type::Exact:  return (_value == path);
333
    case Type::Prefix: return path.startsWith(_value);
334
    case Type::Extension:
335
    {
336
      int split = _value.lastIndexOf("/*.");
337
      return (split >= 0 && path.startsWith(_value.substring(0, split)) && path.endsWith(_value.substring(split + 2)));
338
    }
339
    case Type::BackwardCompatible: return (_value == path) || path.startsWith(_value + "/");
340
    default:
341
      // Should never happen - programming error
342
      assert("Invalid type");
343
      return false;
344
  }
345
}