Update changelog. Request/Response: use ObjectHandle for stream transfers.

This commit is contained in:
lganzzzo 2021-10-29 01:38:39 +03:00
parent 70a643a571
commit 446ad6710d
5 changed files with 79 additions and 26 deletions

View File

@ -14,6 +14,7 @@ Contents:
- [ConnectionProviderSwitch](#connectionproviderswitch)
- [Proper Server Stoppage](#proper-server-stoppage)
- [TemporaryFile](#temporaryfile)
- [Better Multipart](#better-multipart)
- [Response::getBody()](#responsegetbody)
- [data::stream::FIFOStream](#datastreamfifostream)
- [data::stream::BufferedInputStream](#datastreambufferedinputstream)
@ -243,7 +244,7 @@ Now call to `HttpConnectionHandler::stop()`, `AsyncHttpConnectionHandler::stop()
## TemporaryFile
Introduce `oatpp::data::share::TemporaryFile`.
Introduce `oatpp::data::resource::TemporaryFile`.
Use-case:
@ -251,20 +252,72 @@ Temporary file resolves concurrency issues during file uploads.
Also, a temporary file ensures that partially uploaded (due to errors/exceptions) resources will be automatically deleted at the end of the block.
```cpp
#include "oatpp/core/data/resource/TemporaryFile.hpp"
...
ENDPOINT("POST", "/upload", upload,
REQUEST(std::shared_ptr<IncomingRequest>, request))
{
oatpp::data::share::TemporaryFile tmp("/tmp"); // create random file in '/tmp' folder
auto stream = tmp.openOutputStream();
request->transferBody(&stream); // transfer body to temporary file
tmp.moveFile("/path/to/permanent/storage/avatar.png"); // move file to permanent storage
/* create random file in '/tmp' folder */
oatpp::data::resource::TemporaryFile tmp("/tmp");
/* transfer body to temporary file */
request->transferBody(tmp.openOutputStream());
/* move file to permanent storage */
OATPP_ASSERT_HTTP(tmp.moveFile("/path/to/permanent/storage/avatar.png"), Status::CODE_500, "Failed to save file")
/* return 200 */
return createResponse(Status::CODE_200, "OK");
}
```
## Better Multipart
Multipart API has been changed and improved.
Now it's possible to upload multiple files using `TemporaryFile` and keep track of
all parts and their corresponding data resources.
```cpp
#include "oatpp/web/mime/multipart/TemporaryFileProvider.hpp"
#include "oatpp/web/mime/multipart/Reader.hpp"
#include "oatpp/web/mime/multipart/PartList.hpp"
...
namespace multipart = oatpp::web::mime::multipart;
...
ENDPOINT("POST", "upload", upload,
REQUEST(std::shared_ptr<IncomingRequest>, request))
{
/* create multipart object */
multipart::PartList multipart(request->getHeaders());
/* create multipart reader */
multipart::Reader multipartReader(&multipart);
/* setup reader to stream parts to a temporary files by default */
multipartReader.setDefaultPartReader(multipart::createTemporaryFilePartReader("/Users/leonid/Documents/tmp"));
/* upload multipart data */
request->transferBody(&multipartReader);
/* list all parts and locations to corresponding temporary files */
auto parts = multipart.getAllParts();
for(auto& p : parts) {
OATPP_LOGD("part", "name=%s, location=%s", p->getName()->c_str(), p->getPayload()->getLocation()->c_str());
}
/* return 200 */
return createResponse(Status::CODE_200, "OK");
}
```
## Response::getBody()
`oatpp::web::protocol::http::outgoing::Response` has a new method `getBody()` to retreive the body of the response.

View File

@ -138,12 +138,12 @@ const data::Bundle& Request::getBundle() const {
return m_bundle;
}
void Request::transferBody(data::stream::WriteCallback* writeCallback) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), writeCallback, m_connection.get());
void Request::transferBody(const base::ObjectHandle<data::stream::WriteCallback>& writeCallback) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), writeCallback.get(), m_connection.get());
}
void Request::transferBodyToStream(oatpp::data::stream::OutputStream* toStream) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), toStream, m_connection.get());
void Request::transferBodyToStream(const base::ObjectHandle<oatpp::data::stream::OutputStream>& toStream) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), toStream.get(), m_connection.get());
}
oatpp::String Request::readBodyToString() const {

View File

@ -240,13 +240,13 @@ public:
* Read body chunk by chunk and pass chunks to the `writeCallback`.
* @param writeCallback - &id:oatpp::data::stream::WriteCallback;.
*/
void transferBody(data::stream::WriteCallback* writeCallback) const;
void transferBody(const base::ObjectHandle<data::stream::WriteCallback>& writeCallback) const;
/**
* Stream content of the body-stream to toStream
* @param toStream
*/
void transferBodyToStream(oatpp::data::stream::OutputStream* toStream) const;
void transferBodyToStream(const base::ObjectHandle<data::stream::OutputStream>& toStream) const;
/**
* Transfer body stream to string
@ -261,7 +261,7 @@ public:
* @return DTO
*/
template<class Wrapper>
Wrapper readBodyToDto(data::mapping::ObjectMapper* objectMapper) const {
Wrapper readBodyToDto(const base::ObjectHandle<data::mapping::ObjectMapper>& objectMapper) const {
return objectMapper->readFromString<Wrapper>(m_bodyDecoder->decodeToString(m_headers, m_bodyStream.get(), m_connection.get()));
}

View File

@ -103,12 +103,12 @@ std::shared_ptr<const http::incoming::BodyDecoder> Response::getBodyDecoder() co
return m_bodyDecoder;
}
void Response::transferBody(data::stream::WriteCallback* writeCallback) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), writeCallback, m_connection.get());
void Response::transferBody(const base::ObjectHandle<data::stream::WriteCallback>& writeCallback) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), writeCallback.get(), m_connection.get());
}
void Response::transferBodyToStream(oatpp::data::stream::OutputStream* toStream) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), toStream, m_connection.get());
void Response::transferBodyToStream(const base::ObjectHandle<oatpp::data::stream::OutputStream>& toStream) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), toStream.get(), m_connection.get());
}
oatpp::String Response::readBodyToString() const {

View File

@ -185,7 +185,7 @@ public:
* Get raw body stream.
* @return - raw body stream as &id:oatpp::data::stream::InputStream;.
*/
std::shared_ptr<oatpp::data::stream::InputStream> getBodyStream() const;
std::shared_ptr<data::stream::InputStream> getBodyStream() const;
/**
* Get body decoder configured for this response.
@ -198,14 +198,14 @@ public:
* Read body chunk by chunk and pass chunks to the `writeCallback`.
* @param writeCallback - &id:oatpp::data::stream::WriteCallback;.
*/
void transferBody(data::stream::WriteCallback* writeCallback) const;
void transferBody(const base::ObjectHandle<data::stream::WriteCallback>& writeCallback) const;
/**
* Decode and transfer body to toStream.
* Use case example - stream huge body directly to file using relatively small buffer.
* @param toStream - pointer to &id:oatpp::data::stream::OutputStream;.
*/
void transferBodyToStream(oatpp::data::stream::OutputStream* toStream) const;
void transferBodyToStream(const base::ObjectHandle<data::stream::OutputStream>& toStream) const;
/**
* Decode and read body to &id:oatpp::String;.
@ -220,8 +220,8 @@ public:
* @return - deserialized DTO object.
*/
template<class Wrapper>
Wrapper readBodyToDto(oatpp::data::mapping::ObjectMapper* objectMapper) const {
return m_bodyDecoder->decodeToDto<Wrapper>(m_headers, m_bodyStream.get(), m_connection.get(), objectMapper);
Wrapper readBodyToDto(const base::ObjectHandle<data::mapping::ObjectMapper>& objectMapper) const {
return m_bodyDecoder->decodeToDto<Wrapper>(m_headers, m_bodyStream.get(), m_connection.get(), objectMapper.get());
}
// Async
@ -240,7 +240,7 @@ public:
* @param toStream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;.
* @return - &id:oatpp::async::CoroutineStarter;.
*/
oatpp::async::CoroutineStarter transferBodyToStreamAsync(const std::shared_ptr<oatpp::data::stream::OutputStream>& toStream) const;
oatpp::async::CoroutineStarter transferBodyToStreamAsync(const std::shared_ptr<data::stream::OutputStream>& toStream) const;
/**
* Same as &l:Response::readBodyToString (); but Async.
@ -258,7 +258,7 @@ public:
*/
template<class Wrapper>
oatpp::async::CoroutineStarterForResult<const Wrapper&>
readBodyToDtoAsync(const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const {
readBodyToDtoAsync(const std::shared_ptr<data::mapping::ObjectMapper>& objectMapper) const {
return m_bodyDecoder->decodeToDtoAsync<Wrapper>(m_headers, m_bodyStream, m_connection, objectMapper);
}