RequestHeadersReader.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /***************************************************************************
  2. *
  3. * Project _____ __ ____ _ _
  4. * ( _ ) /__\ (_ _)_| |_ _| |_
  5. * )(_)( /(__)\ )( (_ _)(_ _)
  6. * (_____)(__)(__)(__) |_| |_|
  7. *
  8. *
  9. * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. ***************************************************************************/
  24. #include "RequestHeadersReader.hpp"
  25. namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming {
  26. v_io_size RequestHeadersReader::readHeadersSectionIterative(ReadHeadersIteration& iteration,
  27. data::stream::InputStreamBufferedProxy* stream,
  28. async::Action& action)
  29. {
  30. v_buff_size desiredToRead = m_readChunkSize;
  31. if(m_bufferStream->getCurrentPosition() + desiredToRead > m_maxHeadersSize) {
  32. desiredToRead = m_maxHeadersSize - m_bufferStream->getCurrentPosition();
  33. if(desiredToRead <= 0) {
  34. return -1;
  35. }
  36. }
  37. m_bufferStream->reserveBytesUpfront(desiredToRead);
  38. auto bufferData = m_bufferStream->getData() + m_bufferStream->getCurrentPosition();
  39. auto res = stream->peek(bufferData, desiredToRead, action);
  40. if(res > 0) {
  41. m_bufferStream->setCurrentPosition(m_bufferStream->getCurrentPosition() + res);
  42. for(v_buff_size i = 0; i < res; i ++) {
  43. iteration.accumulator <<= 8;
  44. iteration.accumulator |= bufferData[i];
  45. if(iteration.accumulator == SECTION_END) {
  46. stream->commitReadOffset(i + 1);
  47. iteration.done = true;
  48. return res;
  49. }
  50. }
  51. stream->commitReadOffset(res);
  52. }
  53. return res;
  54. }
  55. RequestHeadersReader::Result RequestHeadersReader::readHeaders(data::stream::InputStreamBufferedProxy* stream,
  56. http::HttpError::Info& error) {
  57. m_bufferStream->setCurrentPosition(0);
  58. RequestHeadersReader::Result result;
  59. ReadHeadersIteration iteration;
  60. async::Action action;
  61. while(!iteration.done) {
  62. error.ioStatus = readHeadersSectionIterative(iteration, stream, action);
  63. if(!action.isNone()) {
  64. OATPP_LOGE("[oatpp::web::protocol::http::incoming::RequestHeadersReader::readHeaders]", "Error. Async action is unexpected.");
  65. throw std::runtime_error("[oatpp::web::protocol::http::incoming::RequestHeadersReader::readHeaders]: Error. Async action is unexpected.");
  66. }
  67. if(error.ioStatus > 0) {
  68. continue;
  69. } else if(error.ioStatus == IOError::RETRY_READ || error.ioStatus == IOError::RETRY_WRITE) {
  70. continue;
  71. } else {
  72. break;
  73. }
  74. }
  75. if(error.ioStatus > 0) {
  76. oatpp::parser::Caret caret ((const char*) m_bufferStream->getData(), m_bufferStream->getCurrentPosition());
  77. http::Status status;
  78. http::Parser::parseRequestStartingLine(result.startingLine, nullptr, caret, status);
  79. if(status.code == 0) {
  80. http::Parser::parseHeaders(result.headers, nullptr, caret, status);
  81. }
  82. }
  83. return result;
  84. }
  85. oatpp::async::CoroutineStarterForResult<const RequestHeadersReader::Result&>
  86. RequestHeadersReader::readHeadersAsync(const std::shared_ptr<data::stream::InputStreamBufferedProxy>& stream)
  87. {
  88. class ReaderCoroutine : public oatpp::async::CoroutineWithResult<ReaderCoroutine, const Result&> {
  89. private:
  90. std::shared_ptr<data::stream::InputStreamBufferedProxy> m_stream;
  91. RequestHeadersReader* m_this;
  92. ReadHeadersIteration m_iteration;
  93. RequestHeadersReader::Result m_result;
  94. public:
  95. ReaderCoroutine(RequestHeadersReader* _this,
  96. const std::shared_ptr<data::stream::InputStreamBufferedProxy>& stream)
  97. : m_stream(stream)
  98. , m_this(_this)
  99. {
  100. m_this->m_bufferStream->setCurrentPosition(0);
  101. }
  102. Action act() override {
  103. async::Action action;
  104. auto res = m_this->readHeadersSectionIterative(m_iteration, m_stream.get(), action);
  105. if(!action.isNone()) {
  106. return action;
  107. }
  108. if(m_iteration.done) {
  109. return yieldTo(&ReaderCoroutine::parseHeaders);
  110. } else {
  111. if (res > 0) {
  112. return repeat();
  113. } else if (res == IOError::RETRY_READ || res == IOError::RETRY_WRITE) {
  114. return repeat();
  115. }
  116. }
  117. return error<Error>("[oatpp::web::protocol::http::incoming::RequestHeadersReader::readHeadersAsync()]: Error. Error reading connection stream.");
  118. }
  119. Action parseHeaders() {
  120. oatpp::parser::Caret caret ((const char*) m_this->m_bufferStream->getData(), m_this->m_bufferStream->getCurrentPosition());
  121. http::Status status;
  122. http::Parser::parseRequestStartingLine(m_result.startingLine, nullptr, caret, status);
  123. if(status.code == 0) {
  124. http::Parser::parseHeaders(m_result.headers, nullptr, caret, status);
  125. if(status.code == 0) {
  126. return _return(m_result);
  127. } else {
  128. return error<Error>("[oatpp::web::protocol::http::incoming::RequestHeadersReader::readHeadersAsync()]: Error. Error occurred while parsing headers.");
  129. }
  130. } else {
  131. return error<Error>("[oatpp::web::protocol::http::incoming::RequestHeadersReader::readHeadersAsync()]: Error. Can't parse starting line.");
  132. }
  133. }
  134. };
  135. return ReaderCoroutine::startForResult(this, stream);
  136. }
  137. }}}}}