7 #include "crow/http_request.h"
8 #include "crow/returnable.h"
9 #include "crow/ci_map.h"
18 const std::string dd =
"--";
24 std::unordered_map<std::string, std::string>
params;
26 operator int()
const {
return std::stoi(
value); }
27 operator double()
const {
return std::stod(
value); }
31 using mph_map = std::unordered_multimap<std::string, header, ci_hash, ci_key_eq>;
34 template<
typename O,
typename T>
37 if (headers.count(key))
39 return headers.find(key)->second;
49 return get_header_value_object<header>(headers, key);
61 operator int()
const {
return std::stoi(
body); }
62 operator double()
const {
return std::stod(
body); }
64 const header& get_header_object(
const std::string& key)
const
71 using mp_map = std::unordered_multimap<std::string, part, ci_hash, ci_key_eq>;
81 const std::string& get_header_value(
const std::string& key)
const
86 part get_part_by_name(
const std::string& name)
88 mp_map::iterator result =
part_map.find(name);
90 return result->second;
96 std::string
dump()
const override
98 std::stringstream str;
99 std::string delimiter = dd +
boundary;
101 for (
unsigned i = 0; i <
parts.size(); i++)
103 str << delimiter << crlf;
106 str << delimiter << dd << crlf;
111 std::string
dump(
int part_)
const
113 std::stringstream str;
115 for (
auto& item_h : item.
headers)
117 str << item_h.first <<
": " << item_h.second.value;
118 for (
auto& it : item_h.second.params)
120 str <<
"; " << it.first <<
'=' << pad(it.second);
125 str << item.
body << crlf;
130 message(
const ci_map& headers_,
const std::string& boundary_,
const std::vector<part>& sections):
134 content_type =
"multipart/form-data; boundary=" +
boundary;
135 for (
auto& item :
parts)
145 returnable(
"multipart/form-data; boundary=CROW-BOUNDARY"),
147 boundary(get_boundary(get_header_value(
"Content-Type")))
150 content_type =
"multipart/form-data; boundary=" +
boundary;
151 parse_body(req.body);
155 std::string get_boundary(
const std::string&
header)
const
157 constexpr
char boundary_text[] =
"boundary=";
158 size_t found =
header.find(boundary_text);
159 if (found != std::string::npos)
161 std::string to_return(
header.substr(found + strlen(boundary_text)));
162 if (to_return[0] ==
'\"')
164 to_return = to_return.substr(1, to_return.length() - 2);
168 return std::string();
171 void parse_body(std::string body)
173 std::string delimiter = dd +
boundary;
176 while (body != (crlf))
178 size_t found = body.find(delimiter);
179 if (found == std::string::npos)
184 std::string section = body.substr(0, found);
188 body.erase(0, found + delimiter.length() + 2);
189 if (!section.empty())
191 part parsed_section(parse_section(section));
195 parts.push_back(std::move(parsed_section));
200 part parse_section(std::string& section)
202 struct part to_return;
204 size_t found = section.find(crlf + crlf);
205 std::string head_line = section.substr(0, found + 2);
206 section.erase(0, found + 4);
208 parse_section_head(head_line, to_return);
209 to_return.body = section.substr(0, section.length() - 2);
213 void parse_section_head(std::string& lines, part& part)
215 while (!lines.empty())
219 const size_t found_crlf = lines.find(crlf);
220 std::string line = lines.substr(0, found_crlf);
222 lines.erase(0, found_crlf + 2);
226 const size_t found_semicolon = line.find(
"; ");
227 std::string header = line.substr(0, found_semicolon);
228 if (found_semicolon != std::string::npos)
229 line.erase(0, found_semicolon + 2);
231 line = std::string();
233 size_t header_split = header.find(
": ");
234 key = header.substr(0, header_split);
236 to_add.value = header.substr(header_split + 2);
240 while (!line.empty())
242 const size_t found_semicolon = line.find(
"; ");
243 std::string param = line.substr(0, found_semicolon);
244 if (found_semicolon != std::string::npos)
245 line.erase(0, found_semicolon + 2);
247 line = std::string();
249 size_t param_split = param.find(
'=');
251 std::string value = param.substr(param_split + 1);
253 to_add.params.emplace(param.substr(0, param_split), trim(value));
255 part.headers.emplace(key, to_add);
259 inline std::string trim(std::string&
string,
const char& excess =
'"')
const
261 if (
string.length() > 1 &&
string[0] == excess &&
string[
string.length() - 1] == excess)
262 return string.substr(1,
string.length() - 2);
266 inline std::string pad(std::string&
string,
const char& padding =
'"')
const
268 return (padding +
string + padding);
std::unordered_multimap< std::string, part, ci_hash, ci_key_eq > mp_map
Multipart map (key is the name parameter).
Definition: multipart.h:71
std::unordered_multimap< std::string, header, ci_hash, ci_key_eq > mph_map
Multipart header map (key is header key).
Definition: multipart.h:31
const header & get_header_object(const T &headers, const std::string &key)
Same as get_header_value_object() but for multipart::header.
Definition: multipart.h:47
const O & get_header_value_object(const T &headers, const std::string &key)
Find and return the value object associated with the key. (returns an empty class if nothing is found...
Definition: multipart.h:35
The main namespace of the library. In this namespace is defined the most important classes and functi...
const std::string & get_header_value(const T &headers, const std::string &key)
Find and return the value associated with the key. (returns an empty string if nothing is found)
Definition: http_request.h:24
The parsed multipart request/response.
Definition: multipart.h:75
message(const ci_map &headers_, const std::string &boundary_, const std::vector< part > §ions)
Default constructor using default values.
Definition: multipart.h:130
std::vector< part > parts
The individual parts of the message.
Definition: multipart.h:78
message(const request &req)
Create a multipart message from a request data.
Definition: multipart.h:144
std::string boundary
The text boundary that separates different parts
Definition: multipart.h:77
mp_map part_map
The individual parts of the message, organized in a map with the name header parameter being the key.
Definition: multipart.h:79
std::string dump(int part_) const
Represent an individual part as a string.
Definition: multipart.h:111
std::string dump() const override
Represent all parts as a string (does not include message headers)
Definition: multipart.h:96
ci_map headers
The request/response headers.
Definition: multipart.h:76
One part of the multipart message.
Definition: multipart.h:57
mph_map headers
(optional) The first part before the data, Contains information regarding the type of data and encodi...
Definition: multipart.h:58
std::string body
The actual data in the part.
Definition: multipart.h:59
An HTTP request.
Definition: http_request.h:36
An abstract class that allows any other class to be returned by a handler.
Definition: returnable.h:9