mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2025-05-10 01:33:53 +00:00
Improve multipart content reader interface
This commit is contained in:
parent
d910bfc303
commit
033bc35723
@ -121,14 +121,14 @@ svr.Post("/content_receiver",
|
|||||||
if (req.is_multipart_form_data()) {
|
if (req.is_multipart_form_data()) {
|
||||||
MultipartFiles files;
|
MultipartFiles files;
|
||||||
content_reader(
|
content_reader(
|
||||||
|
[&](const std::string &name, const MultipartFile &file) {
|
||||||
|
files.emplace(name, file);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
[&](const std::string &name, const char *data, size_t data_length) {
|
[&](const std::string &name, const char *data, size_t data_length) {
|
||||||
auto &file = files.find(name)->second;
|
auto &file = files.find(name)->second;
|
||||||
file.content.append(data, data_length);
|
file.content.append(data, data_length);
|
||||||
return true;
|
return true;
|
||||||
},
|
|
||||||
[&](const std::string &name, const MultipartFile &file) {
|
|
||||||
files.emplace(name, file);
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
std::string body;
|
std::string body;
|
||||||
|
44
httplib.h
44
httplib.h
@ -225,22 +225,22 @@ using MultipartFormDataItems = std::vector<MultipartFormData>;
|
|||||||
using ContentReceiver =
|
using ContentReceiver =
|
||||||
std::function<bool(const char *data, size_t data_length)>;
|
std::function<bool(const char *data, size_t data_length)>;
|
||||||
|
|
||||||
using MultipartContentReceiver =
|
|
||||||
std::function<bool(const std::string& name, const char *data, size_t data_length)>;
|
|
||||||
|
|
||||||
using MultipartContentHeader =
|
using MultipartContentHeader =
|
||||||
std::function<bool(const std::string &name, const MultipartFile &file)>;
|
std::function<bool(const std::string &name, const MultipartFile &file)>;
|
||||||
|
|
||||||
|
using MultipartContentReceiver =
|
||||||
|
std::function<bool(const std::string& name, const char *data, size_t data_length)>;
|
||||||
|
|
||||||
class ContentReader {
|
class ContentReader {
|
||||||
public:
|
public:
|
||||||
using Reader = std::function<bool(ContentReceiver receiver)>;
|
using Reader = std::function<bool(ContentReceiver receiver)>;
|
||||||
using MultipartReader = std::function<bool(MultipartContentReceiver receiver, MultipartContentHeader header)>;
|
using MultipartReader = std::function<bool(MultipartContentHeader header, MultipartContentReceiver receiver)>;
|
||||||
|
|
||||||
ContentReader(Reader reader, MultipartReader muitlpart_reader)
|
ContentReader(Reader reader, MultipartReader muitlpart_reader)
|
||||||
: reader_(reader), muitlpart_reader_(muitlpart_reader) {}
|
: reader_(reader), muitlpart_reader_(muitlpart_reader) {}
|
||||||
|
|
||||||
bool operator()(MultipartContentReceiver receiver, MultipartContentHeader header) const {
|
bool operator()(MultipartContentHeader header, MultipartContentReceiver receiver) const {
|
||||||
return muitlpart_reader_(receiver, header);
|
return muitlpart_reader_(header, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(ContentReceiver receiver) const {
|
bool operator()(ContentReceiver receiver) const {
|
||||||
@ -591,13 +591,13 @@ private:
|
|||||||
bool read_content_with_content_receiver(Stream &strm, bool last_connection,
|
bool read_content_with_content_receiver(Stream &strm, bool last_connection,
|
||||||
Request &req, Response &res,
|
Request &req, Response &res,
|
||||||
ContentReceiver receiver,
|
ContentReceiver receiver,
|
||||||
MultipartContentReceiver multipart_receiver,
|
MultipartContentHeader multipart_header,
|
||||||
MultipartContentHeader multipart_header);
|
MultipartContentReceiver multipart_receiver);
|
||||||
bool read_content_core(Stream &strm, bool last_connection,
|
bool read_content_core(Stream &strm, bool last_connection,
|
||||||
Request &req, Response &res,
|
Request &req, Response &res,
|
||||||
ContentReceiver receiver,
|
ContentReceiver receiver,
|
||||||
MultipartContentReceiver multipart_receiver,
|
MultipartContentHeader mulitpart_header,
|
||||||
MultipartContentHeader mulitpart_header);
|
MultipartContentReceiver multipart_receiver);
|
||||||
|
|
||||||
virtual bool process_and_close_socket(socket_t sock);
|
virtual bool process_and_close_socket(socket_t sock);
|
||||||
|
|
||||||
@ -2796,11 +2796,17 @@ Server::write_content_with_provider(Stream &strm, const Request &req,
|
|||||||
inline bool Server::read_content(Stream &strm, bool last_connection,
|
inline bool Server::read_content(Stream &strm, bool last_connection,
|
||||||
Request &req, Response &res) {
|
Request &req, Response &res) {
|
||||||
auto ret = read_content_core(strm, last_connection, req, res,
|
auto ret = read_content_core(strm, last_connection, req, res,
|
||||||
|
// Regular
|
||||||
[&](const char *buf, size_t n) {
|
[&](const char *buf, size_t n) {
|
||||||
if (req.body.size() + n > req.body.max_size()) { return false; }
|
if (req.body.size() + n > req.body.max_size()) { return false; }
|
||||||
req.body.append(buf, n);
|
req.body.append(buf, n);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
// Multipart
|
||||||
|
[&](const std::string &name, const MultipartFile &file) {
|
||||||
|
req.files.emplace(name, file);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
[&](const std::string &name, const char *buf, size_t n) {
|
[&](const std::string &name, const char *buf, size_t n) {
|
||||||
// TODO: handle elements with a same key
|
// TODO: handle elements with a same key
|
||||||
auto it = req.files.find(name);
|
auto it = req.files.find(name);
|
||||||
@ -2808,10 +2814,6 @@ inline bool Server::read_content(Stream &strm, bool last_connection,
|
|||||||
if (content.size() + n > content.max_size()) { return false; }
|
if (content.size() + n > content.max_size()) { return false; }
|
||||||
content.append(buf, n);
|
content.append(buf, n);
|
||||||
return true;
|
return true;
|
||||||
},
|
|
||||||
[&](const std::string &name, const MultipartFile &file) {
|
|
||||||
req.files.emplace(name, file);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2827,18 +2829,18 @@ inline bool
|
|||||||
Server::read_content_with_content_receiver(Stream &strm, bool last_connection,
|
Server::read_content_with_content_receiver(Stream &strm, bool last_connection,
|
||||||
Request &req, Response &res,
|
Request &req, Response &res,
|
||||||
ContentReceiver receiver,
|
ContentReceiver receiver,
|
||||||
MultipartContentReceiver multipart_receiver,
|
MultipartContentHeader multipart_header,
|
||||||
MultipartContentHeader multipart_header) {
|
MultipartContentReceiver multipart_receiver) {
|
||||||
return read_content_core(strm, last_connection, req, res,
|
return read_content_core(strm, last_connection, req, res,
|
||||||
receiver, multipart_receiver, multipart_header);
|
receiver, multipart_header, multipart_receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
Server::read_content_core(Stream &strm, bool last_connection,
|
Server::read_content_core(Stream &strm, bool last_connection,
|
||||||
Request &req, Response &res,
|
Request &req, Response &res,
|
||||||
ContentReceiver receiver,
|
ContentReceiver receiver,
|
||||||
MultipartContentReceiver multipart_receiver,
|
MultipartContentHeader mulitpart_header,
|
||||||
MultipartContentHeader mulitpart_header) {
|
MultipartContentReceiver multipart_receiver) {
|
||||||
detail::MultipartFormDataParser multipart_form_data_parser;
|
detail::MultipartFormDataParser multipart_form_data_parser;
|
||||||
ContentReceiver out;
|
ContentReceiver out;
|
||||||
|
|
||||||
@ -3001,9 +3003,9 @@ inline bool Server::routing(Request &req, Response &res, Stream &strm,
|
|||||||
return read_content_with_content_receiver(strm, last_connection, req, res,
|
return read_content_with_content_receiver(strm, last_connection, req, res,
|
||||||
receiver, nullptr, nullptr);
|
receiver, nullptr, nullptr);
|
||||||
},
|
},
|
||||||
[&](MultipartContentReceiver receiver, MultipartContentHeader header) {
|
[&](MultipartContentHeader header, MultipartContentReceiver receiver) {
|
||||||
return read_content_with_content_receiver(strm, last_connection, req, res,
|
return read_content_with_content_receiver(strm, last_connection, req, res,
|
||||||
nullptr, receiver, header);
|
nullptr, header, receiver);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -761,14 +761,14 @@ protected:
|
|||||||
if (req.is_multipart_form_data()) {
|
if (req.is_multipart_form_data()) {
|
||||||
MultipartFiles files;
|
MultipartFiles files;
|
||||||
content_reader(
|
content_reader(
|
||||||
|
[&](const std::string &name, const MultipartFile &file) {
|
||||||
|
files.emplace(name, file);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
[&](const std::string &name, const char *data, size_t data_length) {
|
[&](const std::string &name, const char *data, size_t data_length) {
|
||||||
auto &file = files.find(name)->second;
|
auto &file = files.find(name)->second;
|
||||||
file.content.append(data, data_length);
|
file.content.append(data, data_length);
|
||||||
return true;
|
return true;
|
||||||
},
|
|
||||||
[&](const std::string &name, const MultipartFile &file) {
|
|
||||||
files.emplace(name, file);
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
EXPECT_EQ(5u, files.size());
|
EXPECT_EQ(5u, files.size());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user