@@ -571,6 +571,23 @@ struct MultipartFormData {
571571using MultipartFormDataItems = std::vector<MultipartFormData>;
572572using 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+
574591struct 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
63496366inline bool Request::has_file (const std::string &key) const {
6350- return files. find (key) != files. end ( );
6367+ return form. has_file (key);
63516368}
63526369
63536370inline 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
63596374inline std::vector<MultipartFormData>
63606375Request::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
63706437inline 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
72267293inline 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