diff --git a/src/oatpp/web/client/ApiClient.cpp b/src/oatpp/web/client/ApiClient.cpp index 39e2cdcc..3c2dd769 100644 --- a/src/oatpp/web/client/ApiClient.cpp +++ b/src/oatpp/web/client/ApiClient.cpp @@ -112,8 +112,8 @@ void ApiClient::addPathQueryParams(oatpp::data::stream::OutputStream* stream, } -oatpp::web::protocol::http::Protocol::Headers ApiClient::convertParamsMap(const std::shared_ptr& params) { - oatpp::web::protocol::http::Protocol::Headers result; +oatpp::web::protocol::http::Headers ApiClient::convertParamsMap(const std::shared_ptr& params) { + oatpp::web::protocol::http::Headers result; if(params) { auto curr = params->getFirstEntry(); diff --git a/src/oatpp/web/client/ApiClient.hpp b/src/oatpp/web/client/ApiClient.hpp index 3990d2f6..6f6608c7 100644 --- a/src/oatpp/web/client/ApiClient.hpp +++ b/src/oatpp/web/client/ApiClient.hpp @@ -147,7 +147,7 @@ private: void addPathQueryParams(oatpp::data::stream::OutputStream* stream, const std::shared_ptr& params); - oatpp::web::protocol::http::Protocol::Headers convertParamsMap(const std::shared_ptr& params); + oatpp::web::protocol::http::Headers convertParamsMap(const std::shared_ptr& params); protected: diff --git a/src/oatpp/web/client/RequestExecutor.hpp b/src/oatpp/web/client/RequestExecutor.hpp index 618d8fb4..92665bbe 100644 --- a/src/oatpp/web/client/RequestExecutor.hpp +++ b/src/oatpp/web/client/RequestExecutor.hpp @@ -48,9 +48,9 @@ public: typedef oatpp::async::Action Action; public: /** - * Convenience typedef for &id:oatpp::web::protocol::http::Protocol::Headers;. + * Convenience typedef for &id:oatpp::web::protocol::http::Headers;. */ - typedef oatpp::web::protocol::http::Protocol::Headers Headers; + typedef oatpp::web::protocol::http::Headers Headers; /** * Convenience typedef for &id:oatpp::web::protocol::http::incoming::Response;. diff --git a/src/oatpp/web/protocol/http/Http.cpp b/src/oatpp/web/protocol/http/Http.cpp index 5f982294..caa35217 100644 --- a/src/oatpp/web/protocol/http/Http.cpp +++ b/src/oatpp/web/protocol/http/Http.cpp @@ -236,7 +236,7 @@ ContentRange ContentRange::parse(const oatpp::String& str) { return parse(caret); } -oatpp::data::share::StringKeyLabelCI_FAST Protocol::parseHeaderNameLabel(const std::shared_ptr& headersText, +oatpp::data::share::StringKeyLabelCI_FAST Parser::parseHeaderNameLabel(const std::shared_ptr& headersText, oatpp::parser::Caret& caret) { p_char8 data = caret.getData(); for(v_int32 i = caret.getPosition(); i < caret.getDataSize(); i++) { @@ -251,7 +251,7 @@ oatpp::data::share::StringKeyLabelCI_FAST Protocol::parseHeaderNameLabel(const s return oatpp::data::share::StringKeyLabelCI_FAST(nullptr, nullptr, 0); } -void Protocol::parseRequestStartingLine(RequestStartingLine& line, +void Parser::parseRequestStartingLine(RequestStartingLine& line, const std::shared_ptr& headersText, oatpp::parser::Caret& caret, Status& error) { @@ -285,7 +285,7 @@ void Protocol::parseRequestStartingLine(RequestStartingLine& line, } -void Protocol::parseResponseStartingLine(ResponseStartingLine& line, +void Parser::parseResponseStartingLine(ResponseStartingLine& line, const std::shared_ptr& headersText, oatpp::parser::Caret& caret, Status& error) { @@ -312,7 +312,7 @@ void Protocol::parseResponseStartingLine(ResponseStartingLine& line, } -void Protocol::parseOneHeader(Headers& headers, +void Parser::parseOneHeader(Headers& headers, const std::shared_ptr& headersText, oatpp::parser::Caret& caret, Status& error) { @@ -335,7 +335,7 @@ void Protocol::parseOneHeader(Headers& headers, } } -void Protocol::parseHeaders(Headers& headers, +void Parser::parseHeaders(Headers& headers, const std::shared_ptr& headersText, oatpp::parser::Caret& caret, Status& error) { diff --git a/src/oatpp/web/protocol/http/Http.hpp b/src/oatpp/web/protocol/http/Http.hpp index 4870fe6c..94cddb08 100644 --- a/src/oatpp/web/protocol/http/Http.hpp +++ b/src/oatpp/web/protocol/http/Http.hpp @@ -534,43 +534,118 @@ public: static ContentRange parse(const oatpp::String& str); }; - + +/** + * Struct representing HTTP request starting line. + * Example request starting line: `GET /path/to/resource/ HTTP/1.1`. + */ struct RequestStartingLine { + /** + * Method as &id:oatpp::data::share::StringKeyLabel;. + */ oatpp::data::share::StringKeyLabel method; // GET, POST ... + + /** + * Path as &id:oatpp::data::share::StringKeyLabel;. + */ oatpp::data::share::StringKeyLabel path; + + /** + * Protocol as &id:oatpp::data::share::StringKeyLabel;. + */ oatpp::data::share::StringKeyLabel protocol; }; - + +/** + * Struct representing HTTP response starting line. + * Example response starting line: `HTTP/1.1 200 OK`. + */ struct ResponseStartingLine { + /** + * Protocol as &id:oatpp::data::share::StringKeyLabel;. + */ oatpp::data::share::StringKeyLabel protocol; + + /** + * Status code as v_int32. + */ v_int32 statusCode; + + /** + * Description as &id:oatpp::data::share::StringKeyLabel;. + */ oatpp::data::share::StringKeyLabel description; }; - -class Protocol { -public: - typedef std::unordered_map Headers; - typedef std::unordered_map QueryParams; + +/** + * Typedef for headers map. Headers map key is case-insensitive. + * `std::unordered_map` of &id:oatpp::data::share::StringKeyLabelCI_FAST; and &id:oatpp::data::share::StringKeyLabel;. + */ +typedef std::unordered_map Headers; + +/** + * Typedef for query parameters map. + * `std::unordered_map` of &id:oatpp::data::share::StringKeyLabel; and &id:oatpp::data::share::StringKeyLabel;. + */ +typedef std::unordered_map QueryParams; + +/** + * Oatpp Http parser. + */ +class Parser { private: static oatpp::data::share::StringKeyLabelCI_FAST parseHeaderNameLabel(const std::shared_ptr& headersText, oatpp::parser::Caret& caret); public: - + + /** + * Parse &l:RequestStartingLine;. + * @param line - &l:RequestStartingLine;. Values will be set to line's fields. + * @param headersText - `std::shared_ptr` to &id:oatpp::base::StrBuffer; needed as a "memory handle" for + * &l:RequestStartingLine; fields. See &id:oatpp::data::share::MemoryLabel;. + * @param caret - &id:oatpp::parser::Caret;. + * @param error - out parameter &l:Status;. + */ static void parseRequestStartingLine(RequestStartingLine& line, const std::shared_ptr& headersText, oatpp::parser::Caret& caret, Status& error); - + + /** + * Parse &l:ResponseStartingLine;. + * @param line - &l:ResponseStartingLine;. Values will be set to line's fields. + * @param headersText - `std::shared_ptr` to &id:oatpp::base::StrBuffer; needed as a "memory handle" for + * &l:ResponseStartingLine; fields. See &id:oatpp::data::share::MemoryLabel;. + * @param caret - &id:oatpp::parser::Caret;. + * @param error - out parameter &l:Status;. + */ static void parseResponseStartingLine(ResponseStartingLine& line, const std::shared_ptr& headersText, oatpp::parser::Caret& caret, Status& error); - + + /** + * Parse one header line. Example of the header line: + * `"Content-Type: application/json\r\n"`. + * @param headers - &l:Headers; map to put parsed header to. + * @param headersText - `std::shared_ptr` to &id:oatpp::base::StrBuffer; needed as a "memory handle" for + * &l:Headers; values. See &id:oatpp::data::share::MemoryLabel;. + * @param caret - &id:oatpp::parser::Caret;. + * @param error - out parameter &l:Status;. + */ static void parseOneHeader(Headers& headers, const std::shared_ptr& headersText, oatpp::parser::Caret& caret, Status& error); - + + /** + * Parse HTTP headers to &l:Headers; map. + * @param headers - &l:Headers; map to put parsed headers to. + * @param headersText - `std::shared_ptr` to &id:oatpp::base::StrBuffer; needed as a "memory handle" for + * &l:Headers; values. See &id:oatpp::data::share::MemoryLabel;. + * @param caret - &id:oatpp::parser::Caret;. + * @param error - out parameter &l:Status;. + */ static void parseHeaders(Headers& headers, const std::shared_ptr& headersText, oatpp::parser::Caret& caret, diff --git a/src/oatpp/web/protocol/http/incoming/BodyDecoder.cpp b/src/oatpp/web/protocol/http/incoming/BodyDecoder.cpp index e5ca3d23..b8329489 100644 --- a/src/oatpp/web/protocol/http/incoming/BodyDecoder.cpp +++ b/src/oatpp/web/protocol/http/incoming/BodyDecoder.cpp @@ -29,7 +29,7 @@ namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming { BodyDecoder::ToStringDecoder::ToStringDecoder(const BodyDecoder* decoder, - const Protocol::Headers& headers, + const Headers& headers, const std::shared_ptr& bodyStream) : m_decoder(decoder) , m_headers(headers) diff --git a/src/oatpp/web/protocol/http/incoming/BodyDecoder.hpp b/src/oatpp/web/protocol/http/incoming/BodyDecoder.hpp index 6066eced..2136ae22 100644 --- a/src/oatpp/web/protocol/http/incoming/BodyDecoder.hpp +++ b/src/oatpp/web/protocol/http/incoming/BodyDecoder.hpp @@ -30,20 +30,26 @@ #include "oatpp/core/async/Coroutine.hpp" namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming { - + +/** + * Abstract BodyDecoder. + * Body Decoder is responsible to decode body of incoming request. + * For example if you receive chunked-encoded body, you have to decode it in order to get "plain" body. + * You may extend this class in order to customize body-decoding process. + */ class BodyDecoder { private: - + class ToStringDecoder : public oatpp::async::CoroutineWithResult { private: const BodyDecoder* m_decoder; - Protocol::Headers m_headers; + Headers m_headers; std::shared_ptr m_bodyStream; std::shared_ptr m_chunkedBuffer; public: ToStringDecoder(const BodyDecoder* decoder, - const Protocol::Headers& headers, + const Headers& headers, const std::shared_ptr& bodyStream); Action act() override; @@ -55,14 +61,14 @@ private: class ToDtoDecoder : public oatpp::async::CoroutineWithResult, typename Type::ObjectWrapper> { private: const BodyDecoder* m_decoder; - Protocol::Headers m_headers; + Headers m_headers; std::shared_ptr m_bodyStream; std::shared_ptr m_objectMapper; std::shared_ptr m_chunkedBuffer = oatpp::data::stream::ChunkedBuffer::createShared(); public: ToDtoDecoder(const BodyDecoder* decoder, - Protocol::Headers& headers, + Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& objectMapper) : m_decoder(decoder) @@ -88,43 +94,92 @@ private: }; public: - - virtual void decode(const Protocol::Headers& headers, + + /** + * Implement this method! Decode bodyStream and write decoded data to toStream. + * @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;. + * @param toStream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + */ + virtual void decode(const Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& toStream) const = 0; - + + /** + * Implement this method! Same as &l:BodyDecoder::decode (); but Async. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param actionOnReturn - &id:oatpp::async::Action; to do when decoding finished. + * @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;. + * @param toStream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + * @return - &id:oatpp::async::Action;. + */ virtual oatpp::async::Action decodeAsync(oatpp::async::AbstractCoroutine* parentCoroutine, const oatpp::async::Action& actionOnReturn, - const Protocol::Headers& headers, + const Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& toStream) const = 0; - - oatpp::String decodeToString(const Protocol::Headers& headers, + + /** + * Read body stream and decode it to string. + * @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;. + * @return - &oatpp::String;. + */ + oatpp::String decodeToString(const Headers& headers, const std::shared_ptr& bodyStream) const { auto chunkedBuffer = oatpp::data::stream::ChunkedBuffer::createShared(); decode(headers, bodyStream, chunkedBuffer); return chunkedBuffer->toString(); } - + + /** + * Read body stream, decode, and deserialize it as DTO Object (see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/)). + * @tparam Type - DTO object type. + * @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;. + * @param objectMapper - `std::shared_ptr` to &id:oatpp::data::mapping::ObjectMapper;. + * @return - deserialized DTO object. + */ template - typename Type::ObjectWrapper decodeToDto(const Protocol::Headers& headers, + typename Type::ObjectWrapper decodeToDto(const Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& objectMapper) const { return objectMapper->readFromString(decodeToString(headers, bodyStream)); } - + + /** + * Same as &l:BodyDecoder::decodeToString (); but Async. + * @tparam ParentCoroutineType - caller coroutine type. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param callback - pointer to callback function. + * @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;. + * @return - &id:oatpp::async::Action;. + */ template oatpp::async::Action decodeToStringAsync(oatpp::async::AbstractCoroutine* parentCoroutine, oatpp::async::Action (ParentCoroutineType::*callback)(const oatpp::String&), - const Protocol::Headers& headers, + const Headers& headers, const std::shared_ptr& bodyStream) const { return parentCoroutine->startCoroutineForResult(callback, this, headers, bodyStream); } - + + /** + * Same as &l:BodyDecoder::decodeToDto (); but Async. + * @tparam DtoType - DTO object type. + * @tparam ParentCoroutineType - caller coroutine type. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param callback - pointer to callback function. + * @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;. + * @param objectMapper - `std::shared_ptr` to &id:oatpp::data::mapping::ObjectMapper;. + * @return - &id:oatpp::async::Action;. + */ template oatpp::async::Action decodeToDtoAsync(oatpp::async::AbstractCoroutine* parentCoroutine, oatpp::async::Action (ParentCoroutineType::*callback)(const typename DtoType::ObjectWrapper&), - const Protocol::Headers& headers, + const Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& objectMapper) const { return parentCoroutine->startCoroutineForResult>(callback, this, headers, bodyStream, objectMapper); diff --git a/src/oatpp/web/protocol/http/incoming/Request.cpp b/src/oatpp/web/protocol/http/incoming/Request.cpp index fa0ab7dd..31ba6110 100644 --- a/src/oatpp/web/protocol/http/incoming/Request.cpp +++ b/src/oatpp/web/protocol/http/incoming/Request.cpp @@ -28,7 +28,7 @@ namespace oatpp { namespace web { namespace protocol { namespace http { namespac Request::Request(const http::RequestStartingLine& startingLine, const url::mapping::Pattern::MatchMap& pathVariables, - const http::Protocol::Headers& headers, + const http::Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& bodyDecoder) : m_startingLine(startingLine) @@ -41,7 +41,7 @@ Request::Request(const http::RequestStartingLine& startingLine, std::shared_ptr Request::createShared(const http::RequestStartingLine& startingLine, const url::mapping::Pattern::MatchMap& pathVariables, - const http::Protocol::Headers& headers, + const http::Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& bodyDecoder) { return Shared_Incoming_Request_Pool::allocateShared(startingLine, pathVariables, headers, bodyStream, bodyDecoder); @@ -55,11 +55,11 @@ const url::mapping::Pattern::MatchMap& Request::getPathVariables() const { return m_pathVariables; } -const http::Protocol::Headers& Request::getHeaders() const { +const http::Headers& Request::getHeaders() const { return m_headers; } -const http::Protocol::QueryParams& Request::getQueryParameters() const { +const http::QueryParams& Request::getQueryParameters() const { if(!m_queryParamsParsed) { m_queryParams = oatpp::network::Url::Parser::labelQueryParams(m_pathVariables.getTail()); m_queryParamsParsed = true; diff --git a/src/oatpp/web/protocol/http/incoming/Request.hpp b/src/oatpp/web/protocol/http/incoming/Request.hpp index b7894deb..44637927 100644 --- a/src/oatpp/web/protocol/http/incoming/Request.hpp +++ b/src/oatpp/web/protocol/http/incoming/Request.hpp @@ -43,7 +43,7 @@ private: http::RequestStartingLine m_startingLine; url::mapping::Pattern::MatchMap m_pathVariables; - http::Protocol::Headers m_headers; + http::Headers m_headers; std::shared_ptr m_bodyStream; /* @@ -53,20 +53,20 @@ private: std::shared_ptr m_bodyDecoder; mutable bool m_queryParamsParsed; // used for lazy parsing of QueryParams - mutable http::Protocol::QueryParams m_queryParams; + mutable http::QueryParams m_queryParams; public: Request(const http::RequestStartingLine& startingLine, const url::mapping::Pattern::MatchMap& pathVariables, - const http::Protocol::Headers& headers, + const http::Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& bodyDecoder); public: static std::shared_ptr createShared(const http::RequestStartingLine& startingLine, const url::mapping::Pattern::MatchMap& pathVariables, - const http::Protocol::Headers& headers, + const http::Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& bodyDecoder); @@ -76,7 +76,7 @@ public: * Please note: lazy parsing of query parameters is not thread-safe! * @return map for "&key=value" */ - const http::Protocol::QueryParams& getQueryParameters() const; + const http::QueryParams& getQueryParameters() const; /** * Get query parameter value by name @@ -112,7 +112,7 @@ public: * Get request's headers map * @return Headers map */ - const http::Protocol::Headers& getHeaders() const; + const http::Headers& getHeaders() const; /** * Get request's body stream diff --git a/src/oatpp/web/protocol/http/incoming/RequestHeadersReader.cpp b/src/oatpp/web/protocol/http/incoming/RequestHeadersReader.cpp index 4989b331..8b2e0cd7 100644 --- a/src/oatpp/web/protocol/http/incoming/RequestHeadersReader.cpp +++ b/src/oatpp/web/protocol/http/incoming/RequestHeadersReader.cpp @@ -84,9 +84,9 @@ RequestHeadersReader::Result RequestHeadersReader::readHeaders(const std::shared auto headersText = buffer.toString(); oatpp::parser::Caret caret (headersText); http::Status status; - http::Protocol::parseRequestStartingLine(result.startingLine, headersText.getPtr(), caret, status); + http::Parser::parseRequestStartingLine(result.startingLine, headersText.getPtr(), caret, status); if(status.code == 0) { - http::Protocol::parseHeaders(result.headers, headersText.getPtr(), caret, status); + http::Parser::parseHeaders(result.headers, headersText.getPtr(), caret, status); } } @@ -161,9 +161,9 @@ RequestHeadersReader::Action RequestHeadersReader::readHeadersAsync(oatpp::async auto headersText = m_bufferStream.toString(); oatpp::parser::Caret caret (headersText); http::Status status; - http::Protocol::parseRequestStartingLine(m_result.startingLine, headersText.getPtr(), caret, status); + http::Parser::parseRequestStartingLine(m_result.startingLine, headersText.getPtr(), caret, status); if(status.code == 0) { - http::Protocol::parseHeaders(m_result.headers, headersText.getPtr(), caret, status); + http::Parser::parseHeaders(m_result.headers, headersText.getPtr(), caret, status); if(status.code == 0) { return _return(m_result); } else { diff --git a/src/oatpp/web/protocol/http/incoming/RequestHeadersReader.hpp b/src/oatpp/web/protocol/http/incoming/RequestHeadersReader.hpp index a8ece554..8094b43c 100644 --- a/src/oatpp/web/protocol/http/incoming/RequestHeadersReader.hpp +++ b/src/oatpp/web/protocol/http/incoming/RequestHeadersReader.hpp @@ -29,18 +29,42 @@ #include "oatpp/core/async/Coroutine.hpp" namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming { - + +/** + * Helper class to read http headers of incoming request from stream. + */ class RequestHeadersReader { public: + /** + * Convenience typedef for &id:oatpp::async::Action;. + */ typedef oatpp::async::Action Action; private: static constexpr v_int32 SECTION_END = ('\r' << 24) | ('\n' << 16) | ('\r' << 8) | ('\n'); public: - + + /** + * Result of headers reading and parsing. + */ struct Result { + /** + * &id:oatpp::web::protocol::http::RequestStartingLine;. + */ http::RequestStartingLine startingLine; - http::Protocol::Headers headers; + + /** + * &id:oatpp::web::protocol::http::Headers;. + */ + http::Headers headers; + + /** + * This value represents starting position in buffer used to read data from stream for the last read operation. + */ v_int32 bufferPosStart; + + /** + * This value represents end position in buffer used to read data from stream for the last read operation. + */ v_int32 bufferPosEnd; }; @@ -55,14 +79,34 @@ private: v_int32 m_bufferSize; v_int32 m_maxHeadersSize; public: - + + /** + * Constructor. + * @param buffer - buffer to use to read data from stream. + * @param bufferSize - buffer size. + * @param maxHeadersSize - maximum allowed size in bytes of http headers section. + */ RequestHeadersReader(void* buffer, v_int32 bufferSize, v_int32 maxHeadersSize) : m_buffer((p_char8) buffer) , m_bufferSize(bufferSize) , m_maxHeadersSize(maxHeadersSize) {} - + + /** + * Read and parse http headers from stream. + * @param connection - `std::shared_ptr` to &id:oatpp::data::stream::IOStream;. + * @param error - out parameter &id:oatpp::web::protocol::ProtocolError::Info;. + * @return - &l:RequestHeadersReader::Result;. + */ Result readHeaders(const std::shared_ptr& connection, http::HttpError::Info& error); + + /** + * Read and parse http headers from stream in asynchronous manner. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param callback - pointer to callback function. + * @param connection - `std::shared_ptr` to &id:oatpp::data::stream::IOStream;. + * @return - &id:oatpp::async::Action;. + */ Action readHeadersAsync(oatpp::async::AbstractCoroutine* parentCoroutine, AsyncCallback callback, const std::shared_ptr& connection); diff --git a/src/oatpp/web/protocol/http/incoming/Response.cpp b/src/oatpp/web/protocol/http/incoming/Response.cpp index 18094c7d..189ead7e 100644 --- a/src/oatpp/web/protocol/http/incoming/Response.cpp +++ b/src/oatpp/web/protocol/http/incoming/Response.cpp @@ -28,7 +28,7 @@ namespace oatpp { namespace web { namespace protocol { namespace http { namespac Response::Response(v_int32 statusCode, const oatpp::String& statusDescription, - const http::Protocol::Headers& headers, + const http::Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& bodyDecoder) : m_statusCode(statusCode) @@ -40,7 +40,7 @@ Response::Response(v_int32 statusCode, std::shared_ptr Response::createShared(v_int32 statusCode, const oatpp::String& statusDescription, - const http::Protocol::Headers& headers, + const http::Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& bodyDecoder) { return Shared_Incoming_Response_Pool::allocateShared(statusCode, statusDescription, headers, bodyStream, bodyDecoder); @@ -54,7 +54,7 @@ oatpp::String Response::getStatusDescription() const { return m_statusDescription; } -const http::Protocol::Headers& Response::getHeaders() const { +const http::Headers& Response::getHeaders() const { return m_headers; } diff --git a/src/oatpp/web/protocol/http/incoming/Response.hpp b/src/oatpp/web/protocol/http/incoming/Response.hpp index 55b0ea62..82cf9b84 100644 --- a/src/oatpp/web/protocol/http/incoming/Response.hpp +++ b/src/oatpp/web/protocol/http/incoming/Response.hpp @@ -40,10 +40,10 @@ public: private: v_int32 m_statusCode; oatpp::String m_statusDescription; - http::Protocol::Headers m_headers; + http::Headers m_headers; std::shared_ptr m_bodyStream; - /** + /* * Response should be preconfigured with default BodyDecoder. * Entity that created response object is responsible for providing correct BodyDecoder. * Custom BodyDecoder can be set on demand @@ -53,50 +53,125 @@ private: std::shared_ptr m_connection; public: + /** + * Constructor. + * @param statusCode - http status code. + * @param statusDescription - http status description. + * @param headers - &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - &id:oatpp::data::stream::InputStream;. + * @param bodyDecoder - &id:oatpp::web::protocol::http::incoming::BodyDecoder;. + */ Response(v_int32 statusCode, const oatpp::String& statusDescription, - const http::Protocol::Headers& headers, + const http::Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& bodyDecoder); public: - + + /** + * Create shared Response. + * @param statusCode - http status code. + * @param statusDescription - http status description. + * @param headers - &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - &id:oatpp::data::stream::InputStream;. + * @param bodyDecoder - &id:oatpp::web::protocol::http::incoming::BodyDecoder;. + * @return - `std::shared_ptr` to Response. + */ static std::shared_ptr createShared(v_int32 statusCode, const oatpp::String& statusDescription, - const http::Protocol::Headers& headers, + const http::Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& bodyDecoder); - + + /** + * Get http status code. + * @return - http status code. + */ v_int32 getStatusCode() const; - + + /** + * Get http status description. + * @return - http status description. + */ oatpp::String getStatusDescription() const; - - const http::Protocol::Headers& getHeaders() const; - + + /** + * Get response http headers as &id:oatpp::web::protocol::http::Headers;. + * @return - response http headers as &id:oatpp::web::protocol::http::Headers;. + */ + const http::Headers& getHeaders() const; + + /** + * Get raw body stream. + * @return - raw body stream as &id:oatpp::data::stream::InputStream;. + */ std::shared_ptr getBodyStream() const; - + + /** + * Get body decoder configured for this response. + * @return - &id:oatpp::web::protocol::http::incoming::BodyDecoder;. + */ std::shared_ptr getBodyDecoder() const; + /** + * Decode and transfer body to toStream. + * Use case example - stream huge body directly to file using relatively small buffer. + * @param toStream - &id:oatpp::data::stream::OutputStream;. + */ void streamBody(const std::shared_ptr& toStream) const; - + + /** + * Decode and read body to &id:oatpp::String;. + * @return - &id:oatpp::String;. + */ oatpp::String readBodyToString() const; - + + /** + * Read body stream, decode, and deserialize it as DTO Object (see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/)). + * @tparam Type - DTO object type. + * @param objectMapper - `std::shared_ptr` to &id:oatpp::data::mapping::ObjectMapper;. + * @return - deserialized DTO object. + */ template typename Type::ObjectWrapper readBodyToDto(const std::shared_ptr& objectMapper) const { return m_bodyDecoder->decodeToDto(m_headers, m_bodyStream, objectMapper); } // Async - + + /** + * Same as &l:Response::readBodyToDto (); but Async. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param actionOnReturn - &id:oatpp::async::Action; to do when decoding finished. + * @param toStream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + * @return - &id:oatpp::async::Action;. + */ oatpp::async::Action streamBodyAsync(oatpp::async::AbstractCoroutine* parentCoroutine, const oatpp::async::Action& actionOnReturn, const std::shared_ptr& toStream) const; - + + /** + * Same as &l:Response::readBodyToString (); but Async. + * @tparam ParentCoroutineType - caller coroutine type. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param callback - pointer to callback function. + * @return - &id:oatpp::async::Action;. + */ template oatpp::async::Action readBodyToStringAsync(oatpp::async::AbstractCoroutine* parentCoroutine, oatpp::async::Action (ParentCoroutineType::*callback)(const oatpp::String&)) const { return m_bodyDecoder->decodeToStringAsync(parentCoroutine, callback, m_headers, m_bodyStream); } - + + /** + * Same as &l:Response::readBodyToDto (); but Async. + * @tparam DtoType - DTO object type. + * @tparam ParentCoroutineType - caller coroutine type. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param callback - pointer to callback function. + * @param objectMapper - `std::shared_ptr` to &id:oatpp::data::mapping::ObjectMapper;. + * @return - &id:oatpp::async::Action;. + */ template oatpp::async::Action readBodyToDtoAsync(oatpp::async::AbstractCoroutine* parentCoroutine, oatpp::async::Action (ParentCoroutineType::*callback)(const typename DtoType::ObjectWrapper&), diff --git a/src/oatpp/web/protocol/http/incoming/ResponseHeadersReader.cpp b/src/oatpp/web/protocol/http/incoming/ResponseHeadersReader.cpp index a322a01a..9577af41 100644 --- a/src/oatpp/web/protocol/http/incoming/ResponseHeadersReader.cpp +++ b/src/oatpp/web/protocol/http/incoming/ResponseHeadersReader.cpp @@ -84,9 +84,9 @@ ResponseHeadersReader::Result ResponseHeadersReader::readHeaders(const std::shar auto headersText = buffer.toString(); oatpp::parser::Caret caret (headersText); http::Status status; - http::Protocol::parseResponseStartingLine(result.startingLine, headersText.getPtr(), caret, status); + http::Parser::parseResponseStartingLine(result.startingLine, headersText.getPtr(), caret, status); if(status.code == 0) { - http::Protocol::parseHeaders(result.headers, headersText.getPtr(), caret, status); + http::Parser::parseHeaders(result.headers, headersText.getPtr(), caret, status); } } @@ -161,9 +161,9 @@ ResponseHeadersReader::Action ResponseHeadersReader::readHeadersAsync(oatpp::asy auto headersText = m_bufferStream.toString(); oatpp::parser::Caret caret (headersText); http::Status status; - http::Protocol::parseResponseStartingLine(m_result.startingLine, headersText.getPtr(), caret, status); + http::Parser::parseResponseStartingLine(m_result.startingLine, headersText.getPtr(), caret, status); if(status.code == 0) { - http::Protocol::parseHeaders(m_result.headers, headersText.getPtr(), caret, status); + http::Parser::parseHeaders(m_result.headers, headersText.getPtr(), caret, status); if(status.code == 0) { return _return(m_result); } else { diff --git a/src/oatpp/web/protocol/http/incoming/ResponseHeadersReader.hpp b/src/oatpp/web/protocol/http/incoming/ResponseHeadersReader.hpp index daec4797..897445d1 100644 --- a/src/oatpp/web/protocol/http/incoming/ResponseHeadersReader.hpp +++ b/src/oatpp/web/protocol/http/incoming/ResponseHeadersReader.hpp @@ -29,18 +29,42 @@ #include "oatpp/core/async/Coroutine.hpp" namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming { - + +/** + * Helper class to read http headers of incoming response from stream. + */ class ResponseHeadersReader { public: + /** + * Convenience typedef for &id:oatpp::async::Action;. + */ typedef oatpp::async::Action Action; private: static constexpr v_int32 SECTION_END = ('\r' << 24) | ('\n' << 16) | ('\r' << 8) | ('\n'); public: - + + /** + * Result of headers reading and parsing. + */ struct Result { + /** + * &id:oatpp::web::protocol::http::ResponseStartingLine;. + */ http::ResponseStartingLine startingLine; - http::Protocol::Headers headers; + + /** + * &id:oatpp::web::protocol::http::Headers;. + */ + http::Headers headers; + + /** + * This value represents starting position in buffer used to read data from stream for the last read operation. + */ v_int32 bufferPosStart; + + /** + * This value represents end position in buffer used to read data from stream for the last read operation. + */ v_int32 bufferPosEnd; }; @@ -55,14 +79,34 @@ private: v_int32 m_bufferSize; v_int32 m_maxHeadersSize; public: - + + /** + * Constructor. + * @param buffer - buffer to use to read data from stream. + * @param bufferSize - buffer size. + * @param maxHeadersSize - maximum allowed size in bytes of http headers section. + */ ResponseHeadersReader(void* buffer, v_int32 bufferSize, v_int32 maxHeadersSize) : m_buffer((p_char8) buffer) , m_bufferSize(bufferSize) , m_maxHeadersSize(maxHeadersSize) {} - + + /** + * Read and parse http headers from stream. + * @param connection - `std::shared_ptr` to &id:oatpp::data::stream::IOStream;. + * @param error - out parameter &id:oatpp::web::protocol::ProtocolError::Info;. + * @return - &l:ResponseHeadersReader::Result;. + */ Result readHeaders(const std::shared_ptr& connection, http::HttpError::Info& error); + + /** + * Read and parse http headers from stream in asynchronous manner. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param callback - pointer to callback function. + * @param connection - `std::shared_ptr` to &id:oatpp::data::stream::IOStream;. + * @return - &id:oatpp::async::Action;. + */ Action readHeadersAsync(oatpp::async::AbstractCoroutine* parentCoroutine, AsyncCallback callback, const std::shared_ptr& connection); diff --git a/src/oatpp/web/protocol/http/incoming/SimpleBodyDecoder.cpp b/src/oatpp/web/protocol/http/incoming/SimpleBodyDecoder.cpp index ece43326..5bb81254 100644 --- a/src/oatpp/web/protocol/http/incoming/SimpleBodyDecoder.cpp +++ b/src/oatpp/web/protocol/http/incoming/SimpleBodyDecoder.cpp @@ -83,7 +83,7 @@ void SimpleBodyDecoder::doChunkedDecoding(const std::shared_ptr& bodyStream, const std::shared_ptr& toStream) const { @@ -219,7 +219,7 @@ oatpp::async::Action SimpleBodyDecoder::doChunkedDecodingAsync(oatpp::async::Abs oatpp::async::Action SimpleBodyDecoder::decodeAsync(oatpp::async::AbstractCoroutine* parentCoroutine, const oatpp::async::Action& actionOnReturn, - const Protocol::Headers& headers, + const Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& toStream) const { auto transferEncodingIt = headers.find(Header::TRANSFER_ENCODING); diff --git a/src/oatpp/web/protocol/http/incoming/SimpleBodyDecoder.hpp b/src/oatpp/web/protocol/http/incoming/SimpleBodyDecoder.hpp index 9a297651..3959204c 100644 --- a/src/oatpp/web/protocol/http/incoming/SimpleBodyDecoder.hpp +++ b/src/oatpp/web/protocol/http/incoming/SimpleBodyDecoder.hpp @@ -29,6 +29,9 @@ namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming { +/** + * Default implementation of &id:oatpp::web::protocol::http::incoming::BodyDecoder;. + */ class SimpleBodyDecoder : public BodyDecoder { private: static data::v_io_size readLine(const std::shared_ptr& fromStream, @@ -42,14 +45,29 @@ private: const std::shared_ptr& fromStream, const std::shared_ptr& toStream); public: - - void decode(const Protocol::Headers& headers, + + /** + * Decode bodyStream and write decoded data to toStream. + * @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;. + * @param toStream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + */ + void decode(const Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& toStream) const override; - + + /** + * Same as &l:SimpleBodyDecoder::decode (); but Async. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param actionOnReturn - &id:oatpp::async::Action; to do when decoding finished. + * @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;. + * @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;. + * @param toStream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + * @return - &id:oatpp::async::Action;. + */ oatpp::async::Action decodeAsync(oatpp::async::AbstractCoroutine* parentCoroutine, const oatpp::async::Action& actionOnReturn, - const Protocol::Headers& headers, + const Headers& headers, const std::shared_ptr& bodyStream, const std::shared_ptr& toStream) const override; diff --git a/src/oatpp/web/protocol/http/outgoing/Body.hpp b/src/oatpp/web/protocol/http/outgoing/Body.hpp index 1e85e351..29f9c244 100644 --- a/src/oatpp/web/protocol/http/outgoing/Body.hpp +++ b/src/oatpp/web/protocol/http/outgoing/Body.hpp @@ -32,25 +32,42 @@ #include "oatpp/core/async/Coroutine.hpp" namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing { - + +/** + * Abstract http outgoing body. + * You may extend this class in order to implement custom body transferring functionality. + */ class Body { protected: typedef oatpp::async::Action Action; protected: - typedef http::Protocol::Headers Headers; + typedef http::Headers Headers; typedef oatpp::data::stream::OutputStream OutputStream; public: - + /** - * declare headers describing body + * Declare headers describing body. + * @param headers - &id:oatpp::web::protocol::http::Headers;. */ virtual void declareHeaders(Headers& headers) noexcept = 0; /** * write content to stream */ + + /** + * Write body content to stream. + * @param stream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + */ virtual void writeToStream(const std::shared_ptr& stream) noexcept = 0; - + + /** + * Same as &l:Body::writeToStream (); but async. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param actionOnReturn - action to perform once transfer is finished. + * @param stream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + * @return - &id:oatpp::async::Action;. + */ virtual Action writeToStreamAsync(oatpp::async::AbstractCoroutine* parentCoroutine, const Action& actionOnReturn, const std::shared_ptr& stream) = 0; diff --git a/src/oatpp/web/protocol/http/outgoing/BufferBody.hpp b/src/oatpp/web/protocol/http/outgoing/BufferBody.hpp index 08809b83..b7dff7ba 100644 --- a/src/oatpp/web/protocol/http/outgoing/BufferBody.hpp +++ b/src/oatpp/web/protocol/http/outgoing/BufferBody.hpp @@ -30,7 +30,11 @@ #include "oatpp/core/utils/ConversionUtils.hpp" namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing { - + +/** + * Implementation of &id:oatpp::web::protocol::http::outgoing::Body; class. + * Implements functionality to use &id::oatpp::String; as data source for http body. + */ class BufferBody : public oatpp::base::Countable, public Body, public std::enable_shared_from_this { public: OBJECT_POOL(Http_Outgoing_BufferBody_Pool, BufferBody, 32) @@ -40,13 +44,31 @@ private: public: BufferBody(const oatpp::String& buffer); public: - + + /** + * Create shared BufferBody. + * @param buffer - &id:oatpp::String;. + * @return - `std::shared_ptr` to BufferBody. + */ static std::shared_ptr createShared(const oatpp::String& buffer); + + /** + * Declare `Content-Length` header. + * @param headers - &id:oatpp::web::protocol::http::Headers;. + */ void declareHeaders(Headers& headers) noexcept override; + + /** + * Write body data to stream. + * @param stream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + */ void writeToStream(const std::shared_ptr& stream) noexcept override; public: - + + /** + * Coroutine used to write &l:BufferBody; to &id:oatpp::data::stream::OutputStream;. + */ class WriteToStreamCoroutine : public oatpp::async::Coroutine { private: std::shared_ptr m_body; @@ -54,7 +76,12 @@ public: const void* m_currData; oatpp::data::v_io_size m_currDataSize; public: - + + /** + * Constructor. + * @param body - &l:BufferBody;. + * @param stream - &id:oatpp::data::stream::OutputStream;. + */ WriteToStreamCoroutine(const std::shared_ptr& body, const std::shared_ptr& stream); @@ -63,10 +90,17 @@ public: }; public: - + + /** + * Start &l:BufferBody::WriteToStreamCoroutine; to write buffer data to stream. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;. + * @param actionOnReturn - action to do once &l:BufferBody::WriteToStreamCoroutine; is finished. + * @param stream - &id:oatpp::data::stream::OutputStream;. + * @return - &id:oatpp::async::Action; + */ Action writeToStreamAsync(oatpp::async::AbstractCoroutine* parentCoroutine, - const Action& actionOnReturn, - const std::shared_ptr& stream) override; + const Action& actionOnReturn, + const std::shared_ptr& stream) override; }; diff --git a/src/oatpp/web/protocol/http/outgoing/ChunkedBufferBody.cpp b/src/oatpp/web/protocol/http/outgoing/ChunkedBufferBody.cpp index 4f0dbc9d..e5f4530c 100644 --- a/src/oatpp/web/protocol/http/outgoing/ChunkedBufferBody.cpp +++ b/src/oatpp/web/protocol/http/outgoing/ChunkedBufferBody.cpp @@ -33,11 +33,6 @@ ChunkedBufferBody::ChunkedBufferBody(const std::shared_ptr ChunkedBufferBody::createShared(const std::shared_ptr& buffer) { - return Shared_Http_Outgoing_ChunkedBufferBody_Pool::allocateShared(buffer, false); -} - std::shared_ptr ChunkedBufferBody::createShared(const std::shared_ptr& buffer, bool chunked) { return Shared_Http_Outgoing_ChunkedBufferBody_Pool::allocateShared(buffer, chunked); } diff --git a/src/oatpp/web/protocol/http/outgoing/ChunkedBufferBody.hpp b/src/oatpp/web/protocol/http/outgoing/ChunkedBufferBody.hpp index 5048f5c9..1eaef7a8 100644 --- a/src/oatpp/web/protocol/http/outgoing/ChunkedBufferBody.hpp +++ b/src/oatpp/web/protocol/http/outgoing/ChunkedBufferBody.hpp @@ -31,7 +31,11 @@ #include "oatpp/core/utils/ConversionUtils.hpp" namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing { - + +/** + * Implementation of &id:oatpp::web::protocol::http::outgoing::Body; class. + * Implements functionality to use &id::oatpp::data::stream::ChunkedBuffer; as data source for http body. + */ class ChunkedBufferBody : public oatpp::base::Countable, public Body, public std::enable_shared_from_this { public: static const char* ERROR_FAILED_TO_WRITE_DATA; @@ -42,19 +46,40 @@ protected: std::shared_ptr m_buffer; bool m_chunked; public: - ChunkedBufferBody(const std::shared_ptr& buffer, bool chunked); + /** + * Constructor. + * @param buffer - &id::oatpp::data::stream::ChunkedBuffer;. + * @param chunked - set `true` to send using HTTP chunked transfer encoding. Set `false` to send as body with specified `Content-Length` header. + */ + ChunkedBufferBody(const std::shared_ptr& buffer, bool chunked = false); public: - - static std::shared_ptr createShared(const std::shared_ptr& buffer); - - static std::shared_ptr createShared(const std::shared_ptr& buffer, bool chunked); - + + /** + * Create shared ChunkedBufferBody. + * @param buffer - &id::oatpp::data::stream::ChunkedBuffer;. + * @param chunked - set `true` to send using HTTP chunked transfer encoding. Set `false` to send as body with specified `Content-Length` header. + * @return - `std::shared_ptr` to ChunkedBufferBody. + */ + static std::shared_ptr createShared(const std::shared_ptr& buffer, bool chunked = false); + + /** + * Add `Transfer-Encoding: chunked` header if `chunked` option was set to `true`. + * Else, add `Content-Length` header if `chunked` option was set to `false`. + * @param headers - &id:oatpp::web::protocol::http::Headers;. + */ void declareHeaders(Headers& headers) noexcept override; - + + /** + * Write body data to stream. + * @param stream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + */ void writeToStream(const std::shared_ptr& stream) noexcept override; public: - + + /** + * Coroutine used to write &l:ChunkedBufferBody; to &id:oatpp::data::stream::OutputStream;. + */ class WriteToStreamCoroutine : public oatpp::async::Coroutine { private: std::shared_ptr m_body; @@ -66,7 +91,12 @@ public: Action m_nextAction; v_char8 m_buffer[16]; public: - + + /** + * Constructor. + * @param body + * @param stream + */ WriteToStreamCoroutine(const std::shared_ptr& body, const std::shared_ptr& stream); @@ -78,7 +108,14 @@ public: Action writeCurrData(); }; - + + /** + * Start &l:ChunkedBufferBody::WriteToStreamCoroutine; to write buffer data to stream. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;. + * @param actionOnFinish - action to do once &l:ChunkedBufferBody::WriteToStreamCoroutine; is finished. + * @param stream - &id:oatpp::data::stream::OutputStream;. + * @return - &id:oatpp::async::Action; + */ Action writeToStreamAsync(oatpp::async::AbstractCoroutine* parentCoroutine, const Action& actionOnFinish, const std::shared_ptr& stream) override; diff --git a/src/oatpp/web/protocol/http/outgoing/CommunicationUtils.hpp b/src/oatpp/web/protocol/http/outgoing/CommunicationUtils.hpp index cda342b8..f7776226 100644 --- a/src/oatpp/web/protocol/http/outgoing/CommunicationUtils.hpp +++ b/src/oatpp/web/protocol/http/outgoing/CommunicationUtils.hpp @@ -29,20 +29,42 @@ #include "oatpp/web/protocol/http/outgoing/Response.hpp" namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing { - + +/** + * Helper class for communication utils. + */ class CommunicationUtils { public: + /** + * Connection state - close. + */ static constexpr v_int32 CONNECTION_STATE_CLOSE = 0; + + /** + * Connection state - keep alive. + */ static constexpr v_int32 CONNECTION_STATE_KEEP_ALIVE = 1; + + /** + * Connection state - upgrade. + */ static constexpr v_int32 CONNECTION_STATE_UPGRADE = 2; private: static bool headerEqualsCI_FAST(const oatpp::data::share::MemoryLabel& headerValue, const char* value); public: - + /** - * Consider keep connection alive taking into account request headers, response headers and protocol version. - * Corresponding header will be set to response if not existed before - * return one of (CONNECTION_STATE_CLOSE, CONNECTION_STATE_KEEP_ALIVE, CONNECTION_STATE_UPGRADE) + * Consider keep connection alive taking into account request headers, response headers and protocol version.
+ * Corresponding header will be set to response if not existed before.
+ * return one of (CONNECTION_STATE_CLOSE, CONNECTION_STATE_KEEP_ALIVE, CONNECTION_STATE_UPGRADE). + * @param request - `std::shared_ptr` to &id:oatpp::web::protocol::http::incoming::Request; + * @param response - `std::shared_ptr` to &id:oatpp::web::protocol::http::outgoing::Response; + * @return - one of values: + *
    + *
  • &l:CommunicationUtils::CONNECTION_STATE_CLOSE;
  • + *
  • &l:CommunicationUtils::CONNECTION_STATE_KEEP_ALIVE;
  • + *
  • &l:CommunicationUtils::CONNECTION_STATE_UPGRADE;
  • + *
*/ static v_int32 considerConnectionState(const std::shared_ptr& request, const std::shared_ptr& response); diff --git a/src/oatpp/web/protocol/http/outgoing/DtoBody.cpp b/src/oatpp/web/protocol/http/outgoing/DtoBody.cpp index 584dbb71..70dda5da 100644 --- a/src/oatpp/web/protocol/http/outgoing/DtoBody.cpp +++ b/src/oatpp/web/protocol/http/outgoing/DtoBody.cpp @@ -34,11 +34,6 @@ DtoBody::DtoBody(const oatpp::data::mapping::type::AbstractObjectWrapper& dto, , m_objectMapper(objectMapper) {} -std::shared_ptr DtoBody::createShared(const oatpp::data::mapping::type::AbstractObjectWrapper& dto, - oatpp::data::mapping::ObjectMapper* objectMapper) { - return Shared_Http_Outgoing_DtoBody_Pool::allocateShared(dto, objectMapper, false); -} - std::shared_ptr DtoBody::createShared(const oatpp::data::mapping::type::AbstractObjectWrapper& dto, oatpp::data::mapping::ObjectMapper* objectMapper, bool chunked) { diff --git a/src/oatpp/web/protocol/http/outgoing/DtoBody.hpp b/src/oatpp/web/protocol/http/outgoing/DtoBody.hpp index 1590c306..9c49f572 100644 --- a/src/oatpp/web/protocol/http/outgoing/DtoBody.hpp +++ b/src/oatpp/web/protocol/http/outgoing/DtoBody.hpp @@ -31,7 +31,12 @@ #include "oatpp/core/utils/ConversionUtils.hpp" namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing { - + +/** + * Implementation of &id:oatpp::web::protocol::http::outgoing::Body; class.
+ * Extends of &id:oatpp::web::protocol::http::outgoing::ChunkedBufferBody; class.
+ * Implements functionality to use DTO Object (see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/)) as data source for http body. + */ class DtoBody : public ChunkedBufferBody { public: OBJECT_POOL(Http_Outgoing_DtoBody_Pool, DtoBody, 32) @@ -40,18 +45,36 @@ private: oatpp::data::mapping::type::AbstractObjectWrapper m_dto; oatpp::data::mapping::ObjectMapper* m_objectMapper; public: + /** + * Constructor. + * @param dto - &id:oatpp::data::mapping::type::AbstractObjectWrapper;. + * @param objectMapper - &id:oatpp::data::mapping::ObjectMapper;. + * @param chunked - set `true` to send using HTTP chunked transfer encoding. Set `false` to send as body with specified `Content-Length` header. + */ DtoBody(const oatpp::data::mapping::type::AbstractObjectWrapper& dto, oatpp::data::mapping::ObjectMapper* objectMapper, - bool chunked); + bool chunked = false); public: - + + /** + * Create shared DtoBody. + * @param dto - &id:oatpp::data::mapping::type::AbstractObjectWrapper;. + * @param objectMapper - &id:oatpp::data::mapping::ObjectMapper;. + * @param chunked - set `true` to send using HTTP chunked transfer encoding. Set `false` to send as body with specified `Content-Length` header. + * @return - `std::shared_ptr` to DtoBody. + */ static std::shared_ptr createShared(const oatpp::data::mapping::type::AbstractObjectWrapper& dto, - oatpp::data::mapping::ObjectMapper* objectMapper); - - static std::shared_ptr createShared(const oatpp::data::mapping::type::AbstractObjectWrapper& dto, - oatpp::data::mapping::ObjectMapper* objectMapper, - bool chunked); - + oatpp::data::mapping::ObjectMapper* objectMapper, + bool chunked = false); + + /** + * Add `Transfer-Encoding: chunked` header if `chunked` option was set to `true`.
+ * Else, add `Content-Length` header if `chunked` option was set to `false`.
+ *
+ * Add `Content-Type` header depending on &id:oatpp::data::mapping::ObjectMapper; used. See &id:oatpp::data::mapping::ObjectMapper::Info;. + * + * @param headers - &id:oatpp::web::protocol::http::Headers;. + */ void declareHeaders(Headers& headers) noexcept override; }; diff --git a/src/oatpp/web/protocol/http/outgoing/Request.cpp b/src/oatpp/web/protocol/http/outgoing/Request.cpp index 9064f5fd..b1a1a349 100644 --- a/src/oatpp/web/protocol/http/outgoing/Request.cpp +++ b/src/oatpp/web/protocol/http/outgoing/Request.cpp @@ -54,7 +54,7 @@ const oatpp::data::share::StringKeyLabel& Request::getPath() const { return m_path; } -protocol::http::Protocol::Headers& Request::getHeaders() { +protocol::http::Headers& Request::getHeaders() { return m_headers; } diff --git a/src/oatpp/web/protocol/http/outgoing/Request.hpp b/src/oatpp/web/protocol/http/outgoing/Request.hpp index 3fd0ed3f..16e4b140 100644 --- a/src/oatpp/web/protocol/http/outgoing/Request.hpp +++ b/src/oatpp/web/protocol/http/outgoing/Request.hpp @@ -32,7 +32,7 @@ namespace oatpp { namespace web { namespace protocol { namespace http { namespac class Request : public oatpp::base::Countable, public std::enable_shared_from_this { public: - typedef protocol::http::Protocol::Headers Headers; + typedef protocol::http::Headers Headers; public: OBJECT_POOL(Outgoing_Request_Pool, Request, 32) SHARED_OBJECT_POOL(Shared_Outgoing_Request_Pool, Request, 32) diff --git a/src/oatpp/web/protocol/http/outgoing/Response.cpp b/src/oatpp/web/protocol/http/outgoing/Response.cpp index f5ac8ca2..fdc916a2 100644 --- a/src/oatpp/web/protocol/http/outgoing/Response.cpp +++ b/src/oatpp/web/protocol/http/outgoing/Response.cpp @@ -43,7 +43,7 @@ const Status& Response::getStatus() const { return m_status; } -protocol::http::Protocol::Headers& Response::getHeaders() { +protocol::http::Headers& Response::getHeaders() { return m_headers; } diff --git a/src/oatpp/web/protocol/http/outgoing/Response.hpp b/src/oatpp/web/protocol/http/outgoing/Response.hpp index ef59251a..96d0af89 100644 --- a/src/oatpp/web/protocol/http/outgoing/Response.hpp +++ b/src/oatpp/web/protocol/http/outgoing/Response.hpp @@ -39,9 +39,9 @@ class Response : public oatpp::base::Countable, public std::enable_shared_from_t public: /** * Convenience typedef for Headers.
- * See &id:oatpp::web::protocol::http::Protocol::Headers; + * See &id:oatpp::web::protocol::http::Headers; */ - typedef http::Protocol::Headers Headers; + typedef http::Headers Headers; public: OBJECT_POOL(Outgoing_Response_Pool, Response, 32) SHARED_OBJECT_POOL(Shared_Outgoing_Response_Pool, Response, 32) @@ -75,23 +75,55 @@ public: /** * Get headers. - * @return - &id:oatpp::web::protocol::http::Protocol::Headers; + * @return - &id:oatpp::web::protocol::http::Headers; */ Headers& getHeaders(); - + + /** + * Add http header. + * @param key - &id:oatpp::data::share::StringKeyLabelCI_FAST;. + * @param value - &id:oatpp::data::share::StringKeyLabel;. + */ void putHeader(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value); - + + /** + * Add http header if not already exists. + * @param key - &id:oatpp::data::share::StringKeyLabelCI_FAST;. + * @param value - &id:oatpp::data::share::StringKeyLabel;. + * @return - `true` if header was added. + */ bool putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value); - + + /** + * Set connection upgreade header.
+ * Use it together with corresponding headers being set when Response is created as:
+ * Response(&id:oatpp::web::protocol::http::Status::CODE_101;, nullptr);
+ * @param handler - `std::shared_ptr` to &id:oatpp::network::server::ConnectionHandler;. + */ void setConnectionUpgradeHandler(const std::shared_ptr& handler); - + + /** + * Get currently set connection upgrade handler + * @return - `std::shared_ptr` to &id:oatpp::network::server::ConnectionHandler;. + */ std::shared_ptr getConnectionUpgradeHandler(); - + + /** + * Write this Response to stream. + * @param stream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + */ void send(const std::shared_ptr& stream); - + + /** + * Same as &l:Response::send (); but async. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;. + * @param actionOnFinish - action to perform once done. + * @param stream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;. + * @return - &id:oatpp::async::Action;. + */ oatpp::async::Action sendAsync(oatpp::async::AbstractCoroutine* parentCoroutine, - const oatpp::async::Action& actionOnFinish, - const std::shared_ptr& stream); + const oatpp::async::Action& actionOnFinish, + const std::shared_ptr& stream); }; diff --git a/src/oatpp/web/protocol/http/outgoing/ResponseFactory.cpp b/src/oatpp/web/protocol/http/outgoing/ResponseFactory.cpp index df767678..5ae15d8a 100644 --- a/src/oatpp/web/protocol/http/outgoing/ResponseFactory.cpp +++ b/src/oatpp/web/protocol/http/outgoing/ResponseFactory.cpp @@ -36,8 +36,8 @@ ResponseFactory::createShared(const Status& status, const oatpp::String& text) { } std::shared_ptr -ResponseFactory::createShared(const Status& status, const std::shared_ptr& segBuffer) { - return Response::createShared(status, ChunkedBufferBody::createShared(segBuffer)); +ResponseFactory::createShared(const Status& status, const std::shared_ptr& chunkedBuffer) { + return Response::createShared(status, ChunkedBufferBody::createShared(chunkedBuffer)); } std::shared_ptr diff --git a/src/oatpp/web/protocol/http/outgoing/ResponseFactory.hpp b/src/oatpp/web/protocol/http/outgoing/ResponseFactory.hpp index 0570f4d6..72a0c58c 100644 --- a/src/oatpp/web/protocol/http/outgoing/ResponseFactory.hpp +++ b/src/oatpp/web/protocol/http/outgoing/ResponseFactory.hpp @@ -32,15 +32,39 @@ #include "oatpp/core/data/stream/ChunkedBuffer.hpp" namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing { - + +/** + * Helper class to create http outgoing responses (&id:oatpp::web::protocol::http::outgoing::Response). + */ class ResponseFactory { public: - + + /** + * Create &id:oatpp::web::protocol::http::outgoing::Response; with &id:oatpp::web::protocol::http::outgoing::BufferBody;. + * @param status - &id:oatpp::web::protocol::http::Status;. + * @param text - &id:oatpp::String;. + * @return - &id:oatpp::web::protocol::http::outgoing::Response;. + */ static std::shared_ptr createShared(const Status& status, const oatpp::String& text); - static std::shared_ptr createShared(const Status& status, const std::shared_ptr& segBuffer); + + /** + * Create &id:oatpp::web::protocol::http::outgoing::Response; with &id:oatpp::web::protocol::http::outgoing::ChunkedBufferBody;. + * @param status - &id:oatpp::web::protocol::http::Status;. + * @param chunkedBuffer - &id:oatpp::data::stream::ChunkedBuffer;. + * @return - &id:oatpp::web::protocol::http::outgoing::Response;. + */ + static std::shared_ptr createShared(const Status& status, const std::shared_ptr& chunkedBuffer); + + /** + * Create &id:oatpp::web::protocol::http::outgoing::Response; with &id:oatpp::web::protocol::http::outgoing::DtoBody;. + * @param status - &id:oatpp::web::protocol::http::Status;. + * @param dto - see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/). + * @param objectMapper - &id:oatpp::data::mapping::ObjectMapper;. + * @return - &id:oatpp::web::protocol::http::outgoing::Response;. + */ static std::shared_ptr createShared(const Status& status, - const oatpp::data::mapping::type::AbstractObjectWrapper& dto, - oatpp::data::mapping::ObjectMapper* objectMapper); + const oatpp::data::mapping::type::AbstractObjectWrapper& dto, + oatpp::data::mapping::ObjectMapper* objectMapper); }; diff --git a/src/oatpp/web/server/HttpProcessor.cpp b/src/oatpp/web/server/HttpProcessor.cpp index b4811718..206a9bd7 100644 --- a/src/oatpp/web/server/HttpProcessor.cpp +++ b/src/oatpp/web/server/HttpProcessor.cpp @@ -80,7 +80,7 @@ HttpProcessor::processRequest(HttpRouter* router, currInterceptor = currInterceptor->getNext(); } if(!response) { - response = route.processUrl(request); + response = route.processEvent(request); } } catch (oatpp::web::protocol::http::HttpError& error) { return errorHandler->handleError(error.getInfo().status, error.getMessage()); @@ -141,7 +141,7 @@ HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::act() { HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::onRequestFormed() { HttpRouter::BranchRouter::UrlSubscriber::AsyncCallback callback = static_cast(&HttpProcessor::Coroutine::onResponse); - return m_currentRoute.processUrlAsync(this, callback, m_currentRequest); + return m_currentRoute.processEventAsync(this, callback, m_currentRequest); } HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::onResponse(const std::shared_ptr& response) { diff --git a/src/oatpp/web/server/api/ApiController.hpp b/src/oatpp/web/server/api/ApiController.hpp index 7cae5e15..a658ca88 100644 --- a/src/oatpp/web/server/api/ApiController.hpp +++ b/src/oatpp/web/server/api/ApiController.hpp @@ -56,7 +56,7 @@ public: typedef oatpp::web::protocol::http::outgoing::Response OutgoingResponse; typedef oatpp::web::protocol::http::Status Status; typedef oatpp::web::protocol::http::Header Header; - typedef oatpp::web::protocol::http::Protocol::QueryParams QueryParams; + typedef oatpp::web::protocol::http::QueryParams QueryParams; typedef oatpp::web::server::api::Endpoint Endpoint; typedef oatpp::collection::LinkedList> Endpoints; @@ -120,7 +120,7 @@ protected: return std::make_shared(controller, method, methodAsync); } - std::shared_ptr processUrl(const std::shared_ptr& request) override { + std::shared_ptr processEvent(const std::shared_ptr& request) override { if(m_method != nullptr) { return (m_controller->*m_method)(request); } else { @@ -128,7 +128,7 @@ protected: } } - Action processUrlAsync(oatpp::async::AbstractCoroutine* parentCoroutine, + Action processEventAsync(oatpp::async::AbstractCoroutine* parentCoroutine, AsyncCallback callback, const std::shared_ptr& request) override { if(m_methodAsync != nullptr) { diff --git a/src/oatpp/web/url/mapping/Router.hpp b/src/oatpp/web/url/mapping/Router.hpp index 220f4977..13cc25b0 100644 --- a/src/oatpp/web/url/mapping/Router.hpp +++ b/src/oatpp/web/url/mapping/Router.hpp @@ -84,25 +84,25 @@ public: {} /** - * Call &id:oatpp::web::url::mapping::Subscriber::processUrl; with corresponding parameter. + * Call &id:oatpp::web::url::mapping::Subscriber::processEvent; with corresponding parameter. * @param param * @return - corresponding ReturnType. */ - ReturnType processUrl(const Param& param) const { - return m_subscriber->processUrl(param); + ReturnType processEvent(const Param& param) const { + return m_subscriber->processEvent(param); } /** - * Call &id:oatpp::web::url::mapping::Subscriber::processUrlAsync; with corresponding parameter. + * Call &id:oatpp::web::url::mapping::Subscriber::processEventAsync; with corresponding parameter. * @param parentCoroutine - caller coroutine. &id:oatpp::async::AbstractCoroutine;. * @param callback - pointer to callback function. * @param param * @return - &id:oatpp::async::Action;. */ - oatpp::async::Action processUrlAsync(oatpp::async::AbstractCoroutine* parentCoroutine, - typename UrlSubscriber::AsyncCallback callback, - const Param& param) const { - return m_subscriber->processUrlAsync(parentCoroutine, callback, param); + oatpp::async::Action processEventAsync(oatpp::async::AbstractCoroutine* parentCoroutine, + typename UrlSubscriber::AsyncCallback callback, + const Param& param) const { + return m_subscriber->processEventAsync(parentCoroutine, callback, param); } explicit operator bool() const { diff --git a/src/oatpp/web/url/mapping/Subscriber.hpp b/src/oatpp/web/url/mapping/Subscriber.hpp index 80c21463..11cb27ce 100644 --- a/src/oatpp/web/url/mapping/Subscriber.hpp +++ b/src/oatpp/web/url/mapping/Subscriber.hpp @@ -29,17 +29,38 @@ #include "oatpp/core/async/Coroutine.hpp" namespace oatpp { namespace web { namespace url { namespace mapping { - -template + +/** + * Abstract subscriber which can subscribe to incoming events from &id:oatpp::web::url::mapping::Router; and process those events. + * @tparam Event - incoming event type. + * @tparam Result - result of event processing. + */ +template class Subscriber { public: + /** + * Convenience typedef for &id:oatpp::async::Action; + */ typedef oatpp::async::Action Action; - typedef Action (oatpp::async::AbstractCoroutine::*AsyncCallback)(const ReturnType&); + typedef Action (oatpp::async::AbstractCoroutine::*AsyncCallback)(const Result&); public: - virtual ReturnType processUrl(const Param& param) = 0; - virtual Action processUrlAsync(oatpp::async::AbstractCoroutine* parentCoroutine, - AsyncCallback callback, - const Param& param) = 0; + /** + * Process event. + * @param Event - some incoming data. + * @return - some outgoing data. + */ + virtual Result processEvent(const Event& event) = 0; + + /** + * Process event in asynchronous manner. + * @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*. + * @param callback - pointer to callback function. + * @param event - some incoming data. + * @return - &id:oatpp::async::Action;. + */ + virtual Action processEventAsync(oatpp::async::AbstractCoroutine* parentCoroutine, + AsyncCallback callback, + const Event& event) = 0; }; }}}} diff --git a/test/oatpp/core/data/share/MemoryLabelTest.cpp b/test/oatpp/core/data/share/MemoryLabelTest.cpp index 2df7008d..a9912ee3 100644 --- a/test/oatpp/core/data/share/MemoryLabelTest.cpp +++ b/test/oatpp/core/data/share/MemoryLabelTest.cpp @@ -123,8 +123,8 @@ void MemoryLabelTest::onRun() { oatpp::parser::Caret caret(headersText); oatpp::web::protocol::http::Status status; - oatpp::web::protocol::http::Protocol::Headers headers; - oatpp::web::protocol::http::Protocol::parseHeaders(headers, headersText.getPtr(), caret, status); + oatpp::web::protocol::http::Headers headers; + oatpp::web::protocol::http::Parser::parseHeaders(headers, headersText.getPtr(), caret, status); OATPP_ASSERT(status.code == 0); OATPP_ASSERT(headers.size() == 10);