@@ -1248,6 +1248,14 @@ inline std::string from_i_to_hex(size_t n) {
12481248 return ret;
12491249}
12501250
1251+ inline bool start_with (const std::string &a, const std::string &b) {
1252+ if (a.size () < b.size ()) { return false ; }
1253+ for (size_t i = 0 ; i < b.size (); i++) {
1254+ if (std::tolower (a[i]) != std::tolower (b[i])) { return false ; }
1255+ }
1256+ return true ;
1257+ }
1258+
12511259inline size_t to_utf8 (int code, char *buff) {
12521260 if (code < 0x0080 ) {
12531261 buff[0 ] = (code & 0x7F );
@@ -1441,44 +1449,40 @@ inline std::string file_extension(const std::string &path) {
14411449 return std::string ();
14421450}
14431451
1444- inline std::pair<int , int > trim (const char *b, const char *e, int left,
1445- int right) {
1446- while (b + left < e && b[left] == ' ' ) {
1452+ inline bool is_space_or_tab (char c) { return c == ' ' || c == ' \t ' ; }
1453+
1454+ inline std::pair<size_t , size_t > trim (const char *b, const char *e, size_t left,
1455+ size_t right) {
1456+ while (b + left < e && is_space_or_tab (b[left])) {
14471457 left++;
14481458 }
1449- while (right - 1 >= 0 && b[right - 1 ] == ' ' ) {
1459+ while (right > 0 && is_space_or_tab ( b[right - 1 ]) ) {
14501460 right--;
14511461 }
14521462 return std::make_pair (left, right);
14531463}
14541464
1455- inline void trim (std::string &s) {
1456- auto is_not_space = [](int ch) { return !std::isspace (ch); };
1457- s.erase (s.begin (), std::find_if (s.begin (), s.end (), is_not_space));
1458- s.erase (std::find_if (s.rbegin (), s.rend (), is_not_space).base (), s.end ());
1465+ inline std::string trim_copy (const std::string &s) {
1466+ auto r = trim (s.data (), s.data () + s.size (), 0 , s.size ());
1467+ return s.substr (r.first , r.second - r.first );
14591468}
14601469
1461-
14621470template <class Fn > void split (const char *b, const char *e, char d, Fn fn) {
1463- int i = 0 ;
1464- int beg = 0 ;
1471+ size_t i = 0 ;
1472+ size_t beg = 0 ;
14651473
14661474 while (e ? (b + i < e) : (b[i] != ' \0 ' )) {
14671475 if (b[i] == d) {
14681476 auto r = trim (b, e, beg, i);
1469- if (r.first < r.second ) {
1470- fn (&b[r.first ], &b[r.second ]);
1471- }
1477+ if (r.first < r.second ) { fn (&b[r.first ], &b[r.second ]); }
14721478 beg = i + 1 ;
14731479 }
14741480 i++;
14751481 }
14761482
14771483 if (i) {
14781484 auto r = trim (b, e, beg, i);
1479- if (r.first < r.second ) {
1480- fn (&b[r.first ], &b[r.second ]);
1481- }
1485+ if (r.first < r.second ) { fn (&b[r.first ], &b[r.second ]); }
14821486 }
14831487}
14841488
@@ -2429,26 +2433,34 @@ inline uint64_t get_header_value<uint64_t>(const Headers &headers,
24292433 return def;
24302434}
24312435
2432- inline void parse_header (const char *beg, const char *end, Headers &headers) {
2436+ template <typename T>
2437+ inline bool parse_header (const char *beg, const char *end, T fn) {
2438+ // Skip trailing spaces and tabs.
2439+ while (beg < end && is_space_or_tab (end[-1 ])) {
2440+ end--;
2441+ }
2442+
24332443 auto p = beg;
24342444 while (p < end && *p != ' :' ) {
24352445 p++;
24362446 }
2447+
2448+ if (p == end) { return false ; }
2449+
2450+ auto key_end = p;
2451+
2452+ if (*p++ != ' :' ) { return false ; }
2453+
2454+ while (p < end && is_space_or_tab (*p)) {
2455+ p++;
2456+ }
2457+
24372458 if (p < end) {
2438- auto key_end = p;
2439- p++; // skip ':'
2440- while (p < end && (*p == ' ' || *p == ' \t ' )) {
2441- p++;
2442- }
2443- if (p < end) {
2444- auto val_begin = p;
2445- while (p < end) {
2446- p++;
2447- }
2448- headers.emplace (std::string (beg, key_end),
2449- decode_url (std::string (val_begin, end), true ));
2450- }
2459+ fn (std::string (beg, key_end), decode_url (std::string (p, end), true ));
2460+ return true ;
24512461 }
2462+
2463+ return false ;
24522464}
24532465
24542466inline bool read_headers (Stream &strm, Headers &headers) {
@@ -2467,13 +2479,13 @@ inline bool read_headers(Stream &strm, Headers &headers) {
24672479 continue ; // Skip invalid line.
24682480 }
24692481
2470- // Skip trailing spaces and tabs.
2482+ // Exclude CRLF
24712483 auto end = line_reader.ptr () + line_reader.size () - 2 ;
2472- while (line_reader.ptr () < end && (end[-1 ] == ' ' || end[-1 ] == ' \t ' )) {
2473- end--;
2474- }
24752484
2476- parse_header (line_reader.ptr (), end, headers);
2485+ parse_header (line_reader.ptr (), end,
2486+ [&](std::string &&key, std::string &&val) {
2487+ headers.emplace (std::move (key), std::move (val));
2488+ });
24772489 }
24782490
24792491 return true ;
@@ -2835,18 +2847,6 @@ inline bool redirect(T &cli, const Request &req, Response &res,
28352847 return ret;
28362848}
28372849
2838- inline bool contains_header (const std::string &header, const std::string &name) {
2839- if (header.length () >= name.length ()) {
2840- for (int i = 0 ; i < name.length (); ++i) {
2841- if (std::tolower (header[i]) != std::tolower (name[i])) {
2842- return false ;
2843- }
2844- }
2845- return true ;
2846- }
2847- return false ;
2848- }
2849-
28502850inline std::string params_to_query_str (const Params ¶ms) {
28512851 std::string query;
28522852
@@ -2871,7 +2871,7 @@ inline void parse_query_text(const std::string &s, Params ¶ms) {
28712871 }
28722872 });
28732873
2874- if (!key.empty ()) {
2874+ if (!key.empty ()) {
28752875 params.emplace (decode_url (key, true ), decode_url (val, true ));
28762876 }
28772877 });
@@ -2975,15 +2975,13 @@ class MultipartFormDataParser {
29752975 break ;
29762976 }
29772977
2978- auto header = buf_.substr (0 , pos);
2979- {
2978+ static const std::string header_name = " content-type:" ;
2979+ const auto header = buf_.substr (0 , pos);
2980+ if (start_with (header, header_name)) {
2981+ file_.content_type = trim_copy (header.substr (header_name.size ()));
2982+ } else {
29802983 std::smatch m;
2981- const std::string header_name = " content-type:" ;
2982- if (contains_header (header, header_name)) {
2983- header.erase (header.begin (), header.begin () + header_name.size ());
2984- trim (header);
2985- file_.content_type = header;
2986- } else if (std::regex_match (header, m, re_content_disposition)) {
2984+ if (std::regex_match (header, m, re_content_disposition)) {
29872985 file_.name = m[1 ];
29882986 file_.filename = m[2 ];
29892987 }
0 commit comments