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) - [ConnectionProviderSwitch](#connectionproviderswitch)
- [Proper Server Stoppage](#proper-server-stoppage) - [Proper Server Stoppage](#proper-server-stoppage)
- [TemporaryFile](#temporaryfile) - [TemporaryFile](#temporaryfile)
- [Better Multipart](#better-multipart)
- [Response::getBody()](#responsegetbody) - [Response::getBody()](#responsegetbody)
- [data::stream::FIFOStream](#datastreamfifostream) - [data::stream::FIFOStream](#datastreamfifostream)
- [data::stream::BufferedInputStream](#datastreambufferedinputstream) - [data::stream::BufferedInputStream](#datastreambufferedinputstream)
@ -243,7 +244,7 @@ Now call to `HttpConnectionHandler::stop()`, `AsyncHttpConnectionHandler::stop()
## TemporaryFile ## TemporaryFile
Introduce `oatpp::data::share::TemporaryFile`. Introduce `oatpp::data::resource::TemporaryFile`.
Use-case: 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. Also, a temporary file ensures that partially uploaded (due to errors/exceptions) resources will be automatically deleted at the end of the block.
```cpp ```cpp
#include "oatpp/core/data/resource/TemporaryFile.hpp"
...
ENDPOINT("POST", "/upload", upload, ENDPOINT("POST", "/upload", upload,
REQUEST(std::shared_ptr<IncomingRequest>, request)) REQUEST(std::shared_ptr<IncomingRequest>, request))
{ {
oatpp::data::share::TemporaryFile tmp("/tmp"); // create random file in '/tmp' folder /* create random file in '/tmp' folder */
oatpp::data::resource::TemporaryFile tmp("/tmp");
auto stream = tmp.openOutputStream();
request->transferBody(&stream); // transfer body to temporary file /* transfer body to temporary file */
request->transferBody(tmp.openOutputStream());
tmp.moveFile("/path/to/permanent/storage/avatar.png"); // move file to permanent storage
/* 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"); 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() ## Response::getBody()
`oatpp::web::protocol::http::outgoing::Response` has a new method `getBody()` to retreive the body of the response. `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; return m_bundle;
} }
void Request::transferBody(data::stream::WriteCallback* writeCallback) const { void Request::transferBody(const base::ObjectHandle<data::stream::WriteCallback>& writeCallback) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), writeCallback, m_connection.get()); m_bodyDecoder->decode(m_headers, m_bodyStream.get(), writeCallback.get(), m_connection.get());
} }
void Request::transferBodyToStream(oatpp::data::stream::OutputStream* toStream) const { void Request::transferBodyToStream(const base::ObjectHandle<oatpp::data::stream::OutputStream>& toStream) const {
m_bodyDecoder->decode(m_headers, m_bodyStream.get(), toStream, m_connection.get()); m_bodyDecoder->decode(m_headers, m_bodyStream.get(), toStream.get(), m_connection.get());
} }
oatpp::String Request::readBodyToString() const { oatpp::String Request::readBodyToString() const {

View File

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

View File

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