mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2024-12-22 22:16:37 +08:00
Merge branch 'master' into fixescorsswagger
This commit is contained in:
commit
2c33ef4c8e
@ -84,10 +84,11 @@ add_library(oatpp
|
||||
oatpp/core/data/mapping/type/Primitive.hpp
|
||||
oatpp/core/data/mapping/type/Type.cpp
|
||||
oatpp/core/data/mapping/type/Type.hpp
|
||||
oatpp/core/data/share/LazyStringMap.hpp
|
||||
oatpp/core/data/share/MemoryLabel.cpp
|
||||
oatpp/core/data/share/MemoryLabel.hpp
|
||||
oatpp/core/data/stream/BufferInputStream.cpp
|
||||
oatpp/core/data/stream/BufferInputStream.hpp
|
||||
oatpp/core/data/stream/BufferStream.cpp
|
||||
oatpp/core/data/stream/BufferStream.hpp
|
||||
oatpp/core/data/stream/ChunkedBuffer.cpp
|
||||
oatpp/core/data/stream/ChunkedBuffer.hpp
|
||||
oatpp/core/data/stream/FileStream.cpp
|
||||
|
@ -220,6 +220,8 @@ CoroutineHandle::~CoroutineHandle() {
|
||||
|
||||
Action CoroutineHandle::takeAction(Action&& action) {
|
||||
|
||||
//v_int32 iterations = 0;
|
||||
|
||||
while (true) {
|
||||
|
||||
switch (action.m_type) {
|
||||
@ -245,9 +247,18 @@ Action CoroutineHandle::takeAction(Action&& action) {
|
||||
|
||||
case Action::TYPE_YIELD_TO: {
|
||||
_FP = action.m_data.fptr;
|
||||
//break;
|
||||
return std::forward<oatpp::async::Action>(action);
|
||||
}
|
||||
|
||||
// case Action::TYPE_REPEAT: {
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// case Action::TYPE_IO_REPEAT: {
|
||||
// break;
|
||||
// }
|
||||
|
||||
case Action::TYPE_ERROR: {
|
||||
Action newAction = _CP->handleError(action.m_data.error);
|
||||
|
||||
@ -277,6 +288,9 @@ Action CoroutineHandle::takeAction(Action&& action) {
|
||||
|
||||
};
|
||||
|
||||
// action = iterate();
|
||||
// ++ iterations;
|
||||
|
||||
}
|
||||
|
||||
return std::forward<oatpp::async::Action>(action);
|
||||
|
@ -78,13 +78,14 @@ void Executor::SubmissionProcessor::detach() {
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Executor
|
||||
|
||||
Executor::Executor(v_int32 processorWorkersCount, v_int32 ioWorkersCount, v_int32 timerWorkersCount, bool useIOEventWorker)
|
||||
Executor::Executor(v_int32 processorWorkersCount, v_int32 ioWorkersCount, v_int32 timerWorkersCount, v_int32 ioWorkerType)
|
||||
: m_balancer(0)
|
||||
{
|
||||
|
||||
processorWorkersCount = chooseProcessorWorkersCount(processorWorkersCount);
|
||||
ioWorkersCount = chooseIOWorkersCount(processorWorkersCount, ioWorkersCount);
|
||||
timerWorkersCount = chooseTimerWorkersCount(timerWorkersCount);
|
||||
ioWorkerType = chooseIOWorkerType(ioWorkerType);
|
||||
|
||||
for(v_int32 i = 0; i < processorWorkersCount; i ++) {
|
||||
m_processorWorkers.push_back(std::make_shared<SubmissionProcessor>());
|
||||
@ -93,14 +94,26 @@ Executor::Executor(v_int32 processorWorkersCount, v_int32 ioWorkersCount, v_int3
|
||||
m_allWorkers.insert(m_allWorkers.end(), m_processorWorkers.begin(), m_processorWorkers.end());
|
||||
|
||||
std::vector<std::shared_ptr<worker::Worker>> ioWorkers;
|
||||
if(useIOEventWorker) {
|
||||
for (v_int32 i = 0; i < ioWorkersCount; i++) {
|
||||
ioWorkers.push_back(std::make_shared<worker::IOEventWorkerForeman>());
|
||||
|
||||
switch(ioWorkerType) {
|
||||
|
||||
case IO_WORKER_TYPE_NAIVE: {
|
||||
for (v_int32 i = 0; i < ioWorkersCount; i++) {
|
||||
ioWorkers.push_back(std::make_shared<worker::IOWorker>());
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (v_int32 i = 0; i < ioWorkersCount; i++) {
|
||||
ioWorkers.push_back(std::make_shared<worker::IOWorker>());
|
||||
|
||||
case IO_WORKER_TYPE_EVENT: {
|
||||
for (v_int32 i = 0; i < ioWorkersCount; i++) {
|
||||
ioWorkers.push_back(std::make_shared<worker::IOEventWorkerForeman>());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error("[oatpp::async::Executor::Executor()]: Error. Unknown IO worker type.");
|
||||
|
||||
}
|
||||
|
||||
linkWorkers(ioWorkers);
|
||||
@ -148,6 +161,20 @@ v_int32 Executor::chooseTimerWorkersCount(v_int32 timerWorkersCount) {
|
||||
throw std::runtime_error("[oatpp::async::Executor::chooseTimerWorkersCount()]: Error. Invalid timer workers count specified.");
|
||||
}
|
||||
|
||||
v_int32 Executor::chooseIOWorkerType(v_int32 ioWorkerType) {
|
||||
|
||||
if(ioWorkerType == VALUE_SUGGESTED) {
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
return IO_WORKER_TYPE_NAIVE;
|
||||
#else
|
||||
return IO_WORKER_TYPE_EVENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
return ioWorkerType;
|
||||
|
||||
}
|
||||
|
||||
void Executor::linkWorkers(const std::vector<std::shared_ptr<worker::Worker>>& workers) {
|
||||
|
||||
m_allWorkers.insert(m_allWorkers.end(), workers.begin(), workers.end());
|
||||
|
@ -84,6 +84,17 @@ public:
|
||||
* Special value to indicate that Executor should choose it's own the value of specified parameter.
|
||||
*/
|
||||
static constexpr const v_int32 VALUE_SUGGESTED = -1000;
|
||||
public:
|
||||
|
||||
/**
|
||||
* IO Worker type naive.
|
||||
*/
|
||||
static constexpr const v_int32 IO_WORKER_TYPE_NAIVE = 0;
|
||||
|
||||
/**
|
||||
* IO Worker type event.
|
||||
*/
|
||||
static constexpr const v_int32 IO_WORKER_TYPE_EVENT = 1;
|
||||
private:
|
||||
std::atomic<v_word32> m_balancer;
|
||||
private:
|
||||
@ -93,6 +104,7 @@ private:
|
||||
static v_int32 chooseProcessorWorkersCount(v_int32 processorWorkersCount);
|
||||
static v_int32 chooseIOWorkersCount(v_int32 processorWorkersCount, v_int32 ioWorkersCount);
|
||||
static v_int32 chooseTimerWorkersCount(v_int32 timerWorkersCount);
|
||||
static v_int32 chooseIOWorkerType(v_int32 ioWorkerType);
|
||||
void linkWorkers(const std::vector<std::shared_ptr<worker::Worker>>& workers);
|
||||
public:
|
||||
|
||||
@ -101,16 +113,12 @@ public:
|
||||
* @param processorWorkersCount - number of data processing workers.
|
||||
* @param ioWorkersCount - number of I/O processing workers.
|
||||
* @param timerWorkersCount - number of timer processing workers.
|
||||
* @param IOWorkerType
|
||||
*/
|
||||
Executor(v_int32 processorWorkersCount = VALUE_SUGGESTED,
|
||||
v_int32 ioWorkersCount = VALUE_SUGGESTED,
|
||||
v_int32 timerWorkersCount = VALUE_SUGGESTED,
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
bool useIOEventWorker = false
|
||||
#else
|
||||
bool useIOEventWorker = true
|
||||
#endif
|
||||
);
|
||||
v_int32 ioWorkerType = VALUE_SUGGESTED);
|
||||
|
||||
/**
|
||||
* Non-virtual Destructor.
|
||||
|
207
src/oatpp/core/data/share/LazyStringMap.hpp
Normal file
207
src/oatpp/core/data/share/LazyStringMap.hpp
Normal file
@ -0,0 +1,207 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_data_share_LazyStringMap_hpp
|
||||
#define oatpp_data_share_LazyStringMap_hpp
|
||||
|
||||
#include "./MemoryLabel.hpp"
|
||||
#include <unordered_map>
|
||||
|
||||
namespace oatpp { namespace data { namespace share {
|
||||
|
||||
/**
|
||||
* Lazy String Map keeps keys, and values as memory label.
|
||||
* Once value is requested by user, the new memory block is allocated and value is copied to be stored permanently.
|
||||
* @tparam Key - one of: &id:oatpp::data::share::MemoryLabel;, &id:oatpp::data::share::StringKeyLabel;, &id:oatpp::data::share::StringKeyLabelCI;,
|
||||
* &id:oatpp::data::share::StringKeyLabelCI_FAST;.
|
||||
*/
|
||||
template<class Key>
|
||||
class LazyStringMap {
|
||||
private:
|
||||
mutable bool m_fullyInitialized;
|
||||
std::unordered_map<Key, StringKeyLabel> m_map;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
LazyStringMap()
|
||||
: m_fullyInitialized(false)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Default copy-constructor.
|
||||
* @param other
|
||||
*/
|
||||
LazyStringMap(const LazyStringMap& other) = default;
|
||||
|
||||
/**
|
||||
* Move constructor.
|
||||
* @param other
|
||||
*/
|
||||
LazyStringMap(LazyStringMap&& other)
|
||||
: m_fullyInitialized(false)
|
||||
, m_map(std::move(other.m_map))
|
||||
{}
|
||||
|
||||
LazyStringMap& operator = (LazyStringMap& other) = default;
|
||||
|
||||
LazyStringMap& operator = (LazyStringMap&& other){
|
||||
m_fullyInitialized = false;
|
||||
m_map = std::move(other.m_map);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put value to map.
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
void put(const Key& key, const StringKeyLabel& value) {
|
||||
m_map.insert({key, value});
|
||||
m_fullyInitialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put value to map if not already exists.
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
bool putIfNotExists(const Key& key, const StringKeyLabel& value) {
|
||||
|
||||
auto it = m_map.find(key);
|
||||
|
||||
if(it == m_map.end()) {
|
||||
m_map.insert({key, value});
|
||||
m_fullyInitialized = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value as &id:oatpp::String;.
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
oatpp::String get(const Key& key) const {
|
||||
|
||||
auto it = m_map.find(key);
|
||||
|
||||
if(it != m_map.end()) {
|
||||
it->second.captureToOwnMemory();
|
||||
return it->second.getMemoryHandle();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value as a memory label.
|
||||
* @tparam T - one of: &id:oatpp::data::share::MemoryLabel;, &id:oatpp::data::share::StringKeyLabel;, &id:oatpp::data::share::StringKeyLabelCI;,
|
||||
* &id:oatpp::data::share::StringKeyLabelCI_FAST;.
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
template<class T>
|
||||
T getAsMemoryLabel(const Key& key) const {
|
||||
|
||||
auto it = m_map.find(key);
|
||||
|
||||
if(it != m_map.end()) {
|
||||
it->second.captureToOwnMemory();
|
||||
const auto& label = it->second;
|
||||
return T(label.getMemoryHandle(), label.getData(), label.getSize());
|
||||
}
|
||||
|
||||
return T(nullptr, nullptr, 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value as a memory label without allocating memory for value.
|
||||
* @tparam T - one of: &id:oatpp::data::share::MemoryLabel;, &id:oatpp::data::share::StringKeyLabel;, &id:oatpp::data::share::StringKeyLabelCI;,
|
||||
* &id:oatpp::data::share::StringKeyLabelCI_FAST;.
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
template<class T>
|
||||
T getAsMemoryLabel_Unsafe(const Key& key) const {
|
||||
|
||||
auto it = m_map.find(key);
|
||||
|
||||
if(it != m_map.end()) {
|
||||
const auto& label = it->second;
|
||||
return T(label.getMemoryHandle(), label.getData(), label.getSize());
|
||||
}
|
||||
|
||||
return T(nullptr, nullptr, 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get map of all values.
|
||||
* @return
|
||||
*/
|
||||
const std::unordered_map<Key, StringKeyLabel>& getAll() const {
|
||||
|
||||
if(!m_fullyInitialized) {
|
||||
|
||||
for(auto& pair : m_map) {
|
||||
pair.first.captureToOwnMemory();
|
||||
pair.second.captureToOwnMemory();
|
||||
}
|
||||
|
||||
m_fullyInitialized = true;
|
||||
}
|
||||
|
||||
return m_map;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get map of all values without allocating memory for those keys/values.
|
||||
* @return
|
||||
*/
|
||||
const std::unordered_map<Key, StringKeyLabel>& getAll_Unsafe() const {
|
||||
return m_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of entries in the map.
|
||||
* @return
|
||||
*/
|
||||
v_int32 getSize() const {
|
||||
return (v_int32) m_map.size();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif //oatpp_data_share_LazyStringMap_hpp
|
@ -37,8 +37,8 @@ namespace oatpp { namespace data { namespace share {
|
||||
*/
|
||||
class MemoryLabel {
|
||||
protected:
|
||||
std::shared_ptr<base::StrBuffer> m_memoryHandle;
|
||||
p_char8 m_data;
|
||||
mutable std::shared_ptr<base::StrBuffer> m_memoryHandle;
|
||||
mutable p_char8 m_data;
|
||||
v_int32 m_size;
|
||||
public:
|
||||
|
||||
@ -89,6 +89,16 @@ public:
|
||||
return m_memoryHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture data referenced by memory label to its own memory.
|
||||
*/
|
||||
void captureToOwnMemory() const {
|
||||
if(!m_memoryHandle || m_memoryHandle->getData() != m_data || m_memoryHandle->getSize() != m_size) {
|
||||
m_memoryHandle.reset(new base::StrBuffer(m_data, m_size, true));
|
||||
m_data = m_memoryHandle->getData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if labeled data equals to data specified.
|
||||
* Data is compared using &id:oatpp::base::StrBuffer::equals;.
|
||||
@ -126,6 +136,10 @@ public:
|
||||
std::string std_str() const {
|
||||
return std::string((const char*) m_data, m_size);
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return m_data != nullptr;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,109 +0,0 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "BufferInputStream.hpp"
|
||||
|
||||
namespace oatpp { namespace data{ namespace stream {
|
||||
|
||||
BufferInputStream::BufferInputStream(const std::shared_ptr<base::StrBuffer>& memoryHandle, p_char8 data, v_io_size size)
|
||||
: m_memoryHandle(memoryHandle)
|
||||
, m_data(data)
|
||||
, m_size(size)
|
||||
, m_position(0)
|
||||
, m_ioMode(IOMode::NON_BLOCKING)
|
||||
{}
|
||||
|
||||
BufferInputStream::BufferInputStream(const oatpp::String& data)
|
||||
: BufferInputStream(data.getPtr(), data->getData(), data->getSize())
|
||||
{}
|
||||
|
||||
void BufferInputStream::reset(const std::shared_ptr<base::StrBuffer>& memoryHandle, p_char8 data, v_io_size size) {
|
||||
m_memoryHandle = memoryHandle;
|
||||
m_data = data;
|
||||
m_size = size;
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
void BufferInputStream::reset() {
|
||||
m_memoryHandle = nullptr;
|
||||
m_data = nullptr;
|
||||
m_size = 0;
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
data::v_io_size BufferInputStream::read(void *data, data::v_io_size count) {
|
||||
data::v_io_size desiredAmount = count;
|
||||
if(desiredAmount > m_size - m_position) {
|
||||
desiredAmount = m_size - m_position;
|
||||
}
|
||||
std::memcpy(data, &m_data[m_position], desiredAmount);
|
||||
m_position += desiredAmount;
|
||||
return desiredAmount;
|
||||
}
|
||||
|
||||
oatpp::async::Action BufferInputStream::suggestInputStreamAction(data::v_io_size ioResult) {
|
||||
|
||||
if(ioResult > 0) {
|
||||
return oatpp::async::Action::createActionByType(oatpp::async::Action::TYPE_REPEAT);
|
||||
}
|
||||
|
||||
OATPP_LOGE("[oatpp::data::stream::BufferInputStream::suggestInputStreamAction()]", "Error. ioResult=%d", ioResult);
|
||||
|
||||
const char* message =
|
||||
"Error. BufferInputStream::suggestOutputStreamAction() method is called with (ioResult <= 0).\n"
|
||||
"Conceptual error.";
|
||||
|
||||
throw std::runtime_error(message);
|
||||
|
||||
}
|
||||
|
||||
void BufferInputStream::setInputStreamIOMode(IOMode ioMode) {
|
||||
m_ioMode = ioMode;
|
||||
}
|
||||
|
||||
IOMode BufferInputStream::getInputStreamIOMode() {
|
||||
return m_ioMode;
|
||||
}
|
||||
|
||||
std::shared_ptr<base::StrBuffer> BufferInputStream::getDataMemoryHandle() {
|
||||
return m_memoryHandle;
|
||||
}
|
||||
|
||||
p_char8 BufferInputStream::getData() {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
v_io_size BufferInputStream::getDataSize() {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
v_io_size BufferInputStream::getCurrentPosition() {
|
||||
return m_position;
|
||||
}
|
||||
|
||||
void BufferInputStream::setCurrentPosition(v_io_size position) {
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
}}}
|
238
src/oatpp/core/data/stream/BufferStream.cpp
Normal file
238
src/oatpp/core/data/stream/BufferStream.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "BufferStream.hpp"
|
||||
|
||||
namespace oatpp { namespace data{ namespace stream {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BufferOutputStream
|
||||
|
||||
BufferOutputStream::BufferOutputStream(v_io_size initialCapacity, v_io_size growBytes)
|
||||
: m_data(new v_char8[initialCapacity])
|
||||
, m_capacity(initialCapacity)
|
||||
, m_position(0)
|
||||
, m_growBytes(growBytes)
|
||||
, m_ioMode(IOMode::NON_BLOCKING)
|
||||
{}
|
||||
|
||||
BufferOutputStream::~BufferOutputStream() {
|
||||
delete [] m_data;
|
||||
}
|
||||
|
||||
data::v_io_size BufferOutputStream::write(const void *data, data::v_io_size count) {
|
||||
|
||||
reserveBytesUpfront(count);
|
||||
|
||||
std::memcpy(m_data + m_position, data, count);
|
||||
m_position += count;
|
||||
|
||||
return count;
|
||||
|
||||
}
|
||||
|
||||
void BufferOutputStream::setOutputStreamIOMode(IOMode ioMode) {
|
||||
m_ioMode = ioMode;
|
||||
}
|
||||
|
||||
IOMode BufferOutputStream::getOutputStreamIOMode() {
|
||||
return m_ioMode;
|
||||
}
|
||||
|
||||
void BufferOutputStream::reserveBytesUpfront(v_io_size count) {
|
||||
|
||||
if(m_position + count > m_capacity) {
|
||||
|
||||
if(m_growBytes <= 0) {
|
||||
throw std::runtime_error("[oatpp::data::stream::BufferOutputStream::reserveBytesUpfront()]: Error. Buffer was not allowed to grow.");
|
||||
}
|
||||
|
||||
data::v_io_size extraNeeded = m_position + count - m_capacity;
|
||||
data::v_io_size extraChunks = extraNeeded / m_growBytes;
|
||||
|
||||
if(extraChunks * m_growBytes < extraNeeded) {
|
||||
extraChunks ++;
|
||||
}
|
||||
|
||||
data::v_io_size newCapacity = m_capacity + extraChunks * m_growBytes;
|
||||
p_char8 newData = new v_char8[newCapacity];
|
||||
|
||||
std::memcpy(newData, m_data, m_position);
|
||||
delete [] m_data;
|
||||
m_data = newData;
|
||||
m_capacity = newCapacity;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
p_char8 BufferOutputStream::getData() {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
|
||||
v_io_size BufferOutputStream::getCapacity() {
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
|
||||
v_io_size BufferOutputStream::getCurrentPosition() {
|
||||
return m_position;
|
||||
}
|
||||
|
||||
|
||||
void BufferOutputStream::setCurrentPosition(v_io_size position) {
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
oatpp::String BufferOutputStream::toString() {
|
||||
return oatpp::String((const char*)m_data, m_position, true);
|
||||
}
|
||||
|
||||
oatpp::String BufferOutputStream::getSubstring(data::v_io_size pos, data::v_io_size count) {
|
||||
if(pos + count <= m_position) {
|
||||
return oatpp::String((const char *) (m_data + pos), count, true);
|
||||
} else {
|
||||
return oatpp::String((const char *) (m_data + pos), m_position - pos, true);
|
||||
}
|
||||
}
|
||||
|
||||
oatpp::data::v_io_size BufferOutputStream::flushToStream(OutputStream* stream) {
|
||||
return oatpp::data::stream::writeExactSizeData(stream, m_data, m_position);
|
||||
}
|
||||
|
||||
oatpp::async::CoroutineStarter BufferOutputStream::flushToStreamAsync(const std::shared_ptr<BufferOutputStream>& _this, const std::shared_ptr<OutputStream>& stream) {
|
||||
|
||||
class WriteDataCoroutine : public oatpp::async::Coroutine<WriteDataCoroutine> {
|
||||
private:
|
||||
std::shared_ptr<BufferOutputStream> m_this;
|
||||
std::shared_ptr<oatpp::data::stream::OutputStream> m_stream;
|
||||
AsyncInlineWriteData m_inlineData;
|
||||
public:
|
||||
|
||||
WriteDataCoroutine(const std::shared_ptr<BufferOutputStream>& _this,
|
||||
const std::shared_ptr<oatpp::data::stream::OutputStream>& stream)
|
||||
: m_this(_this)
|
||||
, m_stream(stream)
|
||||
{}
|
||||
|
||||
Action act() {
|
||||
if(m_inlineData.currBufferPtr == nullptr) {
|
||||
m_inlineData.currBufferPtr = m_this->m_data;
|
||||
m_inlineData.bytesLeft = m_this->m_position;
|
||||
}
|
||||
return writeExactSizeDataAsyncInline(m_stream.get(), m_inlineData, finish());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return WriteDataCoroutine::start(_this, stream);
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BufferInputStream
|
||||
|
||||
BufferInputStream::BufferInputStream(const std::shared_ptr<base::StrBuffer>& memoryHandle, p_char8 data, v_io_size size)
|
||||
: m_memoryHandle(memoryHandle)
|
||||
, m_data(data)
|
||||
, m_size(size)
|
||||
, m_position(0)
|
||||
, m_ioMode(IOMode::NON_BLOCKING)
|
||||
{}
|
||||
|
||||
BufferInputStream::BufferInputStream(const oatpp::String& data)
|
||||
: BufferInputStream(data.getPtr(), data->getData(), data->getSize())
|
||||
{}
|
||||
|
||||
void BufferInputStream::reset(const std::shared_ptr<base::StrBuffer>& memoryHandle, p_char8 data, v_io_size size) {
|
||||
m_memoryHandle = memoryHandle;
|
||||
m_data = data;
|
||||
m_size = size;
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
void BufferInputStream::reset() {
|
||||
m_memoryHandle = nullptr;
|
||||
m_data = nullptr;
|
||||
m_size = 0;
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
data::v_io_size BufferInputStream::read(void *data, data::v_io_size count) {
|
||||
data::v_io_size desiredAmount = count;
|
||||
if(desiredAmount > m_size - m_position) {
|
||||
desiredAmount = m_size - m_position;
|
||||
}
|
||||
std::memcpy(data, &m_data[m_position], desiredAmount);
|
||||
m_position += desiredAmount;
|
||||
return desiredAmount;
|
||||
}
|
||||
|
||||
oatpp::async::Action BufferInputStream::suggestInputStreamAction(data::v_io_size ioResult) {
|
||||
|
||||
if(ioResult > 0) {
|
||||
return oatpp::async::Action::createActionByType(oatpp::async::Action::TYPE_REPEAT);
|
||||
}
|
||||
|
||||
OATPP_LOGE("[oatpp::data::stream::BufferInputStream::suggestInputStreamAction()]", "Error. ioResult=%d", ioResult);
|
||||
|
||||
const char* message =
|
||||
"Error. BufferInputStream::suggestOutputStreamAction() method is called with (ioResult <= 0).\n"
|
||||
"Conceptual error.";
|
||||
|
||||
throw std::runtime_error(message);
|
||||
|
||||
}
|
||||
|
||||
void BufferInputStream::setInputStreamIOMode(IOMode ioMode) {
|
||||
m_ioMode = ioMode;
|
||||
}
|
||||
|
||||
IOMode BufferInputStream::getInputStreamIOMode() {
|
||||
return m_ioMode;
|
||||
}
|
||||
|
||||
std::shared_ptr<base::StrBuffer> BufferInputStream::getDataMemoryHandle() {
|
||||
return m_memoryHandle;
|
||||
}
|
||||
|
||||
p_char8 BufferInputStream::getData() {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
v_io_size BufferInputStream::getDataSize() {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
v_io_size BufferInputStream::getCurrentPosition() {
|
||||
return m_position;
|
||||
}
|
||||
|
||||
void BufferInputStream::setCurrentPosition(v_io_size position) {
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
}}}
|
@ -22,13 +22,120 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_data_stream_BufferInputStream_hpp
|
||||
#define oatpp_data_stream_BufferInputStream_hpp
|
||||
#ifndef oatpp_data_stream_BufferStream_hpp
|
||||
#define oatpp_data_stream_BufferStream_hpp
|
||||
|
||||
#include "Stream.hpp"
|
||||
|
||||
namespace oatpp { namespace data{ namespace stream {
|
||||
|
||||
/**
|
||||
* BufferOutputStream
|
||||
*/
|
||||
class BufferOutputStream : public ConsistentOutputStream {
|
||||
private:
|
||||
p_char8 m_data;
|
||||
v_io_size m_capacity;
|
||||
v_io_size m_position;
|
||||
v_io_size m_growBytes;
|
||||
IOMode m_ioMode;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param growBytes
|
||||
*/
|
||||
BufferOutputStream(v_io_size initialCapacity = 2048, v_io_size growBytes = 2048);
|
||||
|
||||
/**
|
||||
* Virtual destructor.
|
||||
*/
|
||||
~BufferOutputStream();
|
||||
|
||||
/**
|
||||
* Write `count` of bytes to stream.
|
||||
* @param data - data to write.
|
||||
* @param count - number of bytes to write.
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size write(const void *data, data::v_io_size count) override;
|
||||
|
||||
/**
|
||||
* Set stream I/O mode.
|
||||
* @throws
|
||||
*/
|
||||
void setOutputStreamIOMode(IOMode ioMode) override;
|
||||
|
||||
/**
|
||||
* Get stream I/O mode.
|
||||
* @return
|
||||
*/
|
||||
IOMode getOutputStreamIOMode() override;
|
||||
|
||||
/**
|
||||
* Reserve bytes for future writes.
|
||||
*/
|
||||
void reserveBytesUpfront(v_io_size count);
|
||||
|
||||
/**
|
||||
* Get pointer to data.
|
||||
* @return - pointer to data.
|
||||
*/
|
||||
p_char8 getData();
|
||||
|
||||
/**
|
||||
* Get current capacity.
|
||||
* Capacity may change.
|
||||
* @return
|
||||
*/
|
||||
v_io_size getCapacity();
|
||||
|
||||
/**
|
||||
* Get current data write position.
|
||||
* @return - current data write position.
|
||||
*/
|
||||
v_io_size getCurrentPosition();
|
||||
|
||||
/**
|
||||
* Set current data write position.
|
||||
* @param position - data write position.
|
||||
*/
|
||||
void setCurrentPosition(v_io_size position);
|
||||
|
||||
/**
|
||||
* Copy data to &id:oatpp::String;.
|
||||
* @return
|
||||
*/
|
||||
oatpp::String toString();
|
||||
|
||||
/**
|
||||
* Create &id:oatpp::String; from part of buffer.
|
||||
* @param pos - starting position in buffer.
|
||||
* @param count - size of bytes to write to substring.
|
||||
* @return - &id:oatpp::String;
|
||||
*/
|
||||
oatpp::String getSubstring(data::v_io_size pos, data::v_io_size count);
|
||||
|
||||
/**
|
||||
* Write all bytes from buffer to stream.
|
||||
* @param stream - stream to flush all data to.
|
||||
* @return - actual amount of bytes flushed.
|
||||
*/
|
||||
oatpp::data::v_io_size flushToStream(OutputStream* stream);
|
||||
|
||||
/**
|
||||
* Write all bytes from buffer to stream in async manner.
|
||||
* @param _this - pointer to `this` buffer.
|
||||
* @param stream - stream to flush all data to.
|
||||
* @return - &id:oatpp::async::CoroutineStarter;.
|
||||
*/
|
||||
static oatpp::async::CoroutineStarter flushToStreamAsync(const std::shared_ptr<BufferOutputStream>& _this, const std::shared_ptr<OutputStream>& stream);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* BufferInputStream
|
||||
*/
|
||||
class BufferInputStream : public InputStream {
|
||||
private:
|
||||
std::shared_ptr<base::StrBuffer> m_memoryHandle;
|
||||
@ -131,4 +238,4 @@ public:
|
||||
|
||||
}}}
|
||||
|
||||
#endif // oatpp_data_stream_BufferInputStream_hpp
|
||||
#endif // oatpp_data_stream_BufferStream_hpp
|
@ -188,10 +188,6 @@ public:
|
||||
*/
|
||||
data::v_io_size readSubstring(void *buffer, data::v_io_size pos, data::v_io_size count);
|
||||
|
||||
/**
|
||||
* Create &id:oatpp::String; from part of ChunkedBuffer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create &id:oatpp::String; from part of ChunkedBuffer.
|
||||
* @param pos - starting position in ChunkedBuffer.
|
||||
|
@ -135,7 +135,9 @@ v_int32 Caret::StateSaveGuard::getSavedErrorCode() {
|
||||
|
||||
Caret::Caret(const oatpp::String& str)
|
||||
: Caret(str->getData(), str->getSize())
|
||||
{}
|
||||
{
|
||||
m_dataMemoryHandle = str.getPtr();
|
||||
}
|
||||
|
||||
std::shared_ptr<Caret> Caret::createShared(const char* text){
|
||||
return std::make_shared<Caret>(text);
|
||||
@ -163,7 +165,11 @@ v_int32 Caret::StateSaveGuard::getSavedErrorCode() {
|
||||
v_int32 Caret::getDataSize(){
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<oatpp::base::StrBuffer> Caret::getDataMemoryHandle() {
|
||||
return m_dataMemoryHandle;
|
||||
}
|
||||
|
||||
void Caret::setPosition(v_int32 position){
|
||||
m_pos = position;
|
||||
}
|
||||
|
@ -152,6 +152,7 @@ private:
|
||||
v_int32 m_pos;
|
||||
const char* m_errorMessage;
|
||||
v_int32 m_errorCode;
|
||||
std::shared_ptr<oatpp::base::StrBuffer> m_dataMemoryHandle;
|
||||
public:
|
||||
Caret(const char* text);
|
||||
Caret(p_char8 parseData, v_int32 dataSize);
|
||||
@ -182,6 +183,12 @@ public:
|
||||
*/
|
||||
v_int32 getDataSize();
|
||||
|
||||
/**
|
||||
* Get data memoryHandle.
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr<oatpp::base::StrBuffer> getDataMemoryHandle();
|
||||
|
||||
/**
|
||||
* Set caret position relative to data
|
||||
* @param position
|
||||
|
@ -103,10 +103,10 @@ oatpp::String Url::Parser::parsePath(oatpp::parser::Caret& caret) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Url::Parser::parseQueryParamsToMap(Url::Parameters& params, oatpp::parser::Caret& caret) {
|
||||
|
||||
void Url::Parser::parseQueryParams(Url::Parameters& params, oatpp::parser::Caret& caret) {
|
||||
|
||||
if(caret.findChar('?')) {
|
||||
|
||||
|
||||
do {
|
||||
caret.inc();
|
||||
auto nameLabel = caret.putLabel();
|
||||
@ -116,60 +116,32 @@ void Url::Parser::parseQueryParamsToMap(Url::Parameters& params, oatpp::parser::
|
||||
caret.inc();
|
||||
auto valueLabel = caret.putLabel();
|
||||
caret.findChar('&');
|
||||
params[nameLabel.toString()] = valueLabel.toString();
|
||||
params.put(StringKeyLabel(caret.getDataMemoryHandle(), nameLabel.getData(), nameLabel.getSize()),
|
||||
StringKeyLabel(caret.getDataMemoryHandle(), valueLabel.getData(), valueLabel.getSize()));
|
||||
} else {
|
||||
params[nameLabel.toString()] = oatpp::String("", false);
|
||||
params.put(StringKeyLabel(caret.getDataMemoryHandle(), nameLabel.getData(), nameLabel.getSize()), "");
|
||||
}
|
||||
} while (caret.canContinueAtChar('&'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Url::Parser::parseQueryParamsToMap(Url::Parameters& params, const oatpp::String& str) {
|
||||
void Url::Parser::parseQueryParams(Url::Parameters& params, const oatpp::String& str) {
|
||||
oatpp::parser::Caret caret(str.getPtr());
|
||||
parseQueryParamsToMap(params, caret);
|
||||
parseQueryParams(params, caret);
|
||||
}
|
||||
|
||||
Url::Parameters Url::Parser::parseQueryParams(oatpp::parser::Caret& caret) {
|
||||
Url::Parameters params;
|
||||
parseQueryParamsToMap(params, caret);
|
||||
return params;
|
||||
parseQueryParams(params, caret);
|
||||
return std::move(params);
|
||||
}
|
||||
|
||||
Url::Parameters Url::Parser::parseQueryParams(const oatpp::String& str) {
|
||||
Url::Parameters params;
|
||||
parseQueryParamsToMap(params, str);
|
||||
return params;
|
||||
}
|
||||
|
||||
Url::ParametersAsLabels Url::Parser::labelQueryParams(const oatpp::String& str) {
|
||||
|
||||
Url::ParametersAsLabels params;
|
||||
oatpp::parser::Caret caret(str);
|
||||
|
||||
if(caret.findChar('?')) {
|
||||
|
||||
do {
|
||||
caret.inc();
|
||||
auto nameLabel = caret.putLabel();
|
||||
v_int32 charFound = caret.findCharFromSet("=&");
|
||||
if(charFound == '=') {
|
||||
nameLabel.end();
|
||||
caret.inc();
|
||||
auto valueLabel = caret.putLabel();
|
||||
caret.findChar('&');
|
||||
params[StringKeyLabel(str.getPtr(), nameLabel.getData(), nameLabel.getSize())] =
|
||||
StringKeyLabel(str.getPtr(), valueLabel.getData(), valueLabel.getSize());
|
||||
} else {
|
||||
params[StringKeyLabel(str.getPtr(), nameLabel.getData(), nameLabel.getSize())] = "";
|
||||
}
|
||||
} while (caret.canContinueAtChar('&'));
|
||||
|
||||
}
|
||||
|
||||
return params;
|
||||
|
||||
parseQueryParams(params, str);
|
||||
return std::move(params);
|
||||
}
|
||||
|
||||
Url Url::Parser::parseUrl(oatpp::parser::Caret& caret) {
|
||||
|
@ -25,13 +25,11 @@
|
||||
#ifndef oatpp_network_Url_hpp
|
||||
#define oatpp_network_Url_hpp
|
||||
|
||||
#include "oatpp/core/data/share/MemoryLabel.hpp"
|
||||
#include "oatpp/core/data/share/LazyStringMap.hpp"
|
||||
#include "oatpp/core/parser/Caret.hpp"
|
||||
#include "oatpp/core/collection/ListMap.hpp"
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace oatpp { namespace network {
|
||||
|
||||
|
||||
@ -48,13 +46,8 @@ public:
|
||||
/**
|
||||
* Parameters - map string to string.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::String, oatpp::String> Parameters;
|
||||
typedef oatpp::data::share::LazyStringMap<oatpp::data::share::StringKeyLabel> Parameters;
|
||||
|
||||
/**
|
||||
* Parameters as &id:oatpp::data::share::StringKeyLabel;.
|
||||
* Advantage of oatpp::data::share::StringKeyLabel - is that there is no memory allocations needed to create "Memory Label".
|
||||
*/
|
||||
typedef std::unordered_map<StringKeyLabel, StringKeyLabel> ParametersAsLabels;
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -111,13 +104,13 @@ public:
|
||||
* parse query params in form of `"?<paramName>=<paramValue>&<paramName>=<paramValue>..."` referred by ParsingCaret
|
||||
* and put that params to Parameters map
|
||||
*/
|
||||
static void parseQueryParamsToMap(Url::Parameters& params, oatpp::parser::Caret& caret);
|
||||
static void parseQueryParams(Url::Parameters& params, oatpp::parser::Caret& caret);
|
||||
|
||||
/**
|
||||
* parse query params in form of `"?<paramName>=<paramValue>&<paramName>=<paramValue>..."` referred by str
|
||||
* and put that params to Parameters map
|
||||
*/
|
||||
static void parseQueryParamsToMap(Url::Parameters& params, const oatpp::String& str);
|
||||
static void parseQueryParams(Url::Parameters& params, const oatpp::String& str);
|
||||
|
||||
/**
|
||||
* parse query params in form of `"?<paramName>=<paramValue>&<paramName>=<paramValue>..."` referred by ParsingCaret
|
||||
@ -129,14 +122,6 @@ public:
|
||||
*/
|
||||
static Url::Parameters parseQueryParams(const oatpp::String& str);
|
||||
|
||||
/**
|
||||
* Same as parseQueryParams() but use StringKeyLabel instead of a String.
|
||||
* Zero allocations. Use this method for better performance.
|
||||
* @param str
|
||||
* @return `std::unordered_map<StringKeyLabel, StringKeyLabel>`. See &l:Url::StringKeyLabel;.
|
||||
*/
|
||||
static ParametersAsLabels labelQueryParams(const oatpp::String& str);
|
||||
|
||||
/**
|
||||
* Parse Url
|
||||
* @param caret
|
||||
|
@ -118,11 +118,11 @@ oatpp::web::protocol::http::Headers ApiClient::convertParamsMap(const std::share
|
||||
auto curr = params->getFirstEntry();
|
||||
|
||||
while (curr != nullptr) {
|
||||
result[curr->getKey()] = oatpp::utils::conversion::primitiveToStr(curr->getValue());
|
||||
result.put(curr->getKey(), oatpp::utils::conversion::primitiveToStr(curr->getValue()));
|
||||
curr = curr->getNext();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
oatpp::String ApiClient::formatPath(const PathPattern& pathPattern,
|
||||
|
@ -158,6 +158,8 @@ HttpRequestExecutor::executeAsync(const String& method,
|
||||
typedef protocol::http::incoming::ResponseHeadersReader ResponseHeadersReader;
|
||||
|
||||
class ExecutorCoroutine : public oatpp::async::CoroutineWithResult<ExecutorCoroutine, const std::shared_ptr<HttpRequestExecutor::Response>&> {
|
||||
private:
|
||||
typedef oatpp::web::protocol::http::outgoing::Request OutgoingRequest;
|
||||
private:
|
||||
std::shared_ptr<oatpp::network::ClientConnectionProvider> m_connectionProvider;
|
||||
String m_method;
|
||||
@ -202,12 +204,12 @@ HttpRequestExecutor::executeAsync(const String& method,
|
||||
/* Because there is a call to it from act() in synchronous manner */
|
||||
Action onConnectionReady(const std::shared_ptr<oatpp::data::stream::IOStream>& connection) {
|
||||
m_connection = connection;
|
||||
auto request = oatpp::web::protocol::http::outgoing::Request::createShared(m_method, m_path, m_headers, m_body);
|
||||
auto request = OutgoingRequest::createShared(m_method, m_path, m_headers, m_body);
|
||||
request->putHeaderIfNotExists(Header::HOST, m_connectionProvider->getProperty("host"));
|
||||
request->putHeaderIfNotExists(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE);
|
||||
m_buffer = oatpp::data::share::MemoryLabel(oatpp::base::StrBuffer::createShared(oatpp::data::buffer::IOBuffer::BUFFER_SIZE));
|
||||
m_upstream = oatpp::data::stream::OutputStreamBufferedProxy::createShared(connection, m_buffer);
|
||||
return request->sendAsync(m_upstream).next(m_upstream->flushAsync()).next(yieldTo(&ExecutorCoroutine::readResponse));
|
||||
return OutgoingRequest::sendAsync(request, m_upstream).next(m_upstream->flushAsync()).next(yieldTo(&ExecutorCoroutine::readResponse));
|
||||
}
|
||||
|
||||
Action readResponse() {
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include "InMemoryPartReader.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferInputStream.hpp"
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
|
||||
|
@ -38,11 +38,11 @@ Multipart::Multipart(const oatpp::String& boundary)
|
||||
|
||||
Multipart::Multipart(const Headers& requestHeaders){
|
||||
|
||||
auto it = requestHeaders.find("Content-Type");
|
||||
if(it != requestHeaders.end()) {
|
||||
auto contentType = requestHeaders.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("Content-Type");
|
||||
if(contentType) {
|
||||
|
||||
oatpp::web::protocol::http::HeaderValueData valueData;
|
||||
oatpp::web::protocol::http::Parser::parseHeaderValueData(valueData, it->second, ';');
|
||||
oatpp::web::protocol::http::Parser::parseHeaderValueData(valueData, contentType, ';');
|
||||
|
||||
m_boundary = valueData.getTitleParamValue("boundary");
|
||||
|
||||
|
@ -26,16 +26,15 @@
|
||||
#define oatpp_web_mime_multipart_Multipart_hpp
|
||||
|
||||
#include "Part.hpp"
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
|
||||
namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
|
||||
/**
|
||||
* 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;.
|
||||
* For more info see &id:oatpp::data::share::LazyStringMap;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
typedef oatpp::data::share::LazyStringMap<oatpp::data::share::StringKeyLabelCI_FAST> Headers;
|
||||
|
||||
/**
|
||||
* Structure that holds parts of Multipart.
|
||||
|
@ -41,11 +41,11 @@ Part::Part(const Headers &headers,
|
||||
, m_knownSize(knownSize)
|
||||
{
|
||||
|
||||
auto it = m_headers.find("Content-Disposition");
|
||||
if(it != m_headers.end()) {
|
||||
auto contentDisposition = m_headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("Content-Disposition");
|
||||
if(contentDisposition) {
|
||||
|
||||
oatpp::web::protocol::http::HeaderValueData valueData;
|
||||
oatpp::web::protocol::http::Parser::parseHeaderValueData(valueData, it->second, ';');
|
||||
oatpp::web::protocol::http::Parser::parseHeaderValueData(valueData, contentDisposition, ';');
|
||||
|
||||
m_name = valueData.getTitleParamValue("name");
|
||||
m_filename = valueData.getTitleParamValue("filename");
|
||||
@ -86,25 +86,16 @@ const Part::Headers& Part::getHeaders() const {
|
||||
return m_headers;
|
||||
}
|
||||
|
||||
oatpp::String Part::getHeader(const oatpp::data::share::StringKeyLabelCI_FAST &headerName) const {
|
||||
auto it = m_headers.find(headerName);
|
||||
if(it != m_headers.end()) {
|
||||
return it->second.toString();
|
||||
}
|
||||
return nullptr;
|
||||
oatpp::String Part::getHeader(const oatpp::data::share::StringKeyLabelCI_FAST& headerName) const {
|
||||
return m_headers.get(headerName);
|
||||
}
|
||||
|
||||
void Part::putHeader(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) {
|
||||
m_headers[key] = value;
|
||||
m_headers.put(key, value);
|
||||
}
|
||||
|
||||
bool Part::putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) {
|
||||
auto it = m_headers.find(key);
|
||||
if(it == m_headers.end()) {
|
||||
m_headers.insert({key, value});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return m_headers.putIfNotExists(key, value);
|
||||
}
|
||||
|
||||
std::shared_ptr<data::stream::InputStream> Part::getInputStream() const {
|
||||
|
@ -25,11 +25,9 @@
|
||||
#ifndef oatpp_web_mime_multipart_Part_hpp
|
||||
#define oatpp_web_mime_multipart_Part_hpp
|
||||
|
||||
#include "oatpp/core/data/share/MemoryLabel.hpp"
|
||||
#include "oatpp/core/data/share/LazyStringMap.hpp"
|
||||
#include "oatpp/core/data/stream/Stream.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
|
||||
/**
|
||||
@ -39,9 +37,9 @@ class Part {
|
||||
public:
|
||||
/**
|
||||
* 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;.
|
||||
* For more info see &id:oatpp::data::share::LazyStringMap;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
typedef oatpp::data::share::LazyStringMap<oatpp::data::share::StringKeyLabelCI_FAST> Headers;
|
||||
private:
|
||||
oatpp::String m_name;
|
||||
oatpp::String m_filename;
|
||||
|
@ -26,7 +26,7 @@
|
||||
#define oatpp_web_mime_multipart_StatefulParser_hpp
|
||||
|
||||
#include "oatpp/core/data/stream/ChunkedBuffer.hpp"
|
||||
#include "oatpp/core/data/share/MemoryLabel.hpp"
|
||||
#include "oatpp/core/data/share/LazyStringMap.hpp"
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
@ -49,9 +49,9 @@ private:
|
||||
private:
|
||||
/**
|
||||
* 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;.
|
||||
* For more info see &id:oatpp::data::share::LazyStringMap;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
typedef oatpp::data::share::LazyStringMap<oatpp::data::share::StringKeyLabelCI_FAST> Headers;
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -60,10 +60,10 @@ public:
|
||||
class Listener {
|
||||
public:
|
||||
/**
|
||||
* Convenience 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 for headers map. Headers map key is case-insensitive.
|
||||
* For more info see &id:oatpp::data::share::LazyStringMap;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
typedef oatpp::data::share::LazyStringMap<oatpp::data::share::StringKeyLabelCI_FAST> Headers;
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -97,10 +97,10 @@ public:
|
||||
class AsyncListener {
|
||||
public:
|
||||
/**
|
||||
* Convenience 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 for headers map. Headers map key is case-insensitive.
|
||||
* For more info see &id:oatpp::data::share::LazyStringMap;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
typedef oatpp::data::share::LazyStringMap<oatpp::data::share::StringKeyLabelCI_FAST> Headers;
|
||||
public:
|
||||
|
||||
/**
|
||||
|
@ -346,7 +346,7 @@ void Parser::parseOneHeader(Headers& headers,
|
||||
caret.skipChar(' ');
|
||||
v_int32 valuePos0 = caret.getPosition();
|
||||
caret.findRN();
|
||||
headers[name] = oatpp::data::share::StringKeyLabel(headersText, &caret.getData()[valuePos0], caret.getPosition() - valuePos0);
|
||||
headers.put(name, oatpp::data::share::StringKeyLabel(headersText, &caret.getData()[valuePos0], caret.getPosition() - valuePos0));
|
||||
caret.skipRN();
|
||||
} else {
|
||||
error = Status::CODE_431;
|
||||
@ -421,8 +421,9 @@ void Parser::parseHeaderValueData(HeaderValueData& data, const oatpp::data::shar
|
||||
|
||||
void Utils::writeHeaders(const Headers& headers, data::stream::ConsistentOutputStream* stream) {
|
||||
|
||||
auto it = headers.begin();
|
||||
while(it != headers.end()) {
|
||||
auto& map = headers.getAll_Unsafe();
|
||||
auto it = map.begin();
|
||||
while(it != map.end()) {
|
||||
stream->write(it->first.getData(), it->first.getSize());
|
||||
stream->write(": ", 2);
|
||||
stream->write(it->second.getData(), it->second.getSize());
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "oatpp/web/protocol/CommunicationError.hpp"
|
||||
|
||||
#include "oatpp/core/parser/Caret.hpp"
|
||||
#include "oatpp/core/data/share/MemoryLabel.hpp"
|
||||
#include "oatpp/core/data/share/LazyStringMap.hpp"
|
||||
#include "oatpp/core/collection/ListMap.hpp"
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
@ -41,15 +41,15 @@ namespace oatpp { namespace web { namespace protocol { namespace http {
|
||||
|
||||
/**
|
||||
* 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;.
|
||||
* For more info see &id:oatpp::data::share::LazyStringMap;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
typedef oatpp::data::share::LazyStringMap<oatpp::data::share::StringKeyLabelCI_FAST> Headers;
|
||||
|
||||
/**
|
||||
* Typedef for query parameters map.
|
||||
* `std::unordered_map` of &id:oatpp::data::share::StringKeyLabel; and &id:oatpp::data::share::StringKeyLabel;.
|
||||
* For more info see &id:oatpp::data::share::LazyStringMap;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabel, oatpp::data::share::StringKeyLabel> QueryParams;
|
||||
typedef oatpp::data::share::LazyStringMap<oatpp::data::share::StringKeyLabel> QueryParams;
|
||||
|
||||
/**
|
||||
* Http status.
|
||||
@ -443,7 +443,7 @@ public:
|
||||
{}
|
||||
|
||||
/**
|
||||
* Get headers map
|
||||
* Get headers
|
||||
* @return
|
||||
*/
|
||||
const Headers& getHeaders() const {
|
||||
|
@ -61,19 +61,14 @@ const http::Headers& Request::getHeaders() const {
|
||||
|
||||
const http::QueryParams& Request::getQueryParameters() const {
|
||||
if(!m_queryParamsParsed) {
|
||||
m_queryParams = oatpp::network::Url::Parser::labelQueryParams(m_pathVariables.getTail());
|
||||
oatpp::network::Url::Parser::parseQueryParams(m_queryParams, m_pathVariables.getTail());
|
||||
m_queryParamsParsed = true;
|
||||
}
|
||||
return m_queryParams;
|
||||
}
|
||||
|
||||
oatpp::String Request::getQueryParameter(const oatpp::data::share::StringKeyLabel& name) const {
|
||||
auto iter = getQueryParameters().find(name);
|
||||
if (iter == getQueryParameters().end()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return iter->second.toString();
|
||||
}
|
||||
return getQueryParameters().get(name);
|
||||
}
|
||||
|
||||
oatpp::String Request::getQueryParameter(const oatpp::data::share::StringKeyLabel& name, const oatpp::String& defaultValue) const {
|
||||
@ -90,24 +85,15 @@ std::shared_ptr<const http::incoming::BodyDecoder> Request::getBodyDecoder() con
|
||||
}
|
||||
|
||||
void Request::putHeader(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) {
|
||||
m_headers[key] = value;
|
||||
m_headers.put(key, value);
|
||||
}
|
||||
|
||||
bool Request::putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) {
|
||||
auto it = m_headers.find(key);
|
||||
if(it == m_headers.end()) {
|
||||
m_headers.insert({key, value});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return m_headers.putIfNotExists(key, value);
|
||||
}
|
||||
|
||||
oatpp::String Request::getHeader(const oatpp::data::share::StringKeyLabelCI_FAST& headerName) const{
|
||||
auto it = m_headers.find(headerName);
|
||||
if(it != m_headers.end()) {
|
||||
return it->second.toString();
|
||||
}
|
||||
return nullptr;
|
||||
return m_headers.get(headerName);
|
||||
}
|
||||
|
||||
oatpp::String Request::getPathVariable(const oatpp::data::share::StringKeyLabel& name) const {
|
||||
|
@ -28,29 +28,27 @@
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming {
|
||||
|
||||
data::v_io_size RequestHeadersReader::readHeadersSection(data::stream::InputStreamBufferedProxy* stream,
|
||||
oatpp::data::stream::ConsistentOutputStream* bufferStream,
|
||||
Result& result) {
|
||||
data::v_io_size RequestHeadersReader::readHeadersSection(data::stream::InputStreamBufferedProxy* stream, Result& result) {
|
||||
|
||||
v_word32 accumulator = 0;
|
||||
v_int32 progress = 0;
|
||||
m_bufferStream->setCurrentPosition(0);
|
||||
data::v_io_size res;
|
||||
while (true) {
|
||||
|
||||
v_int32 desiredToRead = m_buffer.getSize();
|
||||
if(progress + desiredToRead > m_maxHeadersSize) {
|
||||
desiredToRead = m_maxHeadersSize - progress;
|
||||
v_int32 desiredToRead = m_readChunkSize;
|
||||
if(m_bufferStream->getCurrentPosition() + desiredToRead > m_maxHeadersSize) {
|
||||
desiredToRead = m_maxHeadersSize - m_bufferStream->getCurrentPosition();
|
||||
if(desiredToRead <= 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
auto bufferData = m_buffer.getData();
|
||||
m_bufferStream->reserveBytesUpfront(desiredToRead);
|
||||
auto bufferData = m_bufferStream->getData() + m_bufferStream->getCurrentPosition();
|
||||
res = stream->peek(bufferData, desiredToRead);
|
||||
if(res > 0) {
|
||||
|
||||
bufferStream->write(bufferData, res);
|
||||
progress += res;
|
||||
m_bufferStream->setCurrentPosition(m_bufferStream->getCurrentPosition() + res);
|
||||
|
||||
for(v_int32 i = 0; i < res; i ++) {
|
||||
accumulator <<= 8;
|
||||
@ -79,17 +77,15 @@ RequestHeadersReader::Result RequestHeadersReader::readHeaders(data::stream::Inp
|
||||
http::HttpError::Info& error) {
|
||||
|
||||
RequestHeadersReader::Result result;
|
||||
|
||||
oatpp::data::stream::ChunkedBuffer buffer;
|
||||
error.ioStatus = readHeadersSection(stream, &buffer, result);
|
||||
|
||||
error.ioStatus = readHeadersSection(stream, result);
|
||||
|
||||
if(error.ioStatus > 0) {
|
||||
auto headersText = buffer.toString();
|
||||
oatpp::parser::Caret caret (headersText);
|
||||
oatpp::parser::Caret caret (m_bufferStream->getData(), m_bufferStream->getCurrentPosition());
|
||||
http::Status status;
|
||||
http::Parser::parseRequestStartingLine(result.startingLine, headersText.getPtr(), caret, status);
|
||||
http::Parser::parseRequestStartingLine(result.startingLine, nullptr, caret, status);
|
||||
if(status.code == 0) {
|
||||
http::Parser::parseHeaders(result.headers, headersText.getPtr(), caret, status);
|
||||
http::Parser::parseHeaders(result.headers, nullptr, caret, status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,45 +95,42 @@ RequestHeadersReader::Result RequestHeadersReader::readHeaders(data::stream::Inp
|
||||
|
||||
|
||||
oatpp::async::CoroutineStarterForResult<const RequestHeadersReader::Result&>
|
||||
RequestHeadersReader::readHeadersAsync(const std::shared_ptr<data::stream::InputStreamBufferedProxy>& connection)
|
||||
RequestHeadersReader::readHeadersAsync(const std::shared_ptr<data::stream::InputStreamBufferedProxy>& stream)
|
||||
{
|
||||
|
||||
class ReaderCoroutine : public oatpp::async::CoroutineWithResult<ReaderCoroutine, const Result&> {
|
||||
private:
|
||||
std::shared_ptr<data::stream::InputStreamBufferedProxy> m_stream;
|
||||
oatpp::data::share::MemoryLabel m_buffer;
|
||||
v_int32 m_maxHeadersSize;
|
||||
RequestHeadersReader* m_this;
|
||||
v_word32 m_accumulator;
|
||||
v_int32 m_progress;
|
||||
RequestHeadersReader::Result m_result;
|
||||
oatpp::data::stream::ChunkedBuffer m_bufferStream;
|
||||
public:
|
||||
|
||||
ReaderCoroutine(const std::shared_ptr<data::stream::InputStreamBufferedProxy>& stream,
|
||||
const oatpp::data::share::MemoryLabel& buffer, v_int32 maxHeadersSize)
|
||||
: m_stream(stream)
|
||||
, m_buffer(buffer)
|
||||
, m_maxHeadersSize(maxHeadersSize)
|
||||
ReaderCoroutine(RequestHeadersReader* _this,
|
||||
const std::shared_ptr<data::stream::InputStreamBufferedProxy>& stream)
|
||||
: m_this(_this)
|
||||
, m_stream(stream)
|
||||
, m_accumulator(0)
|
||||
, m_progress(0)
|
||||
{}
|
||||
{
|
||||
m_this->m_bufferStream->setCurrentPosition(0);
|
||||
}
|
||||
|
||||
Action act() override {
|
||||
|
||||
v_int32 desiredToRead = m_buffer.getSize();
|
||||
if(m_progress + desiredToRead > m_maxHeadersSize) {
|
||||
desiredToRead = m_maxHeadersSize - m_progress;
|
||||
v_int32 desiredToRead = m_this->m_readChunkSize;
|
||||
if(m_this->m_bufferStream->getCurrentPosition() + desiredToRead > m_this->m_maxHeadersSize) {
|
||||
desiredToRead = m_this->m_maxHeadersSize - m_this->m_bufferStream->getCurrentPosition();
|
||||
if(desiredToRead <= 0) {
|
||||
return error<Error>("[oatpp::web::protocol::http::incoming::RequestHeadersReader::readHeadersAsync()]: Error. Headers section is too large.");
|
||||
}
|
||||
}
|
||||
|
||||
auto bufferData = m_buffer.getData();
|
||||
m_this->m_bufferStream->reserveBytesUpfront(desiredToRead);
|
||||
auto bufferData = m_this->m_bufferStream->getData() + m_this->m_bufferStream->getCurrentPosition();
|
||||
auto res = m_stream->peek(bufferData, desiredToRead);
|
||||
if(res > 0) {
|
||||
|
||||
m_bufferStream.write(bufferData, res);
|
||||
m_progress += res;
|
||||
m_this->m_bufferStream->setCurrentPosition(m_this->m_bufferStream->getCurrentPosition() + res);
|
||||
|
||||
for(v_int32 i = 0; i < res; i ++) {
|
||||
m_accumulator <<= 8;
|
||||
@ -165,13 +158,12 @@ RequestHeadersReader::readHeadersAsync(const std::shared_ptr<data::stream::Input
|
||||
}
|
||||
|
||||
Action parseHeaders() {
|
||||
|
||||
auto headersText = m_bufferStream.toString();
|
||||
oatpp::parser::Caret caret (headersText);
|
||||
|
||||
oatpp::parser::Caret caret (m_this->m_bufferStream->getData(), m_this->m_bufferStream->getCurrentPosition());
|
||||
http::Status status;
|
||||
http::Parser::parseRequestStartingLine(m_result.startingLine, headersText.getPtr(), caret, status);
|
||||
http::Parser::parseRequestStartingLine(m_result.startingLine, nullptr, caret, status);
|
||||
if(status.code == 0) {
|
||||
http::Parser::parseHeaders(m_result.headers, headersText.getPtr(), caret, status);
|
||||
http::Parser::parseHeaders(m_result.headers, nullptr, caret, status);
|
||||
if(status.code == 0) {
|
||||
return _return(m_result);
|
||||
} else {
|
||||
@ -180,12 +172,12 @@ RequestHeadersReader::readHeadersAsync(const std::shared_ptr<data::stream::Input
|
||||
} else {
|
||||
return error<Error>("[oatpp::web::protocol::http::incoming::RequestHeadersReader::readHeadersAsync()]: Error. Can't parse starting line.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return ReaderCoroutine::startForResult(connection, m_buffer, m_maxHeadersSize);
|
||||
return ReaderCoroutine::startForResult(this, stream);
|
||||
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "oatpp/web/protocol/http/Http.hpp"
|
||||
#include "oatpp/core/async/Coroutine.hpp"
|
||||
#include "oatpp/core/data/stream/StreamBufferedProxy.hpp"
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming {
|
||||
|
||||
@ -61,21 +62,23 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
data::v_io_size readHeadersSection(data::stream::InputStreamBufferedProxy* stream,
|
||||
oatpp::data::stream::ConsistentOutputStream* bufferStream,
|
||||
Result& result);
|
||||
data::v_io_size readHeadersSection(data::stream::InputStreamBufferedProxy* stream, Result& result);
|
||||
private:
|
||||
oatpp::data::share::MemoryLabel m_buffer;
|
||||
v_int32 m_readChunkSize;
|
||||
v_int32 m_maxHeadersSize;
|
||||
oatpp::data::stream::BufferOutputStream* m_bufferStream;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param buffer - buffer to use to read data from stream. &id:oatpp::data::share::MemoryLabel;.
|
||||
* @param readChunkSize
|
||||
* @param maxHeadersSize
|
||||
*/
|
||||
RequestHeadersReader(const oatpp::data::share::MemoryLabel& buffer, v_int32 maxHeadersSize)
|
||||
: m_buffer(buffer)
|
||||
RequestHeadersReader(oatpp::data::stream::BufferOutputStream* bufferStream,
|
||||
v_int32 readChunkSize = 2048,
|
||||
v_int32 maxHeadersSize = 4096)
|
||||
: m_bufferStream(bufferStream)
|
||||
, m_readChunkSize(readChunkSize)
|
||||
, m_maxHeadersSize(maxHeadersSize)
|
||||
{}
|
||||
|
||||
@ -92,7 +95,7 @@ public:
|
||||
* @param stream - `std::shared_ptr` to &id:oatpp::data::stream::InputStreamBufferedProxy;.
|
||||
* @return - &id:oatpp::async::CoroutineStarterForResult;.
|
||||
*/
|
||||
oatpp::async::CoroutineStarterForResult<const RequestHeadersReader::Result&> readHeadersAsync(const std::shared_ptr<data::stream::InputStreamBufferedProxy>& connection);
|
||||
oatpp::async::CoroutineStarterForResult<const RequestHeadersReader::Result&> readHeadersAsync(const std::shared_ptr<data::stream::InputStreamBufferedProxy>& stream);
|
||||
|
||||
};
|
||||
|
||||
|
@ -58,6 +58,10 @@ const http::Headers& Response::getHeaders() const {
|
||||
return m_headers;
|
||||
}
|
||||
|
||||
oatpp::String Response::getHeader(const oatpp::data::share::StringKeyLabelCI_FAST& headerName) const{
|
||||
return m_headers.get(headerName);
|
||||
}
|
||||
|
||||
std::shared_ptr<oatpp::data::stream::InputStream> Response::getBodyStream() const {
|
||||
return m_bodyStream;
|
||||
}
|
||||
|
@ -101,6 +101,13 @@ public:
|
||||
*/
|
||||
const http::Headers& getHeaders() const;
|
||||
|
||||
/**
|
||||
* Get header value
|
||||
* @param headerName - &id:oatpp::data::share::StringKeyLabelCI_FAST;.
|
||||
* @return - &id:oatpp::String;.
|
||||
*/
|
||||
oatpp::String getHeader(const oatpp::data::share::StringKeyLabelCI_FAST& headerName) const;
|
||||
|
||||
/**
|
||||
* Get raw body stream.
|
||||
* @return - raw body stream as &id:oatpp::data::stream::InputStream;.
|
||||
|
@ -88,38 +88,36 @@ void SimpleBodyDecoder::decode(const Headers& headers,
|
||||
oatpp::data::stream::InputStream* bodyStream,
|
||||
oatpp::data::stream::WriteCallback* writeCallback) const {
|
||||
|
||||
auto transferEncodingIt = headers.find(Header::TRANSFER_ENCODING);
|
||||
if(transferEncodingIt != headers.end() && transferEncodingIt->second == Header::Value::TRANSFER_ENCODING_CHUNKED) {
|
||||
auto transferEncoding = headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabelCI_FAST>(Header::TRANSFER_ENCODING);
|
||||
if(transferEncoding && transferEncoding == Header::Value::TRANSFER_ENCODING_CHUNKED) {
|
||||
doChunkedDecoding(bodyStream, writeCallback);
|
||||
} else {
|
||||
|
||||
oatpp::data::v_io_size contentLength = 0;
|
||||
auto contentLengthStrIt = headers.find(Header::CONTENT_LENGTH);
|
||||
auto contentLengthStr = headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>(Header::CONTENT_LENGTH);
|
||||
if(!contentLengthStr) {
|
||||
|
||||
if(contentLengthStrIt == headers.end()) {
|
||||
|
||||
auto connectionStrIt = headers.find(Header::CONNECTION);
|
||||
if(connectionStrIt != headers.end()) {
|
||||
auto headerValue = connectionStrIt->second;
|
||||
|
||||
if(headerValue.getSize() == 5 && oatpp::base::StrBuffer::equalsCI_FAST(headerValue.getData(), "close", 5)) { // read until connection is closed
|
||||
oatpp::data::buffer::IOBuffer buffer;
|
||||
oatpp::data::stream::transfer(bodyStream, writeCallback, 0 /* read until error */, buffer.getData(), buffer.getSize());
|
||||
} // else - do nothing. invalid response.
|
||||
}
|
||||
auto connectionStr = headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabelCI_FAST>(Header::CONNECTION);
|
||||
if(connectionStr && connectionStr == "close") {
|
||||
oatpp::data::buffer::IOBuffer buffer;
|
||||
oatpp::data::stream::transfer(bodyStream, writeCallback, 0 /* read until error */, buffer.getData(), buffer.getSize());
|
||||
} // else - do nothing. invalid response.
|
||||
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
bool success;
|
||||
contentLength = oatpp::utils::conversion::strToInt64(contentLengthStrIt->second.toString(), success);
|
||||
auto contentLength = oatpp::utils::conversion::strToInt64(contentLengthStr.toString(), success);
|
||||
|
||||
if(!success){
|
||||
return; // it is an invalid request/response
|
||||
}
|
||||
|
||||
if(contentLength > 0) {
|
||||
oatpp::data::buffer::IOBuffer buffer;
|
||||
oatpp::data::stream::transfer(bodyStream, writeCallback, contentLength, buffer.getData(), buffer.getSize());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,36 +223,36 @@ oatpp::async::CoroutineStarter SimpleBodyDecoder::doChunkedDecodingAsync(const s
|
||||
oatpp::async::CoroutineStarter SimpleBodyDecoder::decodeAsync(const Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<oatpp::data::stream::AsyncWriteCallback>& writeCallback) const {
|
||||
auto transferEncodingIt = headers.find(Header::TRANSFER_ENCODING);
|
||||
if(transferEncodingIt != headers.end() && transferEncodingIt->second == Header::Value::TRANSFER_ENCODING_CHUNKED) {
|
||||
auto transferEncoding = headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabelCI_FAST>(Header::TRANSFER_ENCODING);
|
||||
if(transferEncoding && transferEncoding == Header::Value::TRANSFER_ENCODING_CHUNKED) {
|
||||
return doChunkedDecodingAsync(bodyStream, writeCallback);
|
||||
} else {
|
||||
oatpp::data::v_io_size contentLength = 0;
|
||||
auto contentLengthStrIt = headers.find(Header::CONTENT_LENGTH);
|
||||
if(contentLengthStrIt == headers.end()) {
|
||||
|
||||
auto connectionStrIt = headers.find(Header::CONNECTION);
|
||||
if(connectionStrIt != headers.end()) {
|
||||
auto headerValue = connectionStrIt->second;
|
||||
auto contentLengthStr = headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>(Header::CONTENT_LENGTH);
|
||||
if(!contentLengthStr) {
|
||||
|
||||
if(headerValue.getSize() == 5 && oatpp::base::StrBuffer::equalsCI_FAST(headerValue.getData(), "close", 5)) { // read until connection is closed
|
||||
return oatpp::data::stream::transferAsync(bodyStream, writeCallback, 0 /* read until error */, oatpp::data::buffer::IOBuffer::createShared());
|
||||
}
|
||||
auto connectionStr = headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabelCI_FAST>(Header::CONNECTION);
|
||||
if(connectionStr && connectionStr == "close") {
|
||||
return oatpp::data::stream::transferAsync(bodyStream, writeCallback, 0 /* read until error */, oatpp::data::buffer::IOBuffer::createShared());
|
||||
}
|
||||
|
||||
return nullptr; // else - do nothing. invalid response.
|
||||
|
||||
} else {
|
||||
|
||||
bool success;
|
||||
contentLength = oatpp::utils::conversion::strToInt64(contentLengthStrIt->second.toString(), success);
|
||||
auto contentLength = oatpp::utils::conversion::strToInt64(contentLengthStr.toString(), success);
|
||||
|
||||
if(!success){
|
||||
throw HttpError(http::Status::CODE_400, "Invalid 'Content-Length' Header");
|
||||
}
|
||||
|
||||
if(contentLength > 0) {
|
||||
return oatpp::data::stream::transferAsync(bodyStream, writeCallback, contentLength, oatpp::data::buffer::IOBuffer::createShared());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ std::shared_ptr<BufferBody> BufferBody::createShared(const oatpp::String& buffer
|
||||
}
|
||||
|
||||
void BufferBody::declareHeaders(Headers& headers) noexcept {
|
||||
headers[oatpp::web::protocol::http::Header::CONTENT_LENGTH] = oatpp::utils::conversion::int32ToStr(m_buffer->getSize());
|
||||
headers.put(oatpp::web::protocol::http::Header::CONTENT_LENGTH, oatpp::utils::conversion::int32ToStr(m_buffer->getSize()));
|
||||
}
|
||||
|
||||
void BufferBody::writeToStream(OutputStream* stream) noexcept {
|
||||
|
@ -47,7 +47,7 @@ bool ChunkedBody::writeData(OutputStream* stream, const void* data, data::v_io_s
|
||||
}
|
||||
|
||||
void ChunkedBody::declareHeaders(Headers& headers) noexcept {
|
||||
headers[oatpp::web::protocol::http::Header::TRANSFER_ENCODING] = oatpp::web::protocol::http::Header::Value::TRANSFER_ENCODING_CHUNKED;
|
||||
headers.put(oatpp::web::protocol::http::Header::TRANSFER_ENCODING, oatpp::web::protocol::http::Header::Value::TRANSFER_ENCODING_CHUNKED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@ std::shared_ptr<ChunkedBufferBody> ChunkedBufferBody::createShared(const std::sh
|
||||
}
|
||||
|
||||
void ChunkedBufferBody::declareHeaders(Headers& headers) noexcept {
|
||||
headers[oatpp::web::protocol::http::Header::CONTENT_LENGTH] = oatpp::utils::conversion::int64ToStr(m_buffer->getSize());
|
||||
headers.put(oatpp::web::protocol::http::Header::CONTENT_LENGTH, oatpp::utils::conversion::int64ToStr(m_buffer->getSize()));
|
||||
}
|
||||
|
||||
void ChunkedBufferBody::writeToStream(OutputStream* stream) noexcept {
|
||||
|
@ -34,18 +34,18 @@ bool CommunicationUtils::headerEqualsCI_FAST(const oatpp::data::share::MemoryLab
|
||||
v_int32 CommunicationUtils::considerConnectionState(const std::shared_ptr<protocol::http::incoming::Request>& request,
|
||||
const std::shared_ptr<protocol::http::outgoing::Response>& response){
|
||||
|
||||
auto outState = response->getHeaders().find(Header::CONNECTION);
|
||||
if(outState != response->getHeaders().end() && headerEqualsCI_FAST(outState->second, Header::Value::CONNECTION_UPGRADE)) {
|
||||
auto outState = response->getHeaders().getAsMemoryLabel<oatpp::data::share::StringKeyLabelCI_FAST>(Header::CONNECTION);
|
||||
if(outState && outState == Header::Value::CONNECTION_UPGRADE) {
|
||||
return CONNECTION_STATE_UPGRADE;
|
||||
}
|
||||
|
||||
if(request) {
|
||||
/* Set keep-alive to value specified in the client's request, if no Connection header present in response. */
|
||||
/* Set keep-alive to value specified in response otherwise */
|
||||
auto it = request->getHeaders().find(Header::CONNECTION);
|
||||
if(it != request->getHeaders().end() && headerEqualsCI_FAST(it->second, Header::Value::CONNECTION_KEEP_ALIVE)) {
|
||||
if(outState != response->getHeaders().end()) {
|
||||
if(headerEqualsCI_FAST(outState->second, Header::Value::CONNECTION_KEEP_ALIVE)) {
|
||||
auto connection = request->getHeaders().getAsMemoryLabel<oatpp::data::share::StringKeyLabelCI_FAST>(Header::CONNECTION);
|
||||
if(connection && connection == Header::Value::CONNECTION_KEEP_ALIVE) {
|
||||
if(outState) {
|
||||
if(outState == Header::Value::CONNECTION_KEEP_ALIVE) {
|
||||
return CONNECTION_STATE_KEEP_ALIVE;
|
||||
} else {
|
||||
return CONNECTION_STATE_CLOSE;
|
||||
@ -60,9 +60,9 @@ v_int32 CommunicationUtils::considerConnectionState(const std::shared_ptr<protoc
|
||||
/* Set HTTP/1.1 default Connection header value (Keep-Alive), if no Connection header present in response. */
|
||||
/* Set keep-alive to value specified in response otherwise */
|
||||
auto& protocol = request->getStartingLine().protocol;
|
||||
if(protocol.getData() != nullptr && headerEqualsCI_FAST(protocol, "HTTP/1.1")) {
|
||||
if(outState != response->getHeaders().end()) {
|
||||
if(headerEqualsCI_FAST(outState->second, Header::Value::CONNECTION_KEEP_ALIVE)) {
|
||||
if(protocol && headerEqualsCI_FAST(protocol, "HTTP/1.1")) {
|
||||
if(outState) {
|
||||
if(outState == Header::Value::CONNECTION_KEEP_ALIVE) {
|
||||
return CONNECTION_STATE_KEEP_ALIVE;
|
||||
} else {
|
||||
return CONNECTION_STATE_CLOSE;
|
||||
@ -78,8 +78,8 @@ v_int32 CommunicationUtils::considerConnectionState(const std::shared_ptr<protoc
|
||||
/* If protocol != HTTP/1.1 */
|
||||
/* Set default Connection header value (Close), if no Connection header present in response. */
|
||||
/* Set keep-alive to value specified in response otherwise */
|
||||
if(outState != response->getHeaders().end()) {
|
||||
if(headerEqualsCI_FAST(outState->second, Header::Value::CONNECTION_KEEP_ALIVE)) {
|
||||
if(outState) {
|
||||
if(outState == Header::Value::CONNECTION_KEEP_ALIVE) {
|
||||
return CONNECTION_STATE_KEEP_ALIVE;
|
||||
} else {
|
||||
return CONNECTION_STATE_CLOSE;
|
||||
|
@ -43,11 +43,7 @@ void DtoBody::declareHeaders(Headers& headers) noexcept {
|
||||
m_objectMapper->write(m_buffer, m_dto);
|
||||
}
|
||||
ChunkedBufferBody::declareHeaders(headers);
|
||||
|
||||
auto it = headers.find(Header::CONTENT_TYPE);
|
||||
if(it == headers.end()) {
|
||||
headers[Header::CONTENT_TYPE] = m_objectMapper->getInfo().http_content_type;
|
||||
}
|
||||
headers.putIfNotExists(Header::CONTENT_TYPE, m_objectMapper->getInfo().http_content_type);
|
||||
}
|
||||
|
||||
data::v_io_size DtoBody::getKnownSize() {
|
||||
|
@ -306,11 +306,11 @@ MultipartBody::MultipartBody(const std::shared_ptr<Multipart>& multipart, data::
|
||||
|
||||
void MultipartBody::declareHeaders(Headers& headers) noexcept {
|
||||
if(m_multipart->getAllParts().empty()) {
|
||||
headers[oatpp::web::protocol::http::Header::CONTENT_LENGTH] = "0";
|
||||
headers.put(oatpp::web::protocol::http::Header::CONTENT_LENGTH, "0");
|
||||
return;
|
||||
}
|
||||
ChunkedBody::declareHeaders(headers);
|
||||
headers[oatpp::web::protocol::http::Header::CONTENT_TYPE] = "multipart/form-data; boundary=" + m_multipart->getBoundary();
|
||||
headers.put(oatpp::web::protocol::http::Header::CONTENT_TYPE, "multipart/form-data; boundary=" + m_multipart->getBoundary());
|
||||
}
|
||||
|
||||
void MultipartBody::writeToStream(OutputStream* stream) noexcept {
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#include "oatpp/web/mime/multipart/Multipart.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferInputStream.hpp"
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing {
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "Request.hpp"
|
||||
#include "oatpp/core/data/stream/ChunkedBuffer.hpp"
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing {
|
||||
|
||||
@ -57,16 +57,11 @@ protocol::http::Headers& Request::getHeaders() {
|
||||
}
|
||||
|
||||
void Request::putHeader(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) {
|
||||
m_headers[key] = value;
|
||||
m_headers.put(key, value);
|
||||
}
|
||||
|
||||
bool Request::putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) {
|
||||
auto it = m_headers.find(key);
|
||||
if(it == m_headers.end()) {
|
||||
m_headers.insert({key, value});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return m_headers.putIfNotExists(key, value);
|
||||
}
|
||||
|
||||
std::shared_ptr<Body> Request::getBody() {
|
||||
@ -78,85 +73,113 @@ void Request::send(data::stream::OutputStream* stream){
|
||||
if(m_body){
|
||||
m_body->declareHeaders(m_headers);
|
||||
} else {
|
||||
m_headers[Header::CONTENT_LENGTH] = "0";
|
||||
m_headers.put(Header::CONTENT_LENGTH, "0");
|
||||
}
|
||||
|
||||
stream->write(m_method.getData(), m_method.getSize());
|
||||
stream->write(" /", 2);
|
||||
stream->write(m_path.getData(), m_path.getSize());
|
||||
stream->write(" ", 1);
|
||||
stream->write("HTTP/1.1", 8);
|
||||
stream->write("\r\n", 2);
|
||||
|
||||
auto it = m_headers.begin();
|
||||
while(it != m_headers.end()){
|
||||
stream->write(it->first.getData(), it->first.getSize());
|
||||
stream->write(": ", 2);
|
||||
stream->write(it->second.getData(), it->second.getSize());
|
||||
stream->write("\r\n", 2);
|
||||
it ++;
|
||||
}
|
||||
|
||||
stream->write("\r\n", 2);
|
||||
|
||||
oatpp::data::stream::BufferOutputStream buffer;
|
||||
|
||||
buffer.write(m_method.getData(), m_method.getSize());
|
||||
buffer.write(" /", 2);
|
||||
buffer.write(m_path.getData(), m_path.getSize());
|
||||
buffer.write(" ", 1);
|
||||
buffer.write("HTTP/1.1", 8);
|
||||
buffer.write("\r\n", 2);
|
||||
|
||||
http::Utils::writeHeaders(m_headers, &buffer);
|
||||
|
||||
buffer.write("\r\n", 2);
|
||||
|
||||
if(m_body) {
|
||||
m_body->writeToStream(stream);
|
||||
|
||||
auto bodySize = m_body->getKnownSize();
|
||||
|
||||
if(bodySize >= 0 && bodySize + buffer.getCurrentPosition() < buffer.getCapacity()) {
|
||||
m_body->writeToStream(&buffer);
|
||||
buffer.flushToStream(stream);
|
||||
} else {
|
||||
buffer.flushToStream(stream);
|
||||
m_body->writeToStream(stream);
|
||||
}
|
||||
|
||||
} else {
|
||||
buffer.flushToStream(stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
oatpp::async::CoroutineStarter Request::sendAsync(const std::shared_ptr<data::stream::OutputStream>& stream){
|
||||
oatpp::async::CoroutineStarter Request::sendAsync(std::shared_ptr<Request> _this,
|
||||
const std::shared_ptr<data::stream::OutputStream>& stream)
|
||||
{
|
||||
|
||||
class SendAsyncCoroutine : public oatpp::async::Coroutine<SendAsyncCoroutine> {
|
||||
private:
|
||||
std::shared_ptr<Request> m_request;
|
||||
std::shared_ptr<Request> m_this;
|
||||
std::shared_ptr<data::stream::OutputStream> m_stream;
|
||||
std::shared_ptr<oatpp::data::stream::ChunkedBuffer> m_buffer;
|
||||
std::shared_ptr<oatpp::data::stream::BufferOutputStream> m_headersWriteBuffer;
|
||||
public:
|
||||
|
||||
SendAsyncCoroutine(const std::shared_ptr<Request>& request,
|
||||
const std::shared_ptr<data::stream::OutputStream>& stream)
|
||||
: m_request(request)
|
||||
: m_this(request)
|
||||
, m_stream(stream)
|
||||
, m_buffer(oatpp::data::stream::ChunkedBuffer::createShared())
|
||||
, m_headersWriteBuffer(std::make_shared<oatpp::data::stream::BufferOutputStream>())
|
||||
{}
|
||||
|
||||
Action act() {
|
||||
|
||||
if(m_request->m_body){
|
||||
m_request->m_body->declareHeaders(m_request->m_headers);
|
||||
if(m_this->m_body){
|
||||
m_this->m_body->declareHeaders(m_this->m_headers);
|
||||
} else {
|
||||
m_request->m_headers[Header::CONTENT_LENGTH] = "0";
|
||||
m_this->m_headers.put(Header::CONTENT_LENGTH, "0");
|
||||
}
|
||||
|
||||
m_buffer->write(m_request->m_method.getData(), m_request->m_method.getSize());
|
||||
m_buffer->write(" /", 2);
|
||||
m_buffer->write(m_request->m_path.getData(), m_request->m_path.getSize());
|
||||
m_buffer->write(" ", 1);
|
||||
m_buffer->write("HTTP/1.1", 8);
|
||||
m_buffer->write("\r\n", 2);
|
||||
m_headersWriteBuffer->write(m_this->m_method.getData(), m_this->m_method.getSize());
|
||||
m_headersWriteBuffer->write(" /", 2);
|
||||
m_headersWriteBuffer->write(m_this->m_path.getData(), m_this->m_path.getSize());
|
||||
m_headersWriteBuffer->write(" ", 1);
|
||||
m_headersWriteBuffer->write("HTTP/1.1", 8);
|
||||
m_headersWriteBuffer->write("\r\n", 2);
|
||||
|
||||
http::Utils::writeHeaders(m_request->m_headers, m_buffer.get());
|
||||
http::Utils::writeHeaders(m_this->m_headers, m_headersWriteBuffer.get());
|
||||
|
||||
m_buffer->write("\r\n", 2);
|
||||
|
||||
return yieldTo(&SendAsyncCoroutine::writeHeaders);
|
||||
m_headersWriteBuffer->write("\r\n", 2);
|
||||
|
||||
const auto& body = m_this->m_body;
|
||||
|
||||
if(body) {
|
||||
|
||||
auto bodySize = body->getKnownSize();
|
||||
|
||||
if(bodySize >= 0 && bodySize + m_headersWriteBuffer->getCurrentPosition() < m_headersWriteBuffer->getCapacity()) {
|
||||
|
||||
return body->writeToStreamAsync(m_headersWriteBuffer)
|
||||
.next(oatpp::data::stream::BufferOutputStream::flushToStreamAsync(m_headersWriteBuffer, m_stream))
|
||||
.next(finish());
|
||||
|
||||
} else {
|
||||
return yieldTo(&SendAsyncCoroutine::writeHeaders);
|
||||
}
|
||||
|
||||
} else {
|
||||
return yieldTo(&SendAsyncCoroutine::writeHeaders);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Action writeHeaders() {
|
||||
return m_buffer->flushToStreamAsync(m_stream).next(yieldTo(&SendAsyncCoroutine::writeBody));
|
||||
return oatpp::data::stream::BufferOutputStream::flushToStreamAsync(m_headersWriteBuffer, m_stream).next(yieldTo(&SendAsyncCoroutine::writeBody));
|
||||
}
|
||||
|
||||
Action writeBody() {
|
||||
if(m_request->m_body) {
|
||||
return m_request->m_body->writeToStreamAsync(m_stream).next(finish());
|
||||
if(m_this->m_body) {
|
||||
return m_this->m_body->writeToStreamAsync(m_stream).next(finish());
|
||||
}
|
||||
return finish();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return SendAsyncCoroutine::start(shared_from_this(), stream);
|
||||
return SendAsyncCoroutine::start(_this, stream);
|
||||
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace oatpp { namespace web { namespace protocol { namespace http { namespac
|
||||
/**
|
||||
* Class http::outgoing::Request AKA OutgoingRequest represents client's outgoing request to server.
|
||||
*/
|
||||
class Request : public oatpp::base::Countable, public std::enable_shared_from_this<Request> {
|
||||
class Request : public oatpp::base::Countable {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::protocol::http::Headers;.
|
||||
@ -124,10 +124,12 @@ public:
|
||||
|
||||
/**
|
||||
* Write request to stream in asynchronous manner.
|
||||
* @param _this
|
||||
* @param stream - &id:oatpp::data::stream::OutputStream;.
|
||||
* @return - &id:oatpp::async::CoroutineStarter;.
|
||||
*/
|
||||
oatpp::async::CoroutineStarter sendAsync(const std::shared_ptr<data::stream::OutputStream>& stream);
|
||||
static oatpp::async::CoroutineStarter sendAsync(std::shared_ptr<Request> _this,
|
||||
const std::shared_ptr<data::stream::OutputStream>& stream);
|
||||
|
||||
};
|
||||
|
||||
|
@ -24,8 +24,6 @@
|
||||
|
||||
#include "./Response.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/ChunkedBuffer.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing {
|
||||
|
||||
Response::Response(const Status& status,
|
||||
@ -48,24 +46,15 @@ protocol::http::Headers& Response::getHeaders() {
|
||||
}
|
||||
|
||||
void Response::putHeader(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) {
|
||||
m_headers[key] = value;
|
||||
m_headers.put(key, value);
|
||||
}
|
||||
|
||||
bool Response::putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI_FAST& key, const oatpp::data::share::StringKeyLabel& value) {
|
||||
auto it = m_headers.find(key);
|
||||
if(it == m_headers.end()) {
|
||||
m_headers.insert({key, value});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return m_headers.putIfNotExists(key, value);
|
||||
}
|
||||
|
||||
oatpp::String Response::getHeader(const oatpp::data::share::StringKeyLabelCI_FAST& headerName) const {
|
||||
auto it = m_headers.find(headerName);
|
||||
if(it != m_headers.end()) {
|
||||
return it->second.toString();
|
||||
}
|
||||
return nullptr;
|
||||
return m_headers.get(headerName);
|
||||
}
|
||||
|
||||
void Response::setConnectionUpgradeHandler(const std::shared_ptr<oatpp::network::server::ConnectionHandler>& handler) {
|
||||
@ -84,95 +73,94 @@ std::shared_ptr<const Response::ConnectionHandler::ParameterMap> Response::getCo
|
||||
return m_connectionUpgradeParameters;
|
||||
}
|
||||
|
||||
void Response::send(data::stream::OutputStream* stream) {
|
||||
|
||||
void Response::send(data::stream::OutputStream* stream, oatpp::data::stream::BufferOutputStream* headersWriteBuffer) {
|
||||
|
||||
if(m_body){
|
||||
m_body->declareHeaders(m_headers);
|
||||
} else {
|
||||
m_headers[Header::CONTENT_LENGTH] = "0";
|
||||
m_headers.put(Header::CONTENT_LENGTH, "0");
|
||||
}
|
||||
|
||||
oatpp::data::stream::ChunkedBuffer buffer;
|
||||
headersWriteBuffer->setCurrentPosition(0);
|
||||
|
||||
buffer.write("HTTP/1.1 ", 9);
|
||||
buffer.writeAsString(m_status.code);
|
||||
buffer.write(" ", 1);
|
||||
buffer.OutputStream::write(m_status.description);
|
||||
buffer.write("\r\n", 2);
|
||||
|
||||
auto it = m_headers.begin();
|
||||
while(it != m_headers.end()) {
|
||||
buffer.write(it->first.getData(), it->first.getSize());
|
||||
buffer.write(": ", 2);
|
||||
buffer.write(it->second.getData(), it->second.getSize());
|
||||
buffer.write("\r\n", 2);
|
||||
it ++;
|
||||
}
|
||||
headersWriteBuffer->write("HTTP/1.1 ", 9);
|
||||
headersWriteBuffer->writeAsString(m_status.code);
|
||||
headersWriteBuffer->write(" ", 1);
|
||||
headersWriteBuffer->OutputStream::write(m_status.description);
|
||||
headersWriteBuffer->write("\r\n", 2);
|
||||
|
||||
buffer.write("\r\n", 2);
|
||||
http::Utils::writeHeaders(m_headers, headersWriteBuffer);
|
||||
|
||||
headersWriteBuffer->write("\r\n", 2);
|
||||
|
||||
if(m_body) {
|
||||
|
||||
auto bodySize = m_body->getKnownSize();
|
||||
|
||||
if(bodySize >= 0 && bodySize + buffer.getSize() < oatpp::data::stream::ChunkedBuffer::CHUNK_ENTRY_SIZE) {
|
||||
m_body->writeToStream(&buffer);
|
||||
buffer.flushToStream(stream);
|
||||
if(bodySize >= 0 && bodySize + headersWriteBuffer->getCurrentPosition() < headersWriteBuffer->getCapacity()) {
|
||||
m_body->writeToStream(headersWriteBuffer);
|
||||
headersWriteBuffer->flushToStream(stream);
|
||||
} else {
|
||||
buffer.flushToStream(stream);
|
||||
headersWriteBuffer->flushToStream(stream);
|
||||
m_body->writeToStream(stream);
|
||||
}
|
||||
|
||||
} else {
|
||||
buffer.flushToStream(stream);
|
||||
headersWriteBuffer->flushToStream(stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
oatpp::async::CoroutineStarter Response::sendAsync(const std::shared_ptr<data::stream::OutputStream>& stream){
|
||||
oatpp::async::CoroutineStarter Response::sendAsync(const std::shared_ptr<Response>& _this,
|
||||
const std::shared_ptr<data::stream::OutputStream>& stream,
|
||||
const std::shared_ptr<oatpp::data::stream::BufferOutputStream>& headersWriteBuffer)
|
||||
{
|
||||
|
||||
class SendAsyncCoroutine : public oatpp::async::Coroutine<SendAsyncCoroutine> {
|
||||
private:
|
||||
std::shared_ptr<Response> m_response;
|
||||
std::shared_ptr<Response> m_this;
|
||||
std::shared_ptr<data::stream::OutputStream> m_stream;
|
||||
std::shared_ptr<oatpp::data::stream::ChunkedBuffer> m_buffer;
|
||||
std::shared_ptr<oatpp::data::stream::BufferOutputStream> m_headersWriteBuffer;
|
||||
public:
|
||||
|
||||
SendAsyncCoroutine(const std::shared_ptr<Response>& response,
|
||||
const std::shared_ptr<data::stream::OutputStream>& stream)
|
||||
: m_response(response)
|
||||
SendAsyncCoroutine(const std::shared_ptr<Response>& _this,
|
||||
const std::shared_ptr<data::stream::OutputStream>& stream,
|
||||
const std::shared_ptr<oatpp::data::stream::BufferOutputStream>& headersWriteBuffer)
|
||||
: m_this(_this)
|
||||
, m_stream(stream)
|
||||
, m_buffer(oatpp::data::stream::ChunkedBuffer::createShared())
|
||||
, m_headersWriteBuffer(headersWriteBuffer)
|
||||
{}
|
||||
|
||||
Action act() override {
|
||||
|
||||
if(m_response->m_body){
|
||||
m_response->m_body->declareHeaders(m_response->m_headers);
|
||||
if(m_this->m_body){
|
||||
m_this->m_body->declareHeaders(m_this->m_headers);
|
||||
} else {
|
||||
m_response->m_headers[Header::CONTENT_LENGTH] = "0";
|
||||
m_this->m_headers.put(Header::CONTENT_LENGTH, "0");
|
||||
}
|
||||
|
||||
m_buffer->write("HTTP/1.1 ", 9);
|
||||
m_buffer->writeAsString(m_response->m_status.code);
|
||||
m_buffer->write(" ", 1);
|
||||
m_buffer->OutputStream::write(m_response->m_status.description);
|
||||
m_buffer->write("\r\n", 2);
|
||||
|
||||
http::Utils::writeHeaders(m_response->m_headers, m_buffer.get());
|
||||
|
||||
m_buffer->write("\r\n", 2);
|
||||
m_headersWriteBuffer->setCurrentPosition(0);
|
||||
|
||||
const auto& body = m_response->m_body;
|
||||
m_headersWriteBuffer->write("HTTP/1.1 ", 9);
|
||||
m_headersWriteBuffer->writeAsString(m_this->m_status.code);
|
||||
m_headersWriteBuffer->write(" ", 1);
|
||||
m_headersWriteBuffer->OutputStream::write(m_this->m_status.description);
|
||||
m_headersWriteBuffer->write("\r\n", 2);
|
||||
|
||||
http::Utils::writeHeaders(m_this->m_headers, m_headersWriteBuffer.get());
|
||||
|
||||
m_headersWriteBuffer->write("\r\n", 2);
|
||||
|
||||
const auto& body = m_this->m_body;
|
||||
|
||||
if(body) {
|
||||
|
||||
auto bodySize = body->getKnownSize();
|
||||
|
||||
if(bodySize >= 0 && bodySize + m_buffer->getSize() < oatpp::data::stream::ChunkedBuffer::CHUNK_ENTRY_SIZE) {
|
||||
if(bodySize >= 0 && bodySize + m_headersWriteBuffer->getCurrentPosition() < m_headersWriteBuffer->getCapacity()) {
|
||||
|
||||
return body->writeToStreamAsync(m_buffer)
|
||||
.next(m_buffer->flushToStreamAsync(m_stream))
|
||||
return body->writeToStreamAsync(m_headersWriteBuffer)
|
||||
.next(oatpp::data::stream::BufferOutputStream::flushToStreamAsync(m_headersWriteBuffer, m_stream))
|
||||
.next(finish());
|
||||
|
||||
} else {
|
||||
@ -186,19 +174,19 @@ oatpp::async::CoroutineStarter Response::sendAsync(const std::shared_ptr<data::s
|
||||
}
|
||||
|
||||
Action writeHeaders() {
|
||||
return m_buffer->flushToStreamAsync(m_stream).next(yieldTo(&SendAsyncCoroutine::writeBody));
|
||||
return oatpp::data::stream::BufferOutputStream::flushToStreamAsync(m_headersWriteBuffer, m_stream).next(yieldTo(&SendAsyncCoroutine::writeBody));
|
||||
}
|
||||
|
||||
Action writeBody() {
|
||||
if(m_response->m_body) {
|
||||
return m_response->m_body->writeToStreamAsync(m_stream).next(finish());
|
||||
if(m_this->m_body) {
|
||||
return m_this->m_body->writeToStreamAsync(m_stream).next(finish());
|
||||
}
|
||||
return finish();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return SendAsyncCoroutine::start(shared_from_this(), stream);
|
||||
return SendAsyncCoroutine::start(_this, stream, headersWriteBuffer);
|
||||
|
||||
}
|
||||
|
||||
|
@ -29,13 +29,14 @@
|
||||
#include "oatpp/web/protocol/http/Http.hpp"
|
||||
#include "oatpp/network/server/ConnectionHandler.hpp"
|
||||
#include "oatpp/core/async/Coroutine.hpp"
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing {
|
||||
|
||||
/**
|
||||
* Class which stores information of outgoing http Response.
|
||||
*/
|
||||
class Response : public oatpp::base::Countable, public std::enable_shared_from_this<Response> {
|
||||
class Response : public oatpp::base::Countable {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for Headers. <br>
|
||||
@ -137,15 +138,20 @@ public:
|
||||
/**
|
||||
* Write this Response to stream.
|
||||
* @param stream - pointer to &id:oatpp::data::stream::OutputStream;.
|
||||
* @param headersWriteBuffer - pointer to &id:oatpp::data::stream::BufferOutputStream;.
|
||||
*/
|
||||
void send(data::stream::OutputStream* stream);
|
||||
void send(data::stream::OutputStream* stream, oatpp::data::stream::BufferOutputStream* headersWriteBuffer);
|
||||
|
||||
/**
|
||||
* Same as &l:Response::send (); but async.
|
||||
* @param _this - `this` response.
|
||||
* @param stream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;.
|
||||
* @param headersWriteBuffer - `std::shared_ptr` to &id:oatpp::data::stream::BufferOutputStream;.
|
||||
* @return - &id:oatpp::async::CoroutineStarter;.
|
||||
*/
|
||||
oatpp::async::CoroutineStarter sendAsync(const std::shared_ptr<data::stream::OutputStream>& stream);
|
||||
static oatpp::async::CoroutineStarter sendAsync(const std::shared_ptr<Response>& _this,
|
||||
const std::shared_ptr<data::stream::OutputStream>& stream,
|
||||
const std::shared_ptr<oatpp::data::stream::BufferOutputStream>& headersWriteBuffer);
|
||||
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,12 @@
|
||||
|
||||
#include "oatpp/core/concurrency/Thread.hpp"
|
||||
|
||||
#include "oatpp/core/data/buffer/IOBuffer.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
#include "oatpp/core/data/stream/StreamBufferedProxy.hpp"
|
||||
|
||||
|
||||
namespace oatpp { namespace web { namespace server {
|
||||
|
||||
HttpConnectionHandler::Task::Task(HttpRouter* router,
|
||||
@ -66,12 +72,16 @@ void HttpConnectionHandler::Task::run(){
|
||||
v_int32 connectionState = oatpp::web::protocol::http::outgoing::CommunicationUtils::CONNECTION_STATE_CLOSE;
|
||||
std::shared_ptr<oatpp::web::protocol::http::outgoing::Response> response;
|
||||
|
||||
oatpp::data::stream::BufferOutputStream headersInBuffer(2048 /* initial capacity */, 2048 /* grow bytes */);
|
||||
oatpp::data::stream::BufferOutputStream headersOutBuffer(2048 /* initial capacity */, 2048 /* grow bytes */);
|
||||
oatpp::web::protocol::http::incoming::RequestHeadersReader headersReader(&headersInBuffer, 2048 /* read chunk size */, 4096 /* max headers size */);
|
||||
|
||||
do {
|
||||
|
||||
response = HttpProcessor::processRequest(m_router, inStream, m_bodyDecoder, m_errorHandler, m_requestInterceptors, connectionState);
|
||||
response = HttpProcessor::processRequest(m_router, headersReader, inStream, m_bodyDecoder, m_errorHandler, m_requestInterceptors, connectionState);
|
||||
|
||||
if(response) {
|
||||
response->send(m_connection.get());
|
||||
response->send(m_connection.get(), &headersOutBuffer);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -34,9 +34,6 @@
|
||||
#include "oatpp/network/server/ConnectionHandler.hpp"
|
||||
#include "oatpp/network/Connection.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/StreamBufferedProxy.hpp"
|
||||
#include "oatpp/core/data/buffer/IOBuffer.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace server {
|
||||
|
||||
/**
|
||||
|
@ -28,6 +28,7 @@ namespace oatpp { namespace web { namespace server {
|
||||
|
||||
std::shared_ptr<protocol::http::outgoing::Response>
|
||||
HttpProcessor::processRequest(HttpRouter* router,
|
||||
RequestHeadersReader& headersReader,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStreamBufferedProxy>& inStream,
|
||||
const std::shared_ptr<const oatpp::web::protocol::http::incoming::BodyDecoder>& bodyDecoder,
|
||||
const std::shared_ptr<handler::ErrorHandler>& errorHandler,
|
||||
@ -35,16 +36,9 @@ HttpProcessor::processRequest(HttpRouter* router,
|
||||
v_int32& connectionState) {
|
||||
|
||||
|
||||
RequestHeadersReader::Result headersReadResult;
|
||||
oatpp::web::protocol::http::HttpError::Info error;
|
||||
|
||||
{
|
||||
const v_int32 bufferSize = 2048;
|
||||
v_char8 buffer [bufferSize];
|
||||
oatpp::data::share::MemoryLabel bufferLabel(nullptr, buffer, bufferSize);
|
||||
RequestHeadersReader headersReader(bufferLabel, 4096);
|
||||
headersReadResult = headersReader.readHeaders(inStream.get(), error);
|
||||
}
|
||||
oatpp::web::protocol::http::HttpError::Info error;
|
||||
auto headersReadResult = headersReader.readHeaders(inStream.get(), error);
|
||||
|
||||
if(error.status.code != 0) {
|
||||
connectionState = oatpp::web::protocol::http::outgoing::CommunicationUtils::CONNECTION_STATE_CLOSE;
|
||||
@ -130,8 +124,7 @@ oatpp::async::Action HttpProcessor::Coroutine::onHeadersParsed(const RequestHead
|
||||
}
|
||||
|
||||
HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::act() {
|
||||
RequestHeadersReader headersReader(m_headerReaderBuffer, 4096);
|
||||
return headersReader.readHeadersAsync(m_inStream).callbackTo(&HttpProcessor::Coroutine::onHeadersParsed);
|
||||
return m_headersReader.readHeadersAsync(m_inStream).callbackTo(&HttpProcessor::Coroutine::onHeadersParsed);
|
||||
}
|
||||
|
||||
HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::onRequestFormed() {
|
||||
@ -147,7 +140,8 @@ HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::onResponseFormed() {
|
||||
|
||||
m_currentResponse->putHeaderIfNotExists(protocol::http::Header::SERVER, protocol::http::Header::Value::SERVER);
|
||||
m_connectionState = oatpp::web::protocol::http::outgoing::CommunicationUtils::considerConnectionState(m_currentRequest, m_currentResponse);
|
||||
return m_currentResponse->sendAsync(m_connection).next(yieldTo(&HttpProcessor::Coroutine::onRequestDone));
|
||||
return protocol::http::outgoing::Response::sendAsync(m_currentResponse, m_connection, m_headersOutBuffer)
|
||||
.next(yieldTo(&HttpProcessor::Coroutine::onRequestDone));
|
||||
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,9 @@ public:
|
||||
class Coroutine : public oatpp::async::Coroutine<HttpProcessor::Coroutine> {
|
||||
private:
|
||||
HttpRouter* m_router;
|
||||
oatpp::data::stream::BufferOutputStream m_headersInBuffer;
|
||||
RequestHeadersReader m_headersReader;
|
||||
std::shared_ptr<oatpp::data::stream::BufferOutputStream> m_headersOutBuffer;
|
||||
std::shared_ptr<const oatpp::web::protocol::http::incoming::BodyDecoder> m_bodyDecoder;
|
||||
std::shared_ptr<handler::ErrorHandler> m_errorHandler;
|
||||
RequestInterceptors* m_requestInterceptors;
|
||||
@ -74,7 +77,6 @@ public:
|
||||
std::shared_ptr<oatpp::data::stream::InputStreamBufferedProxy> m_inStream;
|
||||
v_int32 m_connectionState;
|
||||
private:
|
||||
oatpp::data::share::MemoryLabel m_headerReaderBuffer;
|
||||
oatpp::web::server::HttpRouter::BranchRouter::Route m_currentRoute;
|
||||
std::shared_ptr<protocol::http::incoming::Request> m_currentRequest;
|
||||
std::shared_ptr<protocol::http::outgoing::Response> m_currentResponse;
|
||||
@ -87,13 +89,15 @@ public:
|
||||
const std::shared_ptr<oatpp::data::stream::IOStream>& connection,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStreamBufferedProxy>& inStream)
|
||||
: m_router(router)
|
||||
, m_headersInBuffer(2048 /* initialCapacity */, 2048 /* growBytes */)
|
||||
, m_headersReader(&m_headersInBuffer, 2048 /* read chunk size */, 4096 /* max headers size */)
|
||||
, m_headersOutBuffer(std::make_shared<oatpp::data::stream::BufferOutputStream>(2048 /* initialCapacity */, 2048 /* growBytes */))
|
||||
, m_bodyDecoder(bodyDecoder)
|
||||
, m_errorHandler(errorHandler)
|
||||
, m_requestInterceptors(requestInterceptors)
|
||||
, m_connection(connection)
|
||||
, m_inStream(inStream)
|
||||
, m_connectionState(oatpp::web::protocol::http::outgoing::CommunicationUtils::CONNECTION_STATE_KEEP_ALIVE)
|
||||
, m_headerReaderBuffer(oatpp::base::StrBuffer::createShared(2048))
|
||||
{}
|
||||
|
||||
Action act() override;
|
||||
@ -113,6 +117,7 @@ public:
|
||||
|
||||
static std::shared_ptr<protocol::http::outgoing::Response>
|
||||
processRequest(HttpRouter* router,
|
||||
RequestHeadersReader& headersReader,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStreamBufferedProxy>& inStream,
|
||||
const std::shared_ptr<const oatpp::web::protocol::http::incoming::BodyDecoder>& bodyDecoder,
|
||||
const std::shared_ptr<handler::ErrorHandler>& errorHandler,
|
||||
|
@ -42,7 +42,7 @@ void AuthorizationHandler::renderAuthenticateHeaderValue(ChunkedBuffer& stream)
|
||||
void AuthorizationHandler::addErrorResponseHeaders(Headers& headers) {
|
||||
ChunkedBuffer stream;
|
||||
renderAuthenticateHeaderValue(stream);
|
||||
headers[protocol::http::Header::WWW_AUTHENTICATE] = stream.toString();
|
||||
headers.put(protocol::http::Header::WWW_AUTHENTICATE, stream.toString());
|
||||
}
|
||||
|
||||
oatpp::String AuthorizationHandler::getScheme() {
|
||||
|
@ -48,7 +48,7 @@ DefaultErrorHandler::handleError(const oatpp::web::protocol::http::Status &statu
|
||||
response->putHeader(protocol::http::Header::SERVER, protocol::http::Header::Value::SERVER);
|
||||
response->putHeader(protocol::http::Header::CONNECTION, protocol::http::Header::Value::CONNECTION_CLOSE);
|
||||
|
||||
for(auto& pair : headers) {
|
||||
for(const auto& pair : headers.getAll_Unsafe()) {
|
||||
response->putHeader(pair.first, pair.second);
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,12 @@ add_executable(oatppAllTests
|
||||
oatpp/core/base/memory/PerfTest.hpp
|
||||
oatpp/core/data/mapping/type/TypeTest.cpp
|
||||
oatpp/core/data/mapping/type/TypeTest.hpp
|
||||
oatpp/core/data/share/LazyStringMapTest.cpp
|
||||
oatpp/core/data/share/LazyStringMapTest.hpp
|
||||
oatpp/core/data/share/MemoryLabelTest.cpp
|
||||
oatpp/core/data/share/MemoryLabelTest.hpp
|
||||
oatpp/core/data/stream/BufferStreamTest.cpp
|
||||
oatpp/core/data/stream/BufferStreamTest.hpp
|
||||
oatpp/core/data/stream/ChunkedBufferTest.cpp
|
||||
oatpp/core/data/stream/ChunkedBufferTest.hpp
|
||||
oatpp/core/parser/CaretTest.cpp
|
||||
|
@ -16,7 +16,9 @@
|
||||
#include "oatpp/network/virtual_/InterfaceTest.hpp"
|
||||
#include "oatpp/network/UrlTest.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferStreamTest.hpp"
|
||||
#include "oatpp/core/data/stream/ChunkedBufferTest.hpp"
|
||||
#include "oatpp/core/data/share/LazyStringMapTest.hpp"
|
||||
#include "oatpp/core/data/share/MemoryLabelTest.hpp"
|
||||
|
||||
#include "oatpp/core/base/StrBufferTest.hpp"
|
||||
@ -68,7 +70,12 @@ void runTests() {
|
||||
OATPP_RUN_TEST(oatpp::test::collection::LinkedListTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::share::MemoryLabelTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::share::LazyStringMapTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::stream::ChunkedBufferTest);
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::stream::BufferStreamTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::TypeTest);
|
||||
|
||||
OATPP_RUN_TEST(oatpp::test::async::LockTest);
|
||||
|
171
test/oatpp/core/data/share/LazyStringMapTest.cpp
Normal file
171
test/oatpp/core/data/share/LazyStringMapTest.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "LazyStringMapTest.hpp"
|
||||
|
||||
#include "oatpp/core/data/share/LazyStringMap.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace core { namespace data { namespace share {
|
||||
|
||||
namespace {
|
||||
|
||||
typedef oatpp::data::share::StringKeyLabel StringKeyLabel;
|
||||
typedef oatpp::data::share::StringKeyLabelCI StringKeyLabelCI;
|
||||
|
||||
template<class T>
|
||||
using LazyStringMap = oatpp::data::share::LazyStringMap<T>;
|
||||
|
||||
}
|
||||
|
||||
void LazyStringMapTest::onRun() {
|
||||
|
||||
p_char8 text = (p_char8) "Hello World!";
|
||||
|
||||
{
|
||||
|
||||
LazyStringMap<StringKeyLabel> map;
|
||||
|
||||
map.put("key1", StringKeyLabel(nullptr, text, 5));
|
||||
map.put("key2", StringKeyLabel(nullptr, text + 6, 6));
|
||||
|
||||
oatpp::String s1 = map.get("key1");
|
||||
oatpp::String s2 = map.get("key2");
|
||||
|
||||
OATPP_ASSERT(s1 == "Hello");
|
||||
OATPP_ASSERT(s2 == "World!");
|
||||
|
||||
oatpp::String s12 = map.get("key1");
|
||||
oatpp::String s22 = map.get("key2");
|
||||
|
||||
OATPP_ASSERT(s1.get() == s12.get());
|
||||
OATPP_ASSERT(s2.get() == s22.get());
|
||||
|
||||
OATPP_ASSERT(map.get("KEY1") == nullptr);
|
||||
OATPP_ASSERT(map.get("KEY2") == nullptr);
|
||||
|
||||
auto all = map.getAll();
|
||||
|
||||
auto s13 = all["key1"];
|
||||
auto s23 = all["key2"];
|
||||
|
||||
OATPP_ASSERT(s13.getData() == s1->getData() && s13.getSize() == s1->getSize());
|
||||
OATPP_ASSERT(s23.getData() == s2->getData() && s23.getSize() == s2->getSize());
|
||||
OATPP_ASSERT(s1.get() == s13.getMemoryHandle().get());
|
||||
OATPP_ASSERT(s2.get() == s23.getMemoryHandle().get());
|
||||
|
||||
OATPP_ASSERT(map.getSize() == 2);
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
LazyStringMap<StringKeyLabelCI> map;
|
||||
|
||||
map.put("key1", StringKeyLabel(nullptr, text, 5));
|
||||
map.put("key2", StringKeyLabel(nullptr, text + 6, 6));
|
||||
|
||||
auto s01 = map.getAsMemoryLabel_Unsafe<StringKeyLabel>("key1");
|
||||
auto s02 = map.getAsMemoryLabel_Unsafe<StringKeyLabel>("key2");
|
||||
|
||||
OATPP_ASSERT(s01 == "Hello");
|
||||
OATPP_ASSERT(s02 == "World!");
|
||||
|
||||
OATPP_ASSERT(s01.getMemoryHandle() == nullptr);
|
||||
OATPP_ASSERT(s02.getMemoryHandle() == nullptr);
|
||||
|
||||
auto s1 = map.getAsMemoryLabel<StringKeyLabel>("key1");
|
||||
auto s2 = map.getAsMemoryLabel<StringKeyLabel>("key2");
|
||||
|
||||
OATPP_ASSERT(s1 == "Hello");
|
||||
OATPP_ASSERT(s2 == "World!");
|
||||
|
||||
oatpp::String s12 = map.get("key1");
|
||||
oatpp::String s22 = map.get("key2");
|
||||
|
||||
OATPP_ASSERT(s1.getMemoryHandle().get() == s12.get());
|
||||
OATPP_ASSERT(s2.getMemoryHandle().get() == s22.get());
|
||||
|
||||
OATPP_ASSERT(map.getAsMemoryLabel<StringKeyLabel>("KEY1") == s1);
|
||||
OATPP_ASSERT(map.getAsMemoryLabel<StringKeyLabel>("KEY2") == s2);
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
LazyStringMap<StringKeyLabelCI> map1;
|
||||
LazyStringMap<StringKeyLabelCI> map2;
|
||||
|
||||
map1.put("key1", StringKeyLabel(nullptr, text, 5));
|
||||
map1.put("key2", StringKeyLabel(nullptr, text + 6, 6));
|
||||
|
||||
OATPP_ASSERT(map1.getSize() == 2);
|
||||
OATPP_ASSERT(map2.getSize() == 0);
|
||||
|
||||
map2 = std::move(map1);
|
||||
|
||||
OATPP_ASSERT(map1.getSize() == 0);
|
||||
OATPP_ASSERT(map2.getSize() == 2);
|
||||
|
||||
{
|
||||
|
||||
auto all = map2.getAll_Unsafe();
|
||||
|
||||
auto s1 = all["key1"];
|
||||
auto s2 = all["key2"];
|
||||
|
||||
OATPP_ASSERT(s1.getMemoryHandle() == nullptr);
|
||||
OATPP_ASSERT(s2.getMemoryHandle() == nullptr);
|
||||
|
||||
OATPP_ASSERT(s1 == "Hello");
|
||||
OATPP_ASSERT(s2 == "World!");
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
auto all = map2.getAll();
|
||||
|
||||
auto s1 = all["key1"];
|
||||
auto s2 = all["key2"];
|
||||
|
||||
OATPP_ASSERT(s1.getMemoryHandle());
|
||||
OATPP_ASSERT(s2.getMemoryHandle());
|
||||
|
||||
OATPP_ASSERT(s1 == "Hello");
|
||||
OATPP_ASSERT(s2 == "World!");
|
||||
|
||||
auto s12 = map2.get("key1");
|
||||
auto s22 = map2.get("key2");
|
||||
|
||||
OATPP_ASSERT(s1.getMemoryHandle().get() == s12.get());
|
||||
OATPP_ASSERT(s2.getMemoryHandle().get() == s22.get());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}}}}}
|
42
test/oatpp/core/data/share/LazyStringMapTest.hpp
Normal file
42
test/oatpp/core/data/share/LazyStringMapTest.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_test_core_data_share_LazyStringMapTest_hpp
|
||||
#define oatpp_test_core_data_share_LazyStringMapTest_hpp
|
||||
|
||||
#include "oatpp-test/UnitTest.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace core { namespace data { namespace share {
|
||||
|
||||
class LazyStringMapTest : public UnitTest{
|
||||
public:
|
||||
|
||||
LazyStringMapTest():UnitTest("TEST[core::data::share::LazyStringMapTest]"){}
|
||||
void onRun() override;
|
||||
|
||||
};
|
||||
|
||||
}}}}}
|
||||
|
||||
#endif // oatpp_test_core_data_share_LazyStringMapTest_hpp
|
@ -127,30 +127,30 @@ void MemoryLabelTest::onRun() {
|
||||
oatpp::web::protocol::http::Parser::parseHeaders(headers, headersText.getPtr(), caret, status);
|
||||
|
||||
OATPP_ASSERT(status.code == 0);
|
||||
OATPP_ASSERT(headers.size() == 10);
|
||||
OATPP_ASSERT(headers.getSize() == 10);
|
||||
|
||||
|
||||
OATPP_ASSERT(headers["header0"].equals("value0", 6));
|
||||
OATPP_ASSERT(headers["header1"].equals("value1", 6));
|
||||
OATPP_ASSERT(headers["header2"].equals("value2", 6));
|
||||
OATPP_ASSERT(headers["header3"].equals("value3", 6));
|
||||
OATPP_ASSERT(headers["header4"].equals("value4", 6));
|
||||
OATPP_ASSERT(headers["header5"].equals("value5", 6));
|
||||
OATPP_ASSERT(headers["header6"].equals("value6", 6));
|
||||
OATPP_ASSERT(headers["header7"].equals("value7", 6));
|
||||
OATPP_ASSERT(headers["header8"].equals("value8", 6));
|
||||
OATPP_ASSERT(headers["header9"].equals("value9", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header0").equals("value0", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header1").equals("value1", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header2").equals("value2", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header3").equals("value3", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header4").equals("value4", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header5").equals("value5", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header6").equals("value6", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header7").equals("value7", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header8").equals("value8", 6));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header9").equals("value9", 6));
|
||||
|
||||
OATPP_ASSERT(headers["header0"].equals("value0"));
|
||||
OATPP_ASSERT(headers["header1"].equals("value1"));
|
||||
OATPP_ASSERT(headers["header2"].equals("value2"));
|
||||
OATPP_ASSERT(headers["header3"].equals("value3"));
|
||||
OATPP_ASSERT(headers["header4"].equals("value4"));
|
||||
OATPP_ASSERT(headers["header5"].equals("value5"));
|
||||
OATPP_ASSERT(headers["header6"].equals("value6"));
|
||||
OATPP_ASSERT(headers["header7"].equals("value7"));
|
||||
OATPP_ASSERT(headers["header8"].equals("value8"));
|
||||
OATPP_ASSERT(headers["header9"].equals("value9"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header0").equals("value0"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header1").equals("value1"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header2").equals("value2"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header3").equals("value3"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header4").equals("value4"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header5").equals("value5"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header6").equals("value6"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header7").equals("value7"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header8").equals("value8"));
|
||||
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header9").equals("value9"));
|
||||
|
||||
}
|
||||
|
||||
|
152
test/oatpp/core/data/stream/BufferStreamTest.cpp
Normal file
152
test/oatpp/core/data/stream/BufferStreamTest.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "BufferStreamTest.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
#include "oatpp/core/utils/ConversionUtils.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace core { namespace data { namespace stream {
|
||||
|
||||
void BufferStreamTest::onRun() {
|
||||
|
||||
typedef oatpp::data::stream::BufferOutputStream BufferOutputStream;
|
||||
|
||||
{
|
||||
BufferOutputStream stream;
|
||||
|
||||
stream << "int=" << 1 << ", float=" << 1.1 << ", "
|
||||
<< "bool=" << true << " or " << false;
|
||||
|
||||
OATPP_LOGV(TAG, "str='%s'", stream.toString()->c_str());
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << 101;
|
||||
OATPP_ASSERT(stream.toString() == oatpp::utils::conversion::int32ToStr(101));
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << (v_float32)101.1;
|
||||
OATPP_ASSERT(stream.toString() == oatpp::utils::conversion::float32ToStr(101.1));
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << (v_float64)101.1;
|
||||
OATPP_ASSERT(stream.toString() == oatpp::utils::conversion::float64ToStr(101.1));
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << true;
|
||||
OATPP_ASSERT(stream.toString() == "true");
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << false;
|
||||
OATPP_ASSERT(stream.toString() == "false");
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << oatpp::String("oat++");
|
||||
OATPP_ASSERT(stream.toString() == "oat++");
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << oatpp::Int8(8);
|
||||
OATPP_ASSERT(stream.toString() == oatpp::utils::conversion::int32ToStr(8));
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << oatpp::Int16(16);
|
||||
OATPP_ASSERT(stream.toString() == oatpp::utils::conversion::int32ToStr(16));
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << oatpp::Int32(32);
|
||||
OATPP_ASSERT(stream.toString() == oatpp::utils::conversion::int32ToStr(32));
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << oatpp::Int64(64);
|
||||
OATPP_ASSERT(stream.toString() == oatpp::utils::conversion::int32ToStr(64));
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << oatpp::Float32(0.32);
|
||||
OATPP_ASSERT(stream.toString() == oatpp::utils::conversion::float32ToStr(0.32));
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << oatpp::Float64(0.64);
|
||||
OATPP_ASSERT(stream.toString() == oatpp::utils::conversion::float64ToStr(0.64));
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << oatpp::Boolean(true);
|
||||
OATPP_ASSERT(stream.toString() == "true");
|
||||
|
||||
stream.setCurrentPosition(0);
|
||||
stream << oatpp::Boolean(false);
|
||||
OATPP_ASSERT(stream.toString() == "false");
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
BufferOutputStream stream;
|
||||
v_int32 fragmentsCount = 1024 * 10;
|
||||
|
||||
for(v_int32 i = 0; i < fragmentsCount; i++) {
|
||||
stream.write("0123456789", 10);
|
||||
}
|
||||
|
||||
auto wholeText = stream.toString();
|
||||
|
||||
OATPP_ASSERT(wholeText->getSize() == fragmentsCount * 10);
|
||||
|
||||
v_int32 substringSize = 10;
|
||||
for(v_int32 i = 0; i < wholeText->getSize() - substringSize; i ++) {
|
||||
OATPP_ASSERT(oatpp::String((const char*)&wholeText->getData()[i], substringSize, false) == stream.getSubstring(i, substringSize));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
oatpp::String sample = "0123456789";
|
||||
oatpp::String text = "";
|
||||
|
||||
for(v_int32 i = 0; i < 1024; i++ ) {
|
||||
text = text + sample;
|
||||
}
|
||||
|
||||
for(v_int32 incStep = 1; incStep <= 1024; incStep ++) {
|
||||
|
||||
BufferOutputStream stream(0, incStep);
|
||||
|
||||
for(v_int32 i = 0; i < 1024; i++ ) {
|
||||
stream << sample;
|
||||
|
||||
OATPP_ASSERT(stream.getCapacity() >= stream.getCurrentPosition());
|
||||
|
||||
}
|
||||
|
||||
OATPP_ASSERT(text == stream.toString());
|
||||
|
||||
OATPP_ASSERT(stream.getCapacity() < 1024 * (10 + 1));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}}}}
|
43
test/oatpp/core/data/stream/BufferStreamTest.hpp
Normal file
43
test/oatpp/core/data/stream/BufferStreamTest.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_test_core_data_stream_BufferStream_hpp
|
||||
#define oatpp_test_core_data_stream_BufferStream_hpp
|
||||
|
||||
#include "oatpp-test/UnitTest.hpp"
|
||||
|
||||
namespace oatpp { namespace test { namespace core { namespace data { namespace stream {
|
||||
|
||||
class BufferStreamTest : public UnitTest{
|
||||
public:
|
||||
|
||||
BufferStreamTest():UnitTest("TEST[core::data::stream::BufferStreamTest]"){}
|
||||
void onRun() override;
|
||||
|
||||
};
|
||||
|
||||
}}}}}
|
||||
|
||||
|
||||
#endif // oatpp_test_core_data_stream_BufferStream_hpp
|
@ -44,9 +44,9 @@ void UrlTest::onRun() {
|
||||
OATPP_ASSERT(url.authority.host && url.authority.host == "127.0.0.1");
|
||||
OATPP_ASSERT(url.authority.port == 8000);
|
||||
OATPP_ASSERT(url.path && url.path == "/path/to/resource/");
|
||||
OATPP_ASSERT(url.queryParams.size() == 2);
|
||||
OATPP_ASSERT(url.queryParams["q1"] == "1");
|
||||
OATPP_ASSERT(url.queryParams["q2"] == "2");
|
||||
OATPP_ASSERT(url.queryParams.getSize() == 2);
|
||||
OATPP_ASSERT(url.queryParams.get("q1") == "1");
|
||||
OATPP_ASSERT(url.queryParams.get("q2") == "2");
|
||||
}
|
||||
|
||||
{
|
||||
@ -59,9 +59,9 @@ void UrlTest::onRun() {
|
||||
OATPP_ASSERT(url.authority.host && url.authority.host == "oatpp.io");
|
||||
OATPP_ASSERT(url.authority.port == 8000);
|
||||
OATPP_ASSERT(url.path && url.path == "/path/to/resource");
|
||||
OATPP_ASSERT(url.queryParams.size() == 2);
|
||||
OATPP_ASSERT(url.queryParams["q1"] == "1");
|
||||
OATPP_ASSERT(url.queryParams["q2"] == "2");
|
||||
OATPP_ASSERT(url.queryParams.getSize() == 2);
|
||||
OATPP_ASSERT(url.queryParams.get("q1") == "1");
|
||||
OATPP_ASSERT(url.queryParams.get("q2") == "2");
|
||||
}
|
||||
|
||||
{
|
||||
@ -74,9 +74,9 @@ void UrlTest::onRun() {
|
||||
OATPP_ASSERT(url.authority.host && url.authority.host == "oatpp.io");
|
||||
OATPP_ASSERT(url.authority.port == -1);
|
||||
OATPP_ASSERT(url.path && url.path == "/");
|
||||
OATPP_ASSERT(url.queryParams.size() == 2);
|
||||
OATPP_ASSERT(url.queryParams["q1"] == "1");
|
||||
OATPP_ASSERT(url.queryParams["q2"] == "2");
|
||||
OATPP_ASSERT(url.queryParams.getSize() == 2);
|
||||
OATPP_ASSERT(url.queryParams.get("q1") == "1");
|
||||
OATPP_ASSERT(url.queryParams.get("q2") == "2");
|
||||
}
|
||||
|
||||
{
|
||||
@ -89,7 +89,7 @@ void UrlTest::onRun() {
|
||||
OATPP_ASSERT(url.authority.host && url.authority.host == "oatpp.io");
|
||||
OATPP_ASSERT(url.authority.port == -1);
|
||||
OATPP_ASSERT(url.path && url.path == "/");
|
||||
OATPP_ASSERT(url.queryParams.size() == 0);
|
||||
OATPP_ASSERT(url.queryParams.getSize() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
@ -102,7 +102,7 @@ void UrlTest::onRun() {
|
||||
OATPP_ASSERT(url.authority.host && url.authority.host == "oatpp.io");
|
||||
OATPP_ASSERT(url.authority.port == -1);
|
||||
OATPP_ASSERT(url.path == nullptr);
|
||||
OATPP_ASSERT(url.queryParams.size() == 0);
|
||||
OATPP_ASSERT(url.queryParams.getSize() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
@ -115,67 +115,67 @@ void UrlTest::onRun() {
|
||||
OATPP_ASSERT(url.authority.host && url.authority.host == "oatpp.io");
|
||||
OATPP_ASSERT(url.authority.port == -1);
|
||||
OATPP_ASSERT(url.path == nullptr);
|
||||
OATPP_ASSERT(url.queryParams.size() == 0);
|
||||
OATPP_ASSERT(url.queryParams.getSize() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
const char* urlText = "?key1=value1&key2=value2&key3=value3";
|
||||
OATPP_LOGV(TAG, "urlText='%s'", urlText);
|
||||
auto params = Url::Parser::parseQueryParams(urlText);
|
||||
OATPP_ASSERT(params.size() == 3);
|
||||
OATPP_ASSERT(params["key1"] == "value1");
|
||||
OATPP_ASSERT(params["key2"] == "value2");
|
||||
OATPP_ASSERT(params["key2"] == "value2");
|
||||
OATPP_ASSERT(params.getSize() == 3);
|
||||
OATPP_ASSERT(params.get("key1") == "value1");
|
||||
OATPP_ASSERT(params.get("key2") == "value2");
|
||||
OATPP_ASSERT(params.get("key2") == "value2");
|
||||
}
|
||||
|
||||
{
|
||||
const char *urlText = "?key1=value1&key2&key3=value3";
|
||||
OATPP_LOGV(TAG, "urlText='%s'", urlText);
|
||||
auto params = Url::Parser::parseQueryParams(urlText);
|
||||
OATPP_ASSERT(params.size() == 3);
|
||||
OATPP_ASSERT(params["key1"] == "value1");
|
||||
OATPP_ASSERT(params["key2"] == "");
|
||||
OATPP_ASSERT(params["key3"] == "value3");
|
||||
OATPP_ASSERT(params.getSize() == 3);
|
||||
OATPP_ASSERT(params.get("key1") == "value1");
|
||||
OATPP_ASSERT(params.get("key2") == "");
|
||||
OATPP_ASSERT(params.get("key3") == "value3");
|
||||
}
|
||||
|
||||
{
|
||||
const char *urlText = "?key1=value1&key2&key3";
|
||||
OATPP_LOGV(TAG, "urlText='%s'", urlText);
|
||||
auto params = Url::Parser::parseQueryParams(urlText);
|
||||
OATPP_ASSERT(params.size() == 3);
|
||||
OATPP_ASSERT(params["key1"] == "value1");
|
||||
OATPP_ASSERT(params["key2"] == "");
|
||||
OATPP_ASSERT(params["key3"] == "");
|
||||
OATPP_ASSERT(params.getSize() == 3);
|
||||
OATPP_ASSERT(params.get("key1") == "value1");
|
||||
OATPP_ASSERT(params.get("key2") == "");
|
||||
OATPP_ASSERT(params.get("key3") == "");
|
||||
}
|
||||
|
||||
{
|
||||
const char *urlText = "label?key1=value1&key2=value2&key3=value3";
|
||||
OATPP_LOGV(TAG, "urlText='%s'", urlText);
|
||||
auto params = Url::Parser::labelQueryParams(urlText);
|
||||
OATPP_ASSERT(params.size() == 3);
|
||||
OATPP_ASSERT(params["key1"] == "value1");
|
||||
OATPP_ASSERT(params["key2"] == "value2");
|
||||
OATPP_ASSERT(params["key2"] == "value2");
|
||||
auto params = Url::Parser::parseQueryParams(urlText);
|
||||
OATPP_ASSERT(params.getSize() == 3);
|
||||
OATPP_ASSERT(params.get("key1") == "value1");
|
||||
OATPP_ASSERT(params.get("key2") == "value2");
|
||||
OATPP_ASSERT(params.get("key2") == "value2");
|
||||
}
|
||||
|
||||
{
|
||||
const char* urlText = "label?key1=value1&key2&key3=value3";
|
||||
OATPP_LOGV(TAG, "urlText='%s'", urlText);
|
||||
auto params = Url::Parser::labelQueryParams(urlText);
|
||||
OATPP_ASSERT(params.size() == 3);
|
||||
OATPP_ASSERT(params["key1"] == "value1");
|
||||
OATPP_ASSERT(params["key2"] == "");
|
||||
OATPP_ASSERT(params["key3"] == "value3");
|
||||
auto params = Url::Parser::parseQueryParams(urlText);
|
||||
OATPP_ASSERT(params.getSize() == 3);
|
||||
OATPP_ASSERT(params.get("key1") == "value1");
|
||||
OATPP_ASSERT(params.get("key2") == "");
|
||||
OATPP_ASSERT(params.get("key3") == "value3");
|
||||
}
|
||||
|
||||
{
|
||||
const char* urlText = "label?key1=value1&key2&key3";
|
||||
OATPP_LOGV(TAG, "urlText='%s'", urlText);
|
||||
auto params = Url::Parser::labelQueryParams(urlText);
|
||||
OATPP_ASSERT(params.size() == 3);
|
||||
OATPP_ASSERT(params["key1"] == "value1");
|
||||
OATPP_ASSERT(params["key2"] == "");
|
||||
OATPP_ASSERT(params["key3"] == "");
|
||||
auto params = Url::Parser::parseQueryParams(urlText);
|
||||
OATPP_ASSERT(params.getSize() == 3);
|
||||
OATPP_ASSERT(params.get("key1") == "value1");
|
||||
OATPP_ASSERT(params.get("key2") == "");
|
||||
OATPP_ASSERT(params.get("key3") == "");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -175,29 +175,29 @@ void FullTest::onRun() {
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
auto value = response->readBodyToString();
|
||||
OATPP_ASSERT(value == "Ping");
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "*");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "GET, POST, OPTIONS");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization");
|
||||
auto header = response->getHeader(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "*");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "GET, POST, OPTIONS");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization");
|
||||
}
|
||||
|
||||
{ // test simple OPTIONS with CORS
|
||||
auto response = client->optionsCors(connection);
|
||||
OATPP_ASSERT(response->getStatusCode() == 204);
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "*");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "GET, POST, OPTIONS");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization");
|
||||
auto header = response->getHeader(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "*");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "GET, POST, OPTIONS");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization");
|
||||
}
|
||||
|
||||
{ // test simple GET with CORS
|
||||
@ -205,15 +205,15 @@ void FullTest::onRun() {
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
auto value = response->readBodyToString();
|
||||
OATPP_ASSERT(value == "Pong");
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "127.0.0.1");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "GET, POST, OPTIONS");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization");
|
||||
auto header = response->getHeader(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "127.0.0.1");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "GET, POST, OPTIONS");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization");
|
||||
}
|
||||
|
||||
{ // test simple GET with CORS
|
||||
@ -221,15 +221,15 @@ void FullTest::onRun() {
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
auto value = response->readBodyToString();
|
||||
OATPP_ASSERT(value == "Ping");
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "127.0.0.1");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "GET, OPTIONS");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization");
|
||||
auto header = response->getHeader(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "127.0.0.1");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "GET, OPTIONS");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization");
|
||||
}
|
||||
|
||||
{ // test simple GET with CORS
|
||||
@ -237,15 +237,15 @@ void FullTest::onRun() {
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
auto value = response->readBodyToString();
|
||||
OATPP_ASSERT(value == "Pong");
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "127.0.0.1");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "GET, OPTIONS");
|
||||
header = response->getHeaders().find(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "X-PWNT");
|
||||
auto header = response->getHeader(oatpp::web::protocol::http::Header::CORS_ORIGIN);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "127.0.0.1");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_METHODS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "GET, OPTIONS");
|
||||
header = response->getHeader(oatpp::web::protocol::http::Header::CORS_HEADERS);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "X-PWNT");
|
||||
}
|
||||
|
||||
{ // test GET with path parameter
|
||||
@ -324,9 +324,9 @@ void FullTest::onRun() {
|
||||
"description=Unauthorized\n"
|
||||
"message=Authorization Required\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "Basic realm=\"default-test-realm\"");
|
||||
auto header = response->getHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "Basic realm=\"default-test-realm\"");
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object
|
||||
@ -343,9 +343,9 @@ void FullTest::onRun() {
|
||||
"description=Unauthorized\n"
|
||||
"message=Authorization Required\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() == "Basic realm=\"custom-test-realm\"");
|
||||
auto header = response->getHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "Basic realm=\"custom-test-realm\"");
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object with unknown credentials where the
|
||||
@ -358,9 +358,9 @@ void FullTest::onRun() {
|
||||
"description=Unauthorized\n"
|
||||
"message=Unauthorized\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing or wrong
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString()->startsWith("Basic realm=\"custom-test-realm\""));
|
||||
auto header = response->getHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header->startsWith("Basic realm=\"custom-test-realm\""));
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization method
|
||||
@ -381,9 +381,9 @@ void FullTest::onRun() {
|
||||
"description=Unauthorized\n"
|
||||
"message=Unauthorized\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing or wrong
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end());
|
||||
OATPP_ASSERT(header->second.toString() = "Bearer realm=\"custom-bearer-realm\"");
|
||||
auto header = response->getHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header);
|
||||
OATPP_ASSERT(header == "Bearer realm=\"custom-bearer-realm\"");
|
||||
}
|
||||
|
||||
{ // test Chunked body
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "oatpp/network/virtual_/server/ConnectionProvider.hpp"
|
||||
#include "oatpp/network/virtual_/Interface.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferInputStream.hpp"
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
|
||||
#include "oatpp-test/web/ClientServerTestRunner.hpp"
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "oatpp/network/virtual_/server/ConnectionProvider.hpp"
|
||||
#include "oatpp/network/virtual_/Interface.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferInputStream.hpp"
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
|
||||
#include "oatpp-test/web/ClientServerTestRunner.hpp"
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
QUERIES(QueryParams, queries)) {
|
||||
auto dto = TestDto::createShared();
|
||||
dto->testMap = dto->testMap->createShared();
|
||||
for(auto& it : queries) {
|
||||
for(auto& it : queries.getAll()) {
|
||||
dto->testMap->put(it.first.toString(), it.second.toString());
|
||||
}
|
||||
return createDtoResponse(Status::CODE_200, dto);
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "oatpp/web/mime/multipart/InMemoryPartReader.hpp"
|
||||
#include "oatpp/web/mime/multipart/Reader.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/BufferInputStream.hpp"
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
|
@ -88,6 +88,7 @@ void ApiControllerTest::onRun() {
|
||||
typedef oatpp::web::protocol::http::Status Status;
|
||||
|
||||
Controller controller(nullptr);
|
||||
oatpp::data::stream::BufferOutputStream headersOutBuffer;
|
||||
|
||||
{
|
||||
auto endpoint = controller.Z__ENDPOINT_root;
|
||||
@ -106,7 +107,7 @@ void ApiControllerTest::onRun() {
|
||||
OATPP_ASSERT(response->getStatus().code == 200);
|
||||
|
||||
oatpp::data::stream::ChunkedBuffer stream;
|
||||
response->send(&stream);
|
||||
response->send(&stream, &headersOutBuffer);
|
||||
|
||||
OATPP_LOGD(TAG, "response:\n---\n%s\n---\n", stream.toString()->c_str());
|
||||
|
||||
@ -133,7 +134,7 @@ void ApiControllerTest::onRun() {
|
||||
OATPP_ASSERT(response->getStatus().code == 200);
|
||||
|
||||
oatpp::data::stream::ChunkedBuffer stream;
|
||||
response->send(&stream);
|
||||
response->send(&stream, &headersOutBuffer);
|
||||
|
||||
OATPP_LOGD(TAG, "response:\n---\n%s\n---\n", stream.toString()->c_str());
|
||||
|
||||
@ -154,7 +155,7 @@ void ApiControllerTest::onRun() {
|
||||
OATPP_ASSERT(response->getStatus().code == 200);
|
||||
|
||||
oatpp::data::stream::ChunkedBuffer stream;
|
||||
response->send(&stream);
|
||||
response->send(&stream, &headersOutBuffer);
|
||||
|
||||
OATPP_LOGD(TAG, "response:\n---\n%s\n---\n", stream.toString()->c_str());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user