128 const std::string& get_header_value(
const std::string& key)
const
133 part_view get_part_by_name(
const std::string_view name)
137 return result->second;
142 friend std::ostream& operator<<(std::ostream& stream,
const message_view& message)
144 std::string delimiter = dd + message.boundary;
146 for (
const part_view& part : message.
parts)
148 stream << delimiter << crlf;
151 stream << delimiter << dd << crlf;
159 std::ostringstream str;
161 return std::move(str).str();
165 std::string
dump(
int part_)
const
167 std::ostringstream str;
168 str <<
parts.at(part_);
169 return std::move(str).str();
175 boundary(get_boundary(get_header_value(
"Content-Type")))
178 throw bad_request(
"Empty boundary in multipart message");
179 parse_body(req.body);
183 static std::string_view get_boundary(
const std::string_view
header)
185 constexpr std::string_view boundary_text =
"boundary=";
186 const size_t found =
header.find(boundary_text);
187 if (found == std::string_view::npos)
192 const std::string_view to_return = header.substr(found + boundary_text.size());
193 if (!to_return.empty() && to_return[0] ==
'\"')
195 return to_return.substr(1, to_return.length() - 2);
200 void parse_body(std::string_view body)
202 const std::string delimiter = dd +
boundary;
205 while (body != (crlf))
207 const size_t found = body.find(delimiter);
208 if (found == std::string_view::npos)
211 throw bad_request(
"Unable to find multipart delimiter. Probably ill-formed body.");
214 const std::string_view section = body.substr(0, found);
218 body = body.substr(found + delimiter.length() + 2);
219 if (!section.empty())
221 part_view parsed_section = parse_section(section);
223 const auto name_header = section_params.find(
"name");
224 if (name_header == section_params.end())
226 throw bad_request(
"Unable to find header 'name' in multipart section. Probably ill-formed body.");
228 part_map.emplace(name_header->second, parsed_section);
229 parts.push_back(std::move(parsed_section));
234 [[nodiscard]]
static part_view parse_section(std::string_view section)
236 const size_t found = section.find(crlfcrlf);
237 if (found==std::string_view::npos)
239 throw bad_request(
"Section Header end missing in multipart message");
241 const std::string_view head_line = section.substr(0, found + 2);
242 section = section.substr(found + 4);
245 parse_section_head(head_line),
246 section.substr(0, section.length() - 2),
250 static mph_view_map parse_section_head(std::string_view lines)
254 while (!lines.empty())
258 const size_t found_crlf = lines.find(crlf);
259 std::string_view line = lines.substr(0, found_crlf);
260 std::string_view key;
261 lines = lines.substr(found_crlf + 2);
265 const size_t found_semicolon = line.find(
"; ");
266 std::string_view header = line.substr(0, found_semicolon);
267 if (found_semicolon != std::string_view::npos)
268 line = line.substr(found_semicolon + 2);
270 line = std::string_view();
272 const size_t header_split = header.find(
": ");
273 key = header.substr(0, header_split);
275 to_add.value = header.substr(header_split + 2);
279 while (!line.empty())
281 const size_t found_semicolon = line.find(
"; ");
282 std::string_view param = line.substr(0, found_semicolon);
283 if (found_semicolon != std::string_view::npos)
284 line = line.substr(found_semicolon + 2);
286 line = std::string_view();
288 const size_t param_split = param.find(
'=');
290 const std::string_view value = param.substr(param_split + 1);
292 to_add.params.emplace(param.substr(0, param_split), trim(value));
294 result.emplace(key, to_add);
300 [[nodiscard]]
static std::string_view trim(
const std::string_view
string,
const char excess =
'"')
302 if (
string.length() > 1 &&
string[0] == excess &&
string[
string.length() - 1] == excess)
303 return string.substr(1,
string.length() - 2);