Skip to content

Commit 3159dd7

Browse files
committed
Fix #1578
1 parent a636a09 commit 3159dd7

File tree

2 files changed

+236
-142
lines changed

2 files changed

+236
-142
lines changed

httplib.h

Lines changed: 94 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,23 @@ struct MultipartFormData {
571571
using MultipartFormDataItems = std::vector<MultipartFormData>;
572572
using MultipartFormDataMap = std::multimap<std::string, MultipartFormData>;
573573

574+
struct FormData {
575+
Params fields; // Text fields from multipart
576+
MultipartFormDataMap files; // Files from multipart
577+
578+
// Text field access
579+
std::string get_field(const std::string &key, size_t id = 0) const;
580+
std::vector<std::string> get_fields(const std::string &key) const;
581+
bool has_field(const std::string &key) const;
582+
size_t get_field_count(const std::string &key) const;
583+
584+
// File access
585+
MultipartFormData get_file(const std::string &key, size_t id = 0) const;
586+
std::vector<MultipartFormData> get_files(const std::string &key) const;
587+
bool has_file(const std::string &key) const;
588+
size_t get_file_count(const std::string &key) const;
589+
};
590+
574591
struct MultipartFormDataForClientInput {
575592
std::string name;
576593
std::string content;
@@ -681,7 +698,7 @@ struct Request {
681698
// for server
682699
std::string version;
683700
std::string target;
684-
MultipartFormDataMap files;
701+
FormData form;
685702
Ranges ranges;
686703
Match matches;
687704
std::unordered_map<std::string, std::string> path_params;
@@ -6347,17 +6364,58 @@ inline bool Request::is_multipart_form_data() const {
63476364
}
63486365

63496366
inline bool Request::has_file(const std::string &key) const {
6350-
return files.find(key) != files.end();
6367+
return form.has_file(key);
63516368
}
63526369

63536370
inline MultipartFormData Request::get_file_value(const std::string &key) const {
6354-
auto it = files.find(key);
6355-
if (it != files.end()) { return it->second; }
6356-
return MultipartFormData();
6371+
return form.get_file(key);
63576372
}
63586373

63596374
inline std::vector<MultipartFormData>
63606375
Request::get_file_values(const std::string &key) const {
6376+
return form.get_files(key);
6377+
}
6378+
6379+
// FormData implementation
6380+
inline std::string FormData::get_field(const std::string &key,
6381+
size_t id) const {
6382+
auto rng = fields.equal_range(key);
6383+
auto it = rng.first;
6384+
std::advance(it, static_cast<ssize_t>(id));
6385+
if (it != rng.second) { return it->second; }
6386+
return std::string();
6387+
}
6388+
6389+
inline std::vector<std::string>
6390+
FormData::get_fields(const std::string &key) const {
6391+
std::vector<std::string> values;
6392+
auto rng = fields.equal_range(key);
6393+
for (auto it = rng.first; it != rng.second; it++) {
6394+
values.push_back(it->second);
6395+
}
6396+
return values;
6397+
}
6398+
6399+
inline bool FormData::has_field(const std::string &key) const {
6400+
return fields.find(key) != fields.end();
6401+
}
6402+
6403+
inline size_t FormData::get_field_count(const std::string &key) const {
6404+
auto r = fields.equal_range(key);
6405+
return static_cast<size_t>(std::distance(r.first, r.second));
6406+
}
6407+
6408+
inline MultipartFormData FormData::get_file(const std::string &key,
6409+
size_t id) const {
6410+
auto rng = files.equal_range(key);
6411+
auto it = rng.first;
6412+
std::advance(it, static_cast<ssize_t>(id));
6413+
if (it != rng.second) { return it->second; }
6414+
return MultipartFormData();
6415+
}
6416+
6417+
inline std::vector<MultipartFormData>
6418+
FormData::get_files(const std::string &key) const {
63616419
std::vector<MultipartFormData> values;
63626420
auto rng = files.equal_range(key);
63636421
for (auto it = rng.first; it != rng.second; it++) {
@@ -6366,6 +6424,15 @@ Request::get_file_values(const std::string &key) const {
63666424
return values;
63676425
}
63686426

6427+
inline bool FormData::has_file(const std::string &key) const {
6428+
return files.find(key) != files.end();
6429+
}
6430+
6431+
inline size_t FormData::get_file_count(const std::string &key) const {
6432+
auto r = files.equal_range(key);
6433+
return static_cast<size_t>(std::distance(r.first, r.second));
6434+
}
6435+
63696436
// Response implementation
63706437
inline bool Response::has_header(const std::string &key) const {
63716438
return headers.find(key) != headers.end();
@@ -7225,6 +7292,8 @@ Server::write_content_with_provider(Stream &strm, const Request &req,
72257292

72267293
inline bool Server::read_content(Stream &strm, Request &req, Response &res) {
72277294
MultipartFormDataMap::iterator cur;
7295+
Params::iterator text_cur;
7296+
bool is_text_field = false;
72287297
auto file_count = 0;
72297298
if (read_content_core(
72307299
strm, req, res,
@@ -7239,13 +7308,28 @@ inline bool Server::read_content(Stream &strm, Request &req, Response &res) {
72397308
if (file_count++ == CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT) {
72407309
return false;
72417310
}
7242-
cur = req.files.emplace(file.name, file);
7311+
7312+
if (file.filename.empty()) {
7313+
// Text field -> form.fields
7314+
text_cur = req.form.fields.emplace(file.name, "");
7315+
is_text_field = true;
7316+
} else {
7317+
// File -> form.files
7318+
cur = req.form.files.emplace(file.name, file);
7319+
is_text_field = false;
7320+
}
72437321
return true;
72447322
},
72457323
[&](const char *buf, size_t n) {
7246-
auto &content = cur->second.content;
7247-
if (content.size() + n > content.max_size()) { return false; }
7248-
content.append(buf, n);
7324+
if (is_text_field) {
7325+
// Text field content -> form.fields
7326+
text_cur->second.append(buf, n);
7327+
} else {
7328+
// File content -> form.files
7329+
auto &content = cur->second.content;
7330+
if (content.size() + n > content.max_size()) { return false; }
7331+
content.append(buf, n);
7332+
}
72497333
return true;
72507334
})) {
72517335
const auto &content_type = req.get_header_value("Content-Type");
@@ -7655,7 +7739,7 @@ inline void Server::apply_ranges(const Request &req, Response &res,
76557739

76567740
if (type != detail::EncodingType::None) {
76577741
if (pre_compression_logger_) { pre_compression_logger_(req, res); }
7658-
7742+
76597743
std::unique_ptr<detail::compressor> compressor;
76607744
std::string content_encoding;
76617745

0 commit comments

Comments
 (0)