minor refactoring plus more API-docs for oatpp::web::protocol::http::*

This commit is contained in:
lganzzzo 2019-03-22 04:33:45 +02:00
parent 704fdb52c2
commit fa0b9561a6
35 changed files with 694 additions and 183 deletions

View File

@ -112,8 +112,8 @@ void ApiClient::addPathQueryParams(oatpp::data::stream::OutputStream* stream,
}
oatpp::web::protocol::http::Protocol::Headers ApiClient::convertParamsMap(const std::shared_ptr<StringToParamMap>& params) {
oatpp::web::protocol::http::Protocol::Headers result;
oatpp::web::protocol::http::Headers ApiClient::convertParamsMap(const std::shared_ptr<StringToParamMap>& params) {
oatpp::web::protocol::http::Headers result;
if(params) {
auto curr = params->getFirstEntry();

View File

@ -147,7 +147,7 @@ private:
void addPathQueryParams(oatpp::data::stream::OutputStream* stream,
const std::shared_ptr<StringToParamMap>& params);
oatpp::web::protocol::http::Protocol::Headers convertParamsMap(const std::shared_ptr<StringToParamMap>& params);
oatpp::web::protocol::http::Headers convertParamsMap(const std::shared_ptr<StringToParamMap>& params);
protected:

View File

@ -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;.

View File

@ -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<oatpp::base::StrBuffer>& headersText,
oatpp::data::share::StringKeyLabelCI_FAST Parser::parseHeaderNameLabel(const std::shared_ptr<oatpp::base::StrBuffer>& 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<oatpp::base::StrBuffer>& 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<oatpp::base::StrBuffer>& 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<oatpp::base::StrBuffer>& 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<oatpp::base::StrBuffer>& headersText,
oatpp::parser::Caret& caret,
Status& error) {

View File

@ -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<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
typedef std::unordered_map<oatpp::data::share::StringKeyLabel, oatpp::data::share::StringKeyLabel> 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<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> 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<oatpp::data::share::StringKeyLabel, oatpp::data::share::StringKeyLabel> QueryParams;
/**
* Oatpp Http parser.
*/
class Parser {
private:
static oatpp::data::share::StringKeyLabelCI_FAST parseHeaderNameLabel(const std::shared_ptr<oatpp::base::StrBuffer>& 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<oatpp::base::StrBuffer>& 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<oatpp::base::StrBuffer>& 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<oatpp::base::StrBuffer>& 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<oatpp::base::StrBuffer>& headersText,
oatpp::parser::Caret& caret,

View File

@ -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<oatpp::data::stream::InputStream>& bodyStream)
: m_decoder(decoder)
, m_headers(headers)

View File

@ -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<ToStringDecoder, oatpp::String> {
private:
const BodyDecoder* m_decoder;
Protocol::Headers m_headers;
Headers m_headers;
std::shared_ptr<oatpp::data::stream::InputStream> m_bodyStream;
std::shared_ptr<oatpp::data::stream::ChunkedBuffer> m_chunkedBuffer;
public:
ToStringDecoder(const BodyDecoder* decoder,
const Protocol::Headers& headers,
const Headers& headers,
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream);
Action act() override;
@ -55,14 +61,14 @@ private:
class ToDtoDecoder : public oatpp::async::CoroutineWithResult<ToDtoDecoder<Type>, typename Type::ObjectWrapper> {
private:
const BodyDecoder* m_decoder;
Protocol::Headers m_headers;
Headers m_headers;
std::shared_ptr<oatpp::data::stream::InputStream> m_bodyStream;
std::shared_ptr<oatpp::data::mapping::ObjectMapper> m_objectMapper;
std::shared_ptr<oatpp::data::stream::ChunkedBuffer> m_chunkedBuffer = oatpp::data::stream::ChunkedBuffer::createShared();
public:
ToDtoDecoder(const BodyDecoder* decoder,
Protocol::Headers& headers,
Headers& headers,
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& 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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<oatpp::data::stream::OutputStream>& 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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<oatpp::data::stream::OutputStream>& 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<oatpp::data::stream::InputStream>& 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<class Type>
typename Type::ObjectWrapper decodeToDto(const Protocol::Headers& headers,
typename Type::ObjectWrapper decodeToDto(const Headers& headers,
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const {
return objectMapper->readFromString<Type>(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<typename ParentCoroutineType>
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<oatpp::data::stream::InputStream>& bodyStream) const {
return parentCoroutine->startCoroutineForResult<ToStringDecoder>(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<class DtoType, typename ParentCoroutineType>
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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const {
return parentCoroutine->startCoroutineForResult<ToDtoDecoder<DtoType>>(callback, this, headers, bodyStream, objectMapper);

View File

@ -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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder)
: m_startingLine(startingLine)
@ -41,7 +41,7 @@ Request::Request(const http::RequestStartingLine& startingLine,
std::shared_ptr<Request> 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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<const http::incoming::BodyDecoder>& 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;

View File

@ -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<oatpp::data::stream::InputStream> m_bodyStream;
/*
@ -53,20 +53,20 @@ private:
std::shared_ptr<const http::incoming::BodyDecoder> 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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder);
public:
static 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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder);
@ -76,7 +76,7 @@ public:
* Please note: lazy parsing of query parameters is not thread-safe!
* @return map<key, value> 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

View File

@ -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 {

View File

@ -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<oatpp::data::stream::IOStream>& 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<oatpp::data::stream::IOStream>& connection);

View File

@ -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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder)
: m_statusCode(statusCode)
@ -40,7 +40,7 @@ Response::Response(v_int32 statusCode,
std::shared_ptr<Response> Response::createShared(v_int32 statusCode,
const oatpp::String& statusDescription,
const http::Protocol::Headers& headers,
const http::Headers& headers,
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<const http::incoming::BodyDecoder>& 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;
}

View File

@ -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<oatpp::data::stream::InputStream> 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<oatpp::data::stream::IOStream> 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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<const http::incoming::BodyDecoder>& 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<Response> createShared(v_int32 statusCode,
const oatpp::String& statusDescription,
const http::Protocol::Headers& headers,
const http::Headers& headers,
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<const http::incoming::BodyDecoder>& 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<oatpp::data::stream::InputStream> getBodyStream() const;
/**
* Get body decoder configured for this response.
* @return - &id:oatpp::web::protocol::http::incoming::BodyDecoder;.
*/
std::shared_ptr<const http::incoming::BodyDecoder> 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<oatpp::data::stream::OutputStream>& 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<class Type>
typename Type::ObjectWrapper readBodyToDto(const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const {
return m_bodyDecoder->decodeToDto<Type>(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<oatpp::data::stream::OutputStream>& 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<typename ParentCoroutineType>
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<class DtoType, typename ParentCoroutineType>
oatpp::async::Action readBodyToDtoAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
oatpp::async::Action (ParentCoroutineType::*callback)(const typename DtoType::ObjectWrapper&),

View File

@ -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 {

View File

@ -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<oatpp::data::stream::IOStream>& 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<oatpp::data::stream::IOStream>& connection);

View File

@ -83,7 +83,7 @@ void SimpleBodyDecoder::doChunkedDecoding(const std::shared_ptr<oatpp::data::str
}
void SimpleBodyDecoder::decode(const Protocol::Headers& headers,
void SimpleBodyDecoder::decode(const Headers& headers,
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<oatpp::data::stream::OutputStream>& 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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<oatpp::data::stream::OutputStream>& toStream) const {
auto transferEncodingIt = headers.find(Header::TRANSFER_ENCODING);

View File

@ -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<oatpp::data::stream::InputStream>& fromStream,
@ -42,14 +45,29 @@ private:
const std::shared_ptr<oatpp::data::stream::InputStream>& fromStream,
const std::shared_ptr<oatpp::data::stream::OutputStream>& 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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<oatpp::data::stream::OutputStream>& 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<oatpp::data::stream::InputStream>& bodyStream,
const std::shared_ptr<oatpp::data::stream::OutputStream>& toStream) const override;

View File

@ -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<OutputStream>& 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<OutputStream>& stream) = 0;

View File

@ -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<BufferBody> {
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<BufferBody> 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<OutputStream>& stream) noexcept override;
public:
/**
* Coroutine used to write &l:BufferBody; to &id:oatpp::data::stream::OutputStream;.
*/
class WriteToStreamCoroutine : public oatpp::async::Coroutine<WriteToStreamCoroutine> {
private:
std::shared_ptr<BufferBody> 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<BufferBody>& body,
const std::shared_ptr<OutputStream>& 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<OutputStream>& stream) override;
const Action& actionOnReturn,
const std::shared_ptr<OutputStream>& stream) override;
};

View File

@ -33,11 +33,6 @@ ChunkedBufferBody::ChunkedBufferBody(const std::shared_ptr<oatpp::data::stream::
, m_chunked(chunked)
{}
std::shared_ptr<ChunkedBufferBody> ChunkedBufferBody::createShared(const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& buffer) {
return Shared_Http_Outgoing_ChunkedBufferBody_Pool::allocateShared(buffer, false);
}
std::shared_ptr<ChunkedBufferBody> ChunkedBufferBody::createShared(const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& buffer, bool chunked) {
return Shared_Http_Outgoing_ChunkedBufferBody_Pool::allocateShared(buffer, chunked);
}

View File

@ -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<ChunkedBufferBody> {
public:
static const char* ERROR_FAILED_TO_WRITE_DATA;
@ -42,19 +46,40 @@ protected:
std::shared_ptr<oatpp::data::stream::ChunkedBuffer> m_buffer;
bool m_chunked;
public:
ChunkedBufferBody(const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& 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<oatpp::data::stream::ChunkedBuffer>& buffer, bool chunked = false);
public:
static std::shared_ptr<ChunkedBufferBody> createShared(const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& buffer);
static std::shared_ptr<ChunkedBufferBody> createShared(const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& 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<ChunkedBufferBody> createShared(const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& 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<OutputStream>& stream) noexcept override;
public:
/**
* Coroutine used to write &l:ChunkedBufferBody; to &id:oatpp::data::stream::OutputStream;.
*/
class WriteToStreamCoroutine : public oatpp::async::Coroutine<WriteToStreamCoroutine> {
private:
std::shared_ptr<ChunkedBufferBody> 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<ChunkedBufferBody>& body,
const std::shared_ptr<OutputStream>& 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<OutputStream>& stream) override;

View File

@ -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.<br>
* Corresponding header will be set to response if not existed before. <br>
* 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:
* <ul>
* <li>&l:CommunicationUtils::CONNECTION_STATE_CLOSE;</li>
* <li>&l:CommunicationUtils::CONNECTION_STATE_KEEP_ALIVE;</li>
* <li>&l:CommunicationUtils::CONNECTION_STATE_UPGRADE;</li>
* </ul>
*/
static v_int32 considerConnectionState(const std::shared_ptr<protocol::http::incoming::Request>& request,
const std::shared_ptr<protocol::http::outgoing::Response>& response);

View File

@ -34,11 +34,6 @@ DtoBody::DtoBody(const oatpp::data::mapping::type::AbstractObjectWrapper& dto,
, m_objectMapper(objectMapper)
{}
std::shared_ptr<DtoBody> 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> DtoBody::createShared(const oatpp::data::mapping::type::AbstractObjectWrapper& dto,
oatpp::data::mapping::ObjectMapper* objectMapper,
bool chunked) {

View File

@ -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. <br>
* Extends of &id:oatpp::web::protocol::http::outgoing::ChunkedBufferBody; class. <br>
* 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<DtoBody> createShared(const oatpp::data::mapping::type::AbstractObjectWrapper& dto,
oatpp::data::mapping::ObjectMapper* objectMapper);
static std::shared_ptr<DtoBody> 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`.<br>
* Else, add `Content-Length` header if `chunked` option was set to `false`.<br>
* <br>
* 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;
};

View File

@ -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;
}

View File

@ -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<Request> {
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)

View File

@ -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;
}

View File

@ -39,9 +39,9 @@ class Response : public oatpp::base::Countable, public std::enable_shared_from_t
public:
/**
* Convenience typedef for Headers. <br>
* 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. <br>
* Use it together with corresponding headers being set when Response is created as: <br>
* Response(&id:oatpp::web::protocol::http::Status::CODE_101;, nullptr);<br>
* @param handler - `std::shared_ptr` to &id:oatpp::network::server::ConnectionHandler;.
*/
void setConnectionUpgradeHandler(const std::shared_ptr<oatpp::network::server::ConnectionHandler>& handler);
/**
* Get currently set connection upgrade handler
* @return - `std::shared_ptr` to &id:oatpp::network::server::ConnectionHandler;.
*/
std::shared_ptr<oatpp::network::server::ConnectionHandler> getConnectionUpgradeHandler();
/**
* Write this Response to stream.
* @param stream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;.
*/
void send(const std::shared_ptr<data::stream::OutputStream>& 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<data::stream::OutputStream>& stream);
const oatpp::async::Action& actionOnFinish,
const std::shared_ptr<data::stream::OutputStream>& stream);
};

View File

@ -36,8 +36,8 @@ ResponseFactory::createShared(const Status& status, const oatpp::String& text) {
}
std::shared_ptr<Response>
ResponseFactory::createShared(const Status& status, const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& segBuffer) {
return Response::createShared(status, ChunkedBufferBody::createShared(segBuffer));
ResponseFactory::createShared(const Status& status, const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& chunkedBuffer) {
return Response::createShared(status, ChunkedBufferBody::createShared(chunkedBuffer));
}
std::shared_ptr<Response>

View File

@ -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<Response> createShared(const Status& status, const oatpp::String& text);
static std::shared_ptr<Response> createShared(const Status& status, const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& 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<Response> createShared(const Status& status, const std::shared_ptr<oatpp::data::stream::ChunkedBuffer>& 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<Response> 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);
};

View File

@ -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<HttpRouter::BranchRouter::UrlSubscriber::AsyncCallback>(&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<protocol::http::outgoing::Response>& response) {

View File

@ -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<std::shared_ptr<Endpoint>> Endpoints;
@ -120,7 +120,7 @@ protected:
return std::make_shared<Handler>(controller, method, methodAsync);
}
std::shared_ptr<OutgoingResponse> processUrl(const std::shared_ptr<protocol::http::incoming::Request>& request) override {
std::shared_ptr<OutgoingResponse> processEvent(const std::shared_ptr<protocol::http::incoming::Request>& 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<protocol::http::incoming::Request>& request) override {
if(m_methodAsync != nullptr) {

View File

@ -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 {

View File

@ -29,17 +29,38 @@
#include "oatpp/core/async/Coroutine.hpp"
namespace oatpp { namespace web { namespace url { namespace mapping {
template<class Param, class ReturnType>
/**
* 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 Event, class Result>
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;
};
}}}}

View File

@ -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);