7 #include "crow/http_request.h"
8 #include "crow/returnable.h"
9 #include "crow/ci_map.h"
10 #include "crow/exceptions.h"
19 const std::string dd =
"--";
25 std::unordered_map<std::string, std::string>
params;
27 operator int()
const {
return std::stoi(
value); }
28 operator double()
const {
return std::stod(
value); }
32 using mph_map = std::unordered_multimap<std::string, header, ci_hash, ci_key_eq>;
35 template<
typename O,
typename T>
38 if (headers.count(key))
40 return headers.find(key)->second;
50 return get_header_value_object<header>(headers, key);
62 operator int()
const {
return std::stoi(
body); }
63 operator double()
const {
return std::stod(
body); }
65 const header& get_header_object(
const std::string& key)
const
72 using mp_map = std::unordered_multimap<std::string, part, ci_hash, ci_key_eq>;
82 const std::string& get_header_value(
const std::string& key)
const
87 part get_part_by_name(
const std::string& name)
89 mp_map::iterator result =
part_map.find(name);
91 return result->second;
97 std::string
dump()
const override
99 std::stringstream str;
100 std::string delimiter = dd +
boundary;
102 for (
unsigned i = 0; i <
parts.size(); i++)
104 str << delimiter << crlf;
107 str << delimiter << dd << crlf;
112 std::string
dump(
int part_)
const
114 std::stringstream str;
116 for (
auto& item_h : item.
headers)
118 str << item_h.first <<
": " << item_h.second.value;
119 for (
auto& it : item_h.second.params)
121 str <<
"; " << it.first <<
'=' << pad(it.second);
126 str << item.
body << crlf;
131 message(
const ci_map& headers_,
const std::string& boundary_,
const std::vector<part>& sections):
135 content_type =
"multipart/form-data; boundary=" +
boundary;
136 for (
auto& item :
parts)
146 returnable(
"multipart/form-data; boundary=CROW-BOUNDARY"),
148 boundary(get_boundary(get_header_value(
"Content-Type")))
152 content_type =
"multipart/form-data; boundary=" +
boundary;
153 parse_body(req.body);
157 throw bad_request(
"Empty boundary in multipart message");
162 std::string get_boundary(
const std::string&
header)
const
164 constexpr
char boundary_text[] =
"boundary=";
165 size_t found =
header.find(boundary_text);
166 if (found != std::string::npos)
168 std::string to_return(
header.substr(found + strlen(boundary_text)));
169 if (to_return[0] ==
'\"')
171 to_return = to_return.substr(1, to_return.length() - 2);
175 return std::string();
178 void parse_body(std::string body)
180 std::string delimiter = dd +
boundary;
183 while (body != (crlf))
185 size_t found = body.find(delimiter);
186 if (found == std::string::npos)
189 throw bad_request(
"Unable to find delimiter in multipart message. Probably ill-formed body");
191 std::string section = body.substr(0, found);
195 body.erase(0, found + delimiter.length() + 2);
196 if (!section.empty())
198 part parsed_section(parse_section(section));
202 parts.push_back(std::move(parsed_section));
207 part parse_section(std::string& section)
209 struct part to_return;
211 size_t found = section.find(crlf + crlf);
212 std::string head_line = section.substr(0, found + 2);
213 section.erase(0, found + 4);
215 parse_section_head(head_line, to_return);
216 to_return.body = section.substr(0, section.length() - 2);
220 void parse_section_head(std::string& lines, part& part)
222 while (!lines.empty())
226 const size_t found_crlf = lines.find(crlf);
227 std::string line = lines.substr(0, found_crlf);
229 lines.erase(0, found_crlf + 2);
233 const size_t found_semicolon = line.find(
"; ");
234 std::string header = line.substr(0, found_semicolon);
235 if (found_semicolon != std::string::npos)
236 line.erase(0, found_semicolon + 2);
238 line = std::string();
240 size_t header_split = header.find(
": ");
241 key = header.substr(0, header_split);
243 to_add.value = header.substr(header_split + 2);
247 while (!line.empty())
249 const size_t found_semicolon = line.find(
"; ");
250 std::string param = line.substr(0, found_semicolon);
251 if (found_semicolon != std::string::npos)
252 line.erase(0, found_semicolon + 2);
254 line = std::string();
256 size_t param_split = param.find(
'=');
258 std::string value = param.substr(param_split + 1);
260 to_add.params.emplace(param.substr(0, param_split), trim(value));
262 part.headers.emplace(key, to_add);
266 inline std::string trim(std::string&
string,
const char& excess =
'"')
const
268 if (
string.length() > 1 &&
string[0] == excess &&
string[
string.length() - 1] == excess)
269 return string.substr(1,
string.length() - 2);
273 inline std::string pad(std::string&
string,
const char& padding =
'"')
const
275 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:72
std::unordered_multimap< std::string, header, ci_hash, ci_key_eq > mph_map
Multipart header map (key is header key).
Definition: multipart.h:32
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:48
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:36
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
Definition: exceptions.h:7
The parsed multipart request/response.
Definition: multipart.h:76
message(const ci_map &headers_, const std::string &boundary_, const std::vector< part > §ions)
Default constructor using default values.
Definition: multipart.h:131
std::vector< part > parts
The individual parts of the message.
Definition: multipart.h:79
message(const request &req)
Create a multipart message from a request data.
Definition: multipart.h:145
std::string boundary
The text boundary that separates different parts
Definition: multipart.h:78
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:80
std::string dump(int part_) const
Represent an individual part as a string.
Definition: multipart.h:112
std::string dump() const override
Represent all parts as a string (does not include message headers)
Definition: multipart.h:97
ci_map headers
The request/response headers.
Definition: multipart.h:77
One part of the multipart message.
Definition: multipart.h:58
mph_map headers
(optional) The first part before the data, Contains information regarding the type of data and encodi...
Definition: multipart.h:59
std::string body
The actual data in the part.
Definition: multipart.h:60
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