WebRequest.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  1. /*
  2. Asynchronous WebServer library for Espressif MCUs
  3. Copyright (c) 2016 Hristo Gochkov. All rights reserved.
  4. This file is part of the esp8266 core for Arduino environment.
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #include "ESPAsyncWebServer.h"
  18. #include "WebResponseImpl.h"
  19. #include "WebAuthentication.h"
  20. #ifndef ESP8266
  21. #define os_strlen strlen
  22. #endif
  23. static const String SharedEmptyString = String();
  24. #define __is_param_char(c) ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '='))
  25. enum { PARSE_REQ_START, PARSE_REQ_HEADERS, PARSE_REQ_BODY, PARSE_REQ_END, PARSE_REQ_FAIL };
  26. AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
  27. : _client(c)
  28. , _server(s)
  29. , _handler(NULL)
  30. , _response(NULL)
  31. , _temp()
  32. , _parseState(0)
  33. , _version(0)
  34. , _method(HTTP_ANY)
  35. , _url()
  36. , _host()
  37. , _contentType()
  38. , _boundary()
  39. , _authorization()
  40. , _reqconntype(RCT_HTTP)
  41. , _isDigest(false)
  42. , _isMultipart(false)
  43. , _isPlainPost(false)
  44. , _expectingContinue(false)
  45. , _contentLength(0)
  46. , _parsedLength(0)
  47. , _headers(AlternativeLinkedList<AsyncWebHeader *>([](AsyncWebHeader *h){ delete h; }))
  48. , _params(AlternativeLinkedList<AsyncWebParameter *>([](AsyncWebParameter *p){ delete p; }))
  49. , _pathParams(AlternativeLinkedList<String *>([](String *p){ delete p; }))
  50. , _multiParseState(0)
  51. , _boundaryPosition(0)
  52. , _itemStartIndex(0)
  53. , _itemSize(0)
  54. , _itemName()
  55. , _itemFilename()
  56. , _itemType()
  57. , _itemValue()
  58. , _itemBuffer(0)
  59. , _itemBufferIndex(0)
  60. , _itemIsFile(false)
  61. , _tempObject(NULL)
  62. {
  63. c->onError([](void *r, AsyncClient* c, int8_t error){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onError(error); }, this);
  64. c->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onAck(len, time); }, this);
  65. c->onDisconnect([](void *r, AsyncClient* c){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onDisconnect(); delete c; }, this);
  66. c->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onTimeout(time); }, this);
  67. c->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onData(buf, len); }, this);
  68. c->onPoll([](void *r, AsyncClient* c){ (void)c; AsyncWebServerRequest *req = ( AsyncWebServerRequest*)r; req->_onPoll(); }, this);
  69. }
  70. AsyncWebServerRequest::~AsyncWebServerRequest(){
  71. _headers.free();
  72. _params.free();
  73. _pathParams.free();
  74. _interestingHeaders.free();
  75. if(_response != NULL){
  76. delete _response;
  77. }
  78. if(_tempObject != NULL){
  79. free(_tempObject);
  80. }
  81. if(_tempFile){
  82. _tempFile.close();
  83. }
  84. }
  85. void AsyncWebServerRequest::_onData(void *buf, size_t len){
  86. size_t i = 0;
  87. while (true) {
  88. if(_parseState < PARSE_REQ_BODY){
  89. // Find new line in buf
  90. char *str = (char*)buf;
  91. for (i = 0; i < len; i++) {
  92. if (str[i] == '\n') {
  93. break;
  94. }
  95. }
  96. if (i == len) { // No new line, just add the buffer in _temp
  97. char ch = str[len-1];
  98. str[len-1] = 0;
  99. _temp.reserve(_temp.length()+len);
  100. _temp.concat(str);
  101. _temp.concat(ch);
  102. } else { // Found new line - extract it and parse
  103. str[i] = 0; // Terminate the string at the end of the line.
  104. _temp.concat(str);
  105. _temp.trim();
  106. _parseLine();
  107. if (++i < len) {
  108. // Still have more buffer to process
  109. buf = str+i;
  110. len-= i;
  111. continue;
  112. }
  113. }
  114. } else if(_parseState == PARSE_REQ_BODY){
  115. // A handler should be already attached at this point in _parseLine function.
  116. // If handler does nothing (_onRequest is NULL), we don't need to really parse the body.
  117. const bool needParse = _handler && !_handler->isRequestHandlerTrivial();
  118. if(_isMultipart){
  119. if(needParse){
  120. size_t i;
  121. for(i=0; i<len; i++){
  122. _parseMultipartPostByte(((uint8_t*)buf)[i], i == len - 1);
  123. _parsedLength++;
  124. }
  125. } else
  126. _parsedLength += len;
  127. } else {
  128. if(_parsedLength == 0){
  129. if(_contentType.startsWith("application/x-www-form-urlencoded")){
  130. _isPlainPost = true;
  131. } else if(_contentType == "text/plain" && __is_param_char(((char*)buf)[0])){
  132. size_t i = 0;
  133. while (i<len && __is_param_char(((char*)buf)[i++]));
  134. if(i < len && ((char*)buf)[i-1] == '='){
  135. _isPlainPost = true;
  136. }
  137. }
  138. }
  139. if(!_isPlainPost) {
  140. //check if authenticated before calling the body
  141. if(_handler) _handler->handleBody(this, (uint8_t*)buf, len, _parsedLength, _contentLength);
  142. _parsedLength += len;
  143. } else if(needParse) {
  144. size_t i;
  145. for(i=0; i<len; i++){
  146. _parsedLength++;
  147. _parsePlainPostChar(((uint8_t*)buf)[i]);
  148. }
  149. } else {
  150. _parsedLength += len;
  151. }
  152. }
  153. if(_parsedLength == _contentLength){
  154. _parseState = PARSE_REQ_END;
  155. //check if authenticated before calling handleRequest and request auth instead
  156. if(_handler) _handler->handleRequest(this);
  157. else send(501);
  158. }
  159. }
  160. break;
  161. }
  162. }
  163. void AsyncWebServerRequest::_removeNotInterestingHeaders(){
  164. if (_interestingHeaders.containsIgnoreCase("ANY")) return; // nothing to do
  165. for(const auto& header: _headers){
  166. if(!_interestingHeaders.containsIgnoreCase(header->name().c_str())){
  167. _headers.remove(header);
  168. }
  169. }
  170. }
  171. void AsyncWebServerRequest::_onPoll(){
  172. //os_printf("p\n");
  173. if(_response != NULL && _client != NULL && _client->canSend() && !_response->_finished()){
  174. _response->_ack(this, 0, 0);
  175. }
  176. }
  177. void AsyncWebServerRequest::_onAck(size_t len, uint32_t time){
  178. //os_printf("a:%u:%u\n", len, time);
  179. if(_response != NULL){
  180. if(!_response->_finished()){
  181. _response->_ack(this, len, time);
  182. } else {
  183. AsyncWebServerResponse* r = _response;
  184. _response = NULL;
  185. delete r;
  186. }
  187. }
  188. }
  189. void AsyncWebServerRequest::_onError(int8_t error){
  190. (void)error;
  191. }
  192. void AsyncWebServerRequest::_onTimeout(uint32_t time){
  193. (void)time;
  194. //os_printf("TIMEOUT: %u, state: %s\n", time, _client->stateToString());
  195. _client->close();
  196. }
  197. void AsyncWebServerRequest::onDisconnect (ArDisconnectHandler fn){
  198. _onDisconnectfn=fn;
  199. }
  200. void AsyncWebServerRequest::_onDisconnect(){
  201. //os_printf("d\n");
  202. if(_onDisconnectfn) {
  203. _onDisconnectfn();
  204. }
  205. _server->_handleDisconnect(this);
  206. }
  207. void AsyncWebServerRequest::_addParam(AsyncWebParameter *p){
  208. _params.add(p);
  209. }
  210. void AsyncWebServerRequest::_addPathParam(const char *p){
  211. _pathParams.add(new String(p));
  212. }
  213. void AsyncWebServerRequest::_addGetParams(const String& params){
  214. size_t start = 0;
  215. while (start < params.length()){
  216. int end = params.indexOf('&', start);
  217. if (end < 0) end = params.length();
  218. int equal = params.indexOf('=', start);
  219. if (equal < 0 || equal > end) equal = end;
  220. String name = params.substring(start, equal);
  221. String value = equal + 1 < end ? params.substring(equal + 1, end) : String();
  222. _addParam(new AsyncWebParameter(urlDecode(name), urlDecode(value)));
  223. start = end + 1;
  224. }
  225. }
  226. bool AsyncWebServerRequest::_parseReqHead(){
  227. // Split the head into method, url and version
  228. int index = _temp.indexOf(' ');
  229. String m = _temp.substring(0, index);
  230. index = _temp.indexOf(' ', index+1);
  231. String u = _temp.substring(m.length()+1, index);
  232. _temp = _temp.substring(index+1);
  233. if(m == "GET"){
  234. _method = HTTP_GET;
  235. } else if(m == "POST"){
  236. _method = HTTP_POST;
  237. } else if(m == "DELETE"){
  238. _method = HTTP_DELETE;
  239. } else if(m == "PUT"){
  240. _method = HTTP_PUT;
  241. } else if(m == "PATCH"){
  242. _method = HTTP_PATCH;
  243. } else if(m == "HEAD"){
  244. _method = HTTP_HEAD;
  245. } else if(m == "OPTIONS"){
  246. _method = HTTP_OPTIONS;
  247. }
  248. String g = String();
  249. index = u.indexOf('?');
  250. if(index > 0){
  251. g = u.substring(index +1);
  252. u = u.substring(0, index);
  253. }
  254. _url = urlDecode(u);
  255. _addGetParams(g);
  256. if(!_temp.startsWith("HTTP/1.0"))
  257. _version = 1;
  258. _temp = String();
  259. return true;
  260. }
  261. bool strContains(String src, String find, bool mindcase = true) {
  262. int pos=0, i=0;
  263. const int slen = src.length();
  264. const int flen = find.length();
  265. if (slen < flen) return false;
  266. while (pos <= (slen - flen)) {
  267. for (i=0; i < flen; i++) {
  268. if (mindcase) {
  269. if (src[pos+i] != find[i]) i = flen + 1; // no match
  270. } else if (tolower(src[pos+i]) != tolower(find[i])) i = flen + 1; // no match
  271. }
  272. if (i == flen) return true;
  273. pos++;
  274. }
  275. return false;
  276. }
  277. bool AsyncWebServerRequest::_parseReqHeader(){
  278. int index = _temp.indexOf(':');
  279. if(index){
  280. String name = _temp.substring(0, index);
  281. String value = _temp.substring(index + 2);
  282. if(name.equalsIgnoreCase("Host")){
  283. _host = value;
  284. } else if(name.equalsIgnoreCase("Content-Type")){
  285. _contentType = value.substring(0, value.indexOf(';'));
  286. if (value.startsWith("multipart/")){
  287. _boundary = value.substring(value.indexOf('=')+1);
  288. _boundary.replace("\"","");
  289. _isMultipart = true;
  290. }
  291. } else if(name.equalsIgnoreCase("Content-Length")){
  292. _contentLength = atoi(value.c_str());
  293. } else if(name.equalsIgnoreCase("Expect") && value == "100-continue"){
  294. _expectingContinue = true;
  295. } else if(name.equalsIgnoreCase("Authorization")){
  296. if(value.length() > 5 && value.substring(0,5).equalsIgnoreCase("Basic")){
  297. _authorization = value.substring(6);
  298. } else if(value.length() > 6 && value.substring(0,6).equalsIgnoreCase("Digest")){
  299. _isDigest = true;
  300. _authorization = value.substring(7);
  301. }
  302. } else {
  303. if(name.equalsIgnoreCase("Upgrade") && value.equalsIgnoreCase("websocket")){
  304. // WebSocket request can be uniquely identified by header: [Upgrade: websocket]
  305. _reqconntype = RCT_WS;
  306. } else {
  307. if(name.equalsIgnoreCase("Accept") && strContains(value, "text/event-stream", false)){
  308. // WebEvent request can be uniquely identified by header: [Accept: text/event-stream]
  309. _reqconntype = RCT_EVENT;
  310. }
  311. }
  312. }
  313. _headers.add(new AsyncWebHeader(name, value));
  314. }
  315. _temp = String();
  316. return true;
  317. }
  318. void AsyncWebServerRequest::_parsePlainPostChar(uint8_t data){
  319. if(data && (char)data != '&')
  320. _temp += (char)data;
  321. if(!data || (char)data == '&' || _parsedLength == _contentLength){
  322. String name = "body";
  323. String value = _temp;
  324. if(!_temp.startsWith("{") && !_temp.startsWith("[") && _temp.indexOf('=') > 0){
  325. name = _temp.substring(0, _temp.indexOf('='));
  326. value = _temp.substring(_temp.indexOf('=') + 1);
  327. }
  328. _addParam(new AsyncWebParameter(urlDecode(name), urlDecode(value), true));
  329. _temp = String();
  330. }
  331. }
  332. void AsyncWebServerRequest::_handleUploadByte(uint8_t data, bool last){
  333. _itemBuffer[_itemBufferIndex++] = data;
  334. if(last || _itemBufferIndex == 1460){
  335. //check if authenticated before calling the upload
  336. if(_handler)
  337. _handler->handleUpload(this, _itemFilename, _itemSize - _itemBufferIndex, _itemBuffer, _itemBufferIndex, false);
  338. _itemBufferIndex = 0;
  339. }
  340. }
  341. enum {
  342. EXPECT_BOUNDARY,
  343. PARSE_HEADERS,
  344. WAIT_FOR_RETURN1,
  345. EXPECT_FEED1,
  346. EXPECT_DASH1,
  347. EXPECT_DASH2,
  348. BOUNDARY_OR_DATA,
  349. DASH3_OR_RETURN2,
  350. EXPECT_FEED2,
  351. PARSING_FINISHED,
  352. PARSE_ERROR
  353. };
  354. void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last){
  355. #define itemWriteByte(b) do { _itemSize++; if(_itemIsFile) _handleUploadByte(b, last); else _itemValue+=(char)(b); } while(0)
  356. if(!_parsedLength){
  357. _multiParseState = EXPECT_BOUNDARY;
  358. _temp = String();
  359. _itemName = String();
  360. _itemFilename = String();
  361. _itemType = String();
  362. }
  363. if(_multiParseState == WAIT_FOR_RETURN1){
  364. if(data != '\r'){
  365. itemWriteByte(data);
  366. } else {
  367. _multiParseState = EXPECT_FEED1;
  368. }
  369. } else if(_multiParseState == EXPECT_BOUNDARY){
  370. if(_parsedLength < 2 && data != '-'){
  371. _multiParseState = PARSE_ERROR;
  372. return;
  373. } else if(_parsedLength - 2 < _boundary.length() && _boundary.c_str()[_parsedLength - 2] != data){
  374. _multiParseState = PARSE_ERROR;
  375. return;
  376. } else if(_parsedLength - 2 == _boundary.length() && data != '\r'){
  377. _multiParseState = PARSE_ERROR;
  378. return;
  379. } else if(_parsedLength - 3 == _boundary.length()){
  380. if(data != '\n'){
  381. _multiParseState = PARSE_ERROR;
  382. return;
  383. }
  384. _multiParseState = PARSE_HEADERS;
  385. _itemIsFile = false;
  386. }
  387. } else if(_multiParseState == PARSE_HEADERS){
  388. if((char)data != '\r' && (char)data != '\n')
  389. _temp += (char)data;
  390. if((char)data == '\n'){
  391. if(_temp.length()){
  392. if(_temp.length() > 12 && _temp.substring(0, 12).equalsIgnoreCase("Content-Type")){
  393. _itemType = _temp.substring(14);
  394. _itemIsFile = true;
  395. } else if(_temp.length() > 19 && _temp.substring(0, 19).equalsIgnoreCase("Content-Disposition")){
  396. _temp = _temp.substring(_temp.indexOf(';') + 2);
  397. while(_temp.indexOf(';') > 0){
  398. String name = _temp.substring(0, _temp.indexOf('='));
  399. String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.indexOf(';') - 1);
  400. if(name == "name"){
  401. _itemName = nameVal;
  402. } else if(name == "filename"){
  403. _itemFilename = nameVal;
  404. _itemIsFile = true;
  405. }
  406. _temp = _temp.substring(_temp.indexOf(';') + 2);
  407. }
  408. String name = _temp.substring(0, _temp.indexOf('='));
  409. String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.length() - 1);
  410. if(name == "name"){
  411. _itemName = nameVal;
  412. } else if(name == "filename"){
  413. _itemFilename = nameVal;
  414. _itemIsFile = true;
  415. }
  416. }
  417. _temp = String();
  418. } else {
  419. _multiParseState = WAIT_FOR_RETURN1;
  420. //value starts from here
  421. _itemSize = 0;
  422. _itemStartIndex = _parsedLength;
  423. _itemValue = String();
  424. if(_itemIsFile){
  425. if(_itemBuffer)
  426. free(_itemBuffer);
  427. _itemBuffer = (uint8_t*)malloc(1460);
  428. if(_itemBuffer == NULL){
  429. _multiParseState = PARSE_ERROR;
  430. return;
  431. }
  432. _itemBufferIndex = 0;
  433. }
  434. }
  435. }
  436. } else if(_multiParseState == EXPECT_FEED1){
  437. if(data != '\n'){
  438. _multiParseState = WAIT_FOR_RETURN1;
  439. itemWriteByte('\r'); _parseMultipartPostByte(data, last);
  440. } else {
  441. _multiParseState = EXPECT_DASH1;
  442. }
  443. } else if(_multiParseState == EXPECT_DASH1){
  444. if(data != '-'){
  445. _multiParseState = WAIT_FOR_RETURN1;
  446. itemWriteByte('\r'); itemWriteByte('\n'); _parseMultipartPostByte(data, last);
  447. } else {
  448. _multiParseState = EXPECT_DASH2;
  449. }
  450. } else if(_multiParseState == EXPECT_DASH2){
  451. if(data != '-'){
  452. _multiParseState = WAIT_FOR_RETURN1;
  453. itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); _parseMultipartPostByte(data, last);
  454. } else {
  455. _multiParseState = BOUNDARY_OR_DATA;
  456. _boundaryPosition = 0;
  457. }
  458. } else if(_multiParseState == BOUNDARY_OR_DATA){
  459. if(_boundaryPosition < _boundary.length() && _boundary.c_str()[_boundaryPosition] != data){
  460. _multiParseState = WAIT_FOR_RETURN1;
  461. itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-');
  462. uint8_t i;
  463. for(i=0; i<_boundaryPosition; i++)
  464. itemWriteByte(_boundary.c_str()[i]);
  465. _parseMultipartPostByte(data, last);
  466. } else if(_boundaryPosition == _boundary.length() - 1){
  467. _multiParseState = DASH3_OR_RETURN2;
  468. if(!_itemIsFile){
  469. _addParam(new AsyncWebParameter(_itemName, _itemValue, true));
  470. } else {
  471. if(_itemSize){
  472. //check if authenticated before calling the upload
  473. if(_handler) _handler->handleUpload(this, _itemFilename, _itemSize - _itemBufferIndex, _itemBuffer, _itemBufferIndex, true);
  474. _itemBufferIndex = 0;
  475. _addParam(new AsyncWebParameter(_itemName, _itemFilename, true, true, _itemSize));
  476. }
  477. free(_itemBuffer);
  478. _itemBuffer = NULL;
  479. }
  480. } else {
  481. _boundaryPosition++;
  482. }
  483. } else if(_multiParseState == DASH3_OR_RETURN2){
  484. if(data == '-' && (_contentLength - _parsedLength - 4) != 0){
  485. //os_printf("ERROR: The parser got to the end of the POST but is expecting %u bytes more!\nDrop an issue so we can have more info on the matter!\n", _contentLength - _parsedLength - 4);
  486. _contentLength = _parsedLength + 4;//lets close the request gracefully
  487. }
  488. if(data == '\r'){
  489. _multiParseState = EXPECT_FEED2;
  490. } else if(data == '-' && _contentLength == (_parsedLength + 4)){
  491. _multiParseState = PARSING_FINISHED;
  492. } else {
  493. _multiParseState = WAIT_FOR_RETURN1;
  494. itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-');
  495. uint8_t i; for(i=0; i<_boundary.length(); i++) itemWriteByte(_boundary.c_str()[i]);
  496. _parseMultipartPostByte(data, last);
  497. }
  498. } else if(_multiParseState == EXPECT_FEED2){
  499. if(data == '\n'){
  500. _multiParseState = PARSE_HEADERS;
  501. _itemIsFile = false;
  502. } else {
  503. _multiParseState = WAIT_FOR_RETURN1;
  504. itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-');
  505. uint8_t i; for(i=0; i<_boundary.length(); i++) itemWriteByte(_boundary.c_str()[i]);
  506. itemWriteByte('\r'); _parseMultipartPostByte(data, last);
  507. }
  508. }
  509. }
  510. void AsyncWebServerRequest::_parseLine(){
  511. if(_parseState == PARSE_REQ_START){
  512. if(!_temp.length()){
  513. _parseState = PARSE_REQ_FAIL;
  514. _client->close();
  515. } else {
  516. _parseReqHead();
  517. _parseState = PARSE_REQ_HEADERS;
  518. }
  519. return;
  520. }
  521. if(_parseState == PARSE_REQ_HEADERS){
  522. if(!_temp.length()){
  523. //end of headers
  524. _server->_rewriteRequest(this);
  525. _server->_attachHandler(this);
  526. _removeNotInterestingHeaders();
  527. if(_expectingContinue){
  528. const char * response = "HTTP/1.1 100 Continue\r\n\r\n";
  529. _client->write(response, os_strlen(response));
  530. }
  531. //check handler for authentication
  532. if(_contentLength){
  533. _parseState = PARSE_REQ_BODY;
  534. } else {
  535. _parseState = PARSE_REQ_END;
  536. if(_handler) _handler->handleRequest(this);
  537. else send(501);
  538. }
  539. } else _parseReqHeader();
  540. }
  541. }
  542. size_t AsyncWebServerRequest::headers() const{
  543. return _headers.length();
  544. }
  545. bool AsyncWebServerRequest::hasHeader(const String& name) const {
  546. for(const auto& h: _headers){
  547. if(h->name().equalsIgnoreCase(name)){
  548. return true;
  549. }
  550. }
  551. return false;
  552. }
  553. bool AsyncWebServerRequest::hasHeader(const __FlashStringHelper * data) const {
  554. PGM_P p = reinterpret_cast<PGM_P>(data);
  555. size_t n = 0;
  556. while (1) {
  557. if (pgm_read_byte(p+n) == 0) break;
  558. n += 1;
  559. }
  560. char * name = (char*) malloc(n+1);
  561. name[n] = 0;
  562. if (name) {
  563. for(size_t b=0; b<n; b++)
  564. name[b] = pgm_read_byte(p++);
  565. bool result = hasHeader( String(name) );
  566. free(name);
  567. return result;
  568. } else {
  569. return false;
  570. }
  571. }
  572. AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) const {
  573. for(const auto& h: _headers){
  574. if(h->name().equalsIgnoreCase(name)){
  575. return h;
  576. }
  577. }
  578. return nullptr;
  579. }
  580. AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) const {
  581. PGM_P p = reinterpret_cast<PGM_P>(data);
  582. size_t n = strlen_P(p);
  583. char * name = (char*) malloc(n+1);
  584. if (name) {
  585. strcpy_P(name, p);
  586. AsyncWebHeader* result = getHeader( String(name));
  587. free(name);
  588. return result;
  589. } else {
  590. return nullptr;
  591. }
  592. }
  593. AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const {
  594. auto header = _headers.nth(num);
  595. return header ? *header : nullptr;
  596. }
  597. size_t AsyncWebServerRequest::params() const {
  598. return _params.length();
  599. }
  600. bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) const {
  601. for(const auto& p: _params){
  602. if(p->name() == name && p->isPost() == post && p->isFile() == file){
  603. return true;
  604. }
  605. }
  606. return false;
  607. }
  608. bool AsyncWebServerRequest::hasParam(const __FlashStringHelper * data, bool post, bool file) const {
  609. PGM_P p = reinterpret_cast<PGM_P>(data);
  610. size_t n = strlen_P(p);
  611. char * name = (char*) malloc(n+1);
  612. name[n] = 0;
  613. if (name) {
  614. strcpy_P(name,p);
  615. bool result = hasParam( name, post, file);
  616. free(name);
  617. return result;
  618. } else {
  619. return false;
  620. }
  621. }
  622. AsyncWebParameter* AsyncWebServerRequest::getParam(const String& name, bool post, bool file) const {
  623. for(const auto& p: _params){
  624. if(p->name() == name && p->isPost() == post && p->isFile() == file){
  625. return p;
  626. }
  627. }
  628. return nullptr;
  629. }
  630. AsyncWebParameter* AsyncWebServerRequest::getParam(const __FlashStringHelper * data, bool post, bool file) const {
  631. PGM_P p = reinterpret_cast<PGM_P>(data);
  632. size_t n = strlen_P(p);
  633. char * name = (char*) malloc(n+1);
  634. if (name) {
  635. strcpy_P(name, p);
  636. AsyncWebParameter* result = getParam(name, post, file);
  637. free(name);
  638. return result;
  639. } else {
  640. return nullptr;
  641. }
  642. }
  643. AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const {
  644. auto param = _params.nth(num);
  645. return param ? *param : nullptr;
  646. }
  647. void AsyncWebServerRequest::addInterestingHeader(const String& name){
  648. if(!_interestingHeaders.containsIgnoreCase(name))
  649. _interestingHeaders.add(name);
  650. }
  651. void AsyncWebServerRequest::send(AsyncWebServerResponse *response){
  652. _response = response;
  653. if(_response == NULL){
  654. _client->close(true);
  655. _onDisconnect();
  656. return;
  657. }
  658. if(!_response->_sourceValid()){
  659. delete response;
  660. _response = NULL;
  661. send(500);
  662. }
  663. else {
  664. _client->setRxTimeout(0);
  665. _response->_respond(this);
  666. }
  667. }
  668. AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, const String& contentType, const String& content){
  669. return new AsyncBasicResponse(code, contentType, content);
  670. }
  671. AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){
  672. if(fs.exists(path) || (!download && fs.exists(path+".gz")))
  673. return new AsyncFileResponse(fs, path, contentType, download, callback);
  674. return NULL;
  675. }
  676. AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){
  677. if(content == true)
  678. return new AsyncFileResponse(content, path, contentType, download, callback);
  679. return NULL;
  680. }
  681. AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback){
  682. return new AsyncStreamResponse(stream, contentType, len, callback);
  683. }
  684. AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){
  685. return new AsyncCallbackResponse(contentType, len, callback, templateCallback);
  686. }
  687. AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){
  688. if(_version)
  689. return new AsyncChunkedResponse(contentType, callback, templateCallback);
  690. return new AsyncCallbackResponse(contentType, 0, callback, templateCallback);
  691. }
  692. AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(const String& contentType, size_t bufferSize){
  693. return new AsyncResponseStream(contentType, bufferSize);
  694. }
  695. AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback){
  696. return new AsyncProgmemResponse(code, contentType, content, len, callback);
  697. }
  698. AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback){
  699. return beginResponse_P(code, contentType, (const uint8_t *)content, strlen_P(content), callback);
  700. }
  701. void AsyncWebServerRequest::send(int code, const String& contentType, const String& content){
  702. send(beginResponse(code, contentType, content));
  703. }
  704. void AsyncWebServerRequest::send(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){
  705. if(fs.exists(path) || (!download && fs.exists(path+".gz"))){
  706. send(beginResponse(fs, path, contentType, download, callback));
  707. } else send(404);
  708. }
  709. void AsyncWebServerRequest::send(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){
  710. if(content == true){
  711. send(beginResponse(content, path, contentType, download, callback));
  712. } else send(404);
  713. }
  714. void AsyncWebServerRequest::send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback){
  715. send(beginResponse(stream, contentType, len, callback));
  716. }
  717. void AsyncWebServerRequest::send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){
  718. send(beginResponse(contentType, len, callback, templateCallback));
  719. }
  720. void AsyncWebServerRequest::sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){
  721. send(beginChunkedResponse(contentType, callback, templateCallback));
  722. }
  723. void AsyncWebServerRequest::send_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback){
  724. send(beginResponse_P(code, contentType, content, len, callback));
  725. }
  726. void AsyncWebServerRequest::send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback){
  727. send(beginResponse_P(code, contentType, content, callback));
  728. }
  729. void AsyncWebServerRequest::redirect(const String& url){
  730. AsyncWebServerResponse * response = beginResponse(302);
  731. response->addHeader("Location",url);
  732. send(response);
  733. }
  734. bool AsyncWebServerRequest::authenticate(const char * username, const char * password, const char * realm, bool passwordIsHash){
  735. if(_authorization.length()){
  736. if(_isDigest)
  737. return checkDigestAuthentication(_authorization.c_str(), methodToString(), username, password, realm, passwordIsHash, NULL, NULL, NULL);
  738. else if(!passwordIsHash)
  739. return checkBasicAuthentication(_authorization.c_str(), username, password);
  740. else
  741. return _authorization.equals(password);
  742. }
  743. return false;
  744. }
  745. bool AsyncWebServerRequest::authenticate(const char * hash){
  746. if(!_authorization.length() || hash == NULL)
  747. return false;
  748. if(_isDigest){
  749. String hStr = String(hash);
  750. int separator = hStr.indexOf(":");
  751. if(separator <= 0)
  752. return false;
  753. String username = hStr.substring(0, separator);
  754. hStr = hStr.substring(separator + 1);
  755. separator = hStr.indexOf(":");
  756. if(separator <= 0)
  757. return false;
  758. String realm = hStr.substring(0, separator);
  759. hStr = hStr.substring(separator + 1);
  760. return checkDigestAuthentication(_authorization.c_str(), methodToString(), username.c_str(), hStr.c_str(), realm.c_str(), true, NULL, NULL, NULL);
  761. }
  762. return (_authorization.equals(hash));
  763. }
  764. void AsyncWebServerRequest::requestAuthentication(const char * realm, bool isDigest){
  765. AsyncWebServerResponse * r = beginResponse(401);
  766. if(!isDigest && realm == NULL){
  767. r->addHeader("WWW-Authenticate", "Basic realm=\"Login Required\"");
  768. } else if(!isDigest){
  769. String header = "Basic realm=\"";
  770. header.concat(realm);
  771. header.concat("\"");
  772. r->addHeader("WWW-Authenticate", header);
  773. } else {
  774. String header = "Digest ";
  775. header.concat(requestDigestAuthentication(realm));
  776. r->addHeader("WWW-Authenticate", header);
  777. }
  778. send(r);
  779. }
  780. bool AsyncWebServerRequest::hasArg(const char* name) const {
  781. for(const auto& arg: _params){
  782. if(arg->name() == name){
  783. return true;
  784. }
  785. }
  786. return false;
  787. }
  788. bool AsyncWebServerRequest::hasArg(const __FlashStringHelper * data) const {
  789. PGM_P p = reinterpret_cast<PGM_P>(data);
  790. size_t n = strlen_P(p);
  791. char * name = (char*) malloc(n+1);
  792. if (name) {
  793. strcpy_P(name, p);
  794. bool result = hasArg( name );
  795. free(name);
  796. return result;
  797. } else {
  798. return false;
  799. }
  800. }
  801. const String& AsyncWebServerRequest::arg(const String& name) const {
  802. for(const auto& arg: _params){
  803. if(arg->name() == name){
  804. return arg->value();
  805. }
  806. }
  807. return SharedEmptyString;
  808. }
  809. const String& AsyncWebServerRequest::arg(const __FlashStringHelper * data) const {
  810. PGM_P p = reinterpret_cast<PGM_P>(data);
  811. size_t n = strlen_P(p);
  812. char * name = (char*) malloc(n+1);
  813. if (name) {
  814. strcpy_P(name, p);
  815. const String & result = arg( String(name) );
  816. free(name);
  817. return result;
  818. } else {
  819. return SharedEmptyString;
  820. }
  821. }
  822. const String& AsyncWebServerRequest::arg(size_t i) const {
  823. return getParam(i)->value();
  824. }
  825. const String& AsyncWebServerRequest::argName(size_t i) const {
  826. return getParam(i)->name();
  827. }
  828. const String& AsyncWebServerRequest::pathArg(size_t i) const {
  829. auto param = _pathParams.nth(i);
  830. return param ? **param : SharedEmptyString;
  831. }
  832. const String& AsyncWebServerRequest::header(const char* name) const {
  833. AsyncWebHeader* h = getHeader(String(name));
  834. return h ? h->value() : SharedEmptyString;
  835. }
  836. const String& AsyncWebServerRequest::header(const __FlashStringHelper * data) const {
  837. PGM_P p = reinterpret_cast<PGM_P>(data);
  838. size_t n = strlen_P(p);
  839. char * name = (char*) malloc(n+1);
  840. if (name) {
  841. strcpy_P(name, p);
  842. const String & result = header( (const char *)name );
  843. free(name);
  844. return result;
  845. } else {
  846. return SharedEmptyString;
  847. }
  848. };
  849. const String& AsyncWebServerRequest::header(size_t i) const {
  850. AsyncWebHeader* h = getHeader(i);
  851. return h ? h->value() : SharedEmptyString;
  852. }
  853. const String& AsyncWebServerRequest::headerName(size_t i) const {
  854. AsyncWebHeader* h = getHeader(i);
  855. return h ? h->name() : SharedEmptyString;
  856. }
  857. String AsyncWebServerRequest::urlDecode(const String& text) const {
  858. char temp[] = "0x00";
  859. unsigned int len = text.length();
  860. unsigned int i = 0;
  861. String decoded = String();
  862. decoded.reserve(len); // Allocate the string internal buffer - never longer from source text
  863. while (i < len){
  864. char decodedChar;
  865. char encodedChar = text.charAt(i++);
  866. if ((encodedChar == '%') && (i + 1 < len)){
  867. temp[2] = text.charAt(i++);
  868. temp[3] = text.charAt(i++);
  869. decodedChar = strtol(temp, NULL, 16);
  870. } else if (encodedChar == '+') {
  871. decodedChar = ' ';
  872. } else {
  873. decodedChar = encodedChar; // normal ascii char
  874. }
  875. decoded.concat(decodedChar);
  876. }
  877. return decoded;
  878. }
  879. const char * AsyncWebServerRequest::methodToString() const {
  880. if(_method == HTTP_ANY) return "ANY";
  881. else if(_method & HTTP_GET) return "GET";
  882. else if(_method & HTTP_POST) return "POST";
  883. else if(_method & HTTP_DELETE) return "DELETE";
  884. else if(_method & HTTP_PUT) return "PUT";
  885. else if(_method & HTTP_PATCH) return "PATCH";
  886. else if(_method & HTTP_HEAD) return "HEAD";
  887. else if(_method & HTTP_OPTIONS) return "OPTIONS";
  888. return "UNKNOWN";
  889. }
  890. const char *AsyncWebServerRequest::requestedConnTypeToString() const {
  891. switch (_reqconntype) {
  892. case RCT_NOT_USED: return "RCT_NOT_USED";
  893. case RCT_DEFAULT: return "RCT_DEFAULT";
  894. case RCT_HTTP: return "RCT_HTTP";
  895. case RCT_WS: return "RCT_WS";
  896. case RCT_EVENT: return "RCT_EVENT";
  897. default: return "ERROR";
  898. }
  899. }
  900. bool AsyncWebServerRequest::isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2, RequestedConnectionType erct3) {
  901. bool res = false;
  902. if ((erct1 != RCT_NOT_USED) && (erct1 == _reqconntype)) res = true;
  903. if ((erct2 != RCT_NOT_USED) && (erct2 == _reqconntype)) res = true;
  904. if ((erct3 != RCT_NOT_USED) && (erct3 == _reqconntype)) res = true;
  905. return res;
  906. }