mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2025-01-03 05:22:24 +08:00
Update changelog. Request/Response: use ObjectHandle for stream transfers.
This commit is contained in:
parent
70a643a571
commit
446ad6710d
@ -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.
|
||||||
|
@ -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 {
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user