httpreadrequest.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. Copyright 2017 Herik Lima de Castro and Marcelo Medeiros Eler
  3. Distributed under MIT license, or public domain if desired and
  4. recognized in your jurisdiction.
  5. See file LICENSE for detail.
  6. */
  7. #include "httpreadrequest.h"
  8. #include "configuration.h"
  9. #include "constants.h"
  10. #include "cwf/filter.h"
  11. #include "cwf/filterchain.h"
  12. CWF_BEGIN_NAMESPACE
  13. HttpReadRequest::HttpReadRequest(qintptr socketDescriptor,
  14. QMapThreadSafety<QString, Controller *> &urlController,
  15. QMapThreadSafety<QString, Session *> &sessions,
  16. const Configuration &configuration,
  17. QSslConfiguration *ssl,
  18. Filter *filter)
  19. : socketDescriptor(socketDescriptor)
  20. , urlController(urlController)
  21. , sessions(sessions)
  22. , configuration(configuration)
  23. , ssl(ssl)
  24. , filter(filter)
  25. {}
  26. HttpReadRequest::~HttpReadRequest()
  27. {
  28. delete socket;
  29. }
  30. bool HttpReadRequest::buildSslSocket()
  31. {
  32. #ifndef QT_NO_SSL
  33. if (ssl) {
  34. auto *sslSocket = new QSslSocket;
  35. socket = sslSocket;
  36. sslSocket->setSslConfiguration(*ssl);
  37. sslSocket->setSocketDescriptor(socketDescriptor);
  38. sslSocket->startServerEncryption();
  39. return true;
  40. }
  41. #endif
  42. return false;
  43. }
  44. void HttpReadRequest::buildSocket()
  45. {
  46. if (!buildSslSocket()) {
  47. socket = new QTcpSocket;
  48. socket->setSocketDescriptor(socketDescriptor);
  49. }
  50. }
  51. void HttpReadRequest::run()
  52. {
  53. buildSocket();
  54. maxUploadFile = configuration.getMaxUploadFile();
  55. socket->setReadBufferSize(maxUploadFile);
  56. const QAbstractSocket::SocketState &state = socket->state();
  57. if (state == QAbstractSocket::ConnectedState) {
  58. if (socket->waitForReadyRead()) {
  59. QByteArray req;
  60. try {
  61. req = socket->readAll();
  62. } catch (const std::bad_alloc &e) {
  63. qDebug() << e.what() << "\n";
  64. }
  65. HttpParser parser(req);
  66. if (parser.valid) {
  67. QString url = parser.url;
  68. Request request(*socket, sessions, configuration);
  69. Response response(*socket, configuration);
  70. request.httpParser = &parser;
  71. request.response = &response;
  72. if ((parser.contentLenght > parser.body.size())) {
  73. if (!readBody(parser, request, response)) {
  74. return;
  75. }
  76. }
  77. Controller *controller = urlController.value(url, nullptr);
  78. if (!controller) {
  79. for (QMapThreadSafety<QString, Controller *>::iterator it = urlController.begin();
  80. it != urlController.end();
  81. ++it) {
  82. const QString &key = it.key();
  83. if (key.endsWith('*')) {
  84. QString trueUrl(key.mid(0, key.size() - 1));
  85. if (url.startsWith(trueUrl)) {
  86. url = trueUrl + "*";
  87. controller = it.value();
  88. break;
  89. }
  90. }
  91. }
  92. }
  93. FilterChain chain(controller, configuration);
  94. try {
  95. if (filter) {
  96. filter->doFilter(request, response, chain);
  97. } else {
  98. chain.doFilter(request, response);
  99. }
  100. } catch (std::exception &e) {
  101. qDebug() << e.what();
  102. } catch (...) {
  103. qDebug() << "An unknown exception has occurred\n\n";
  104. }
  105. }
  106. }
  107. }
  108. }
  109. bool HttpReadRequest::readBody(HttpParser &parser, Request &request, Response &response)
  110. {
  111. qint64 contentLength = parser.contentLenght;
  112. QByteArray content(std::move(parser.body));
  113. int maximumTime = configuration.getTimeOut() / 2;
  114. std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
  115. while (true) {
  116. if (socket->waitForReadyRead(10)) {
  117. if (content.size() > maxUploadFile) {
  118. socket->readAll(); // what if the internal buffer throws a
  119. } else {
  120. try {
  121. content += socket->readAll();
  122. } catch (const std::bad_alloc &e) {
  123. qDebug() << e.what() << "\n";
  124. break;
  125. }
  126. }
  127. }
  128. int spendTime = std::chrono::duration_cast<std::chrono::milliseconds>(
  129. std::chrono::high_resolution_clock::now() - start)
  130. .count();
  131. if (content.size() > contentLength) {
  132. content.remove(contentLength, content.size());
  133. break;
  134. }
  135. if (content.size() == contentLength) {
  136. break;
  137. }
  138. if (spendTime >= maximumTime) {
  139. break;
  140. }
  141. }
  142. if (content.size() > maxUploadFile) {
  143. request.getRequestDispatcher(STATUS::STATUS_403).forward(request, response);
  144. return false;
  145. }
  146. parser.body = std::move(content);
  147. if (parser.contentType.contains(HTTP::APPLICATION_WWW_FORM_URLENCODED)) {
  148. parser.doParseBody();
  149. } else if (parser.multiPart) {
  150. parser.doParseFiles();
  151. }
  152. return true;
  153. }
  154. CWF_END_NAMESPACE