@@ -1248,6 +1248,14 @@ inline std::string from_i_to_hex(size_t n) {
1248
1248
return ret;
1249
1249
}
1250
1250
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
+
1251
1259
inline size_t to_utf8 (int code, char *buff) {
1252
1260
if (code < 0x0080 ) {
1253
1261
buff[0 ] = (code & 0x7F );
@@ -1441,44 +1449,40 @@ inline std::string file_extension(const std::string &path) {
1441
1449
return std::string ();
1442
1450
}
1443
1451
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])) {
1447
1457
left++;
1448
1458
}
1449
- while (right - 1 >= 0 && b[right - 1 ] == ' ' ) {
1459
+ while (right > 0 && is_space_or_tab ( b[right - 1 ]) ) {
1450
1460
right--;
1451
1461
}
1452
1462
return std::make_pair (left, right);
1453
1463
}
1454
1464
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 );
1459
1468
}
1460
1469
1461
-
1462
1470
template <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 ;
1465
1473
1466
1474
while (e ? (b + i < e) : (b[i] != ' \0 ' )) {
1467
1475
if (b[i] == d) {
1468
1476
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 ]); }
1472
1478
beg = i + 1 ;
1473
1479
}
1474
1480
i++;
1475
1481
}
1476
1482
1477
1483
if (i) {
1478
1484
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 ]); }
1482
1486
}
1483
1487
}
1484
1488
@@ -2429,26 +2433,34 @@ inline uint64_t get_header_value<uint64_t>(const Headers &headers,
2429
2433
return def;
2430
2434
}
2431
2435
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
+
2433
2443
auto p = beg;
2434
2444
while (p < end && *p != ' :' ) {
2435
2445
p++;
2436
2446
}
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
+
2437
2458
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 ;
2451
2461
}
2462
+
2463
+ return false ;
2452
2464
}
2453
2465
2454
2466
inline bool read_headers (Stream &strm, Headers &headers) {
@@ -2467,13 +2479,13 @@ inline bool read_headers(Stream &strm, Headers &headers) {
2467
2479
continue ; // Skip invalid line.
2468
2480
}
2469
2481
2470
- // Skip trailing spaces and tabs.
2482
+ // Exclude CRLF
2471
2483
auto end = line_reader.ptr () + line_reader.size () - 2 ;
2472
- while (line_reader.ptr () < end && (end[-1 ] == ' ' || end[-1 ] == ' \t ' )) {
2473
- end--;
2474
- }
2475
2484
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
+ });
2477
2489
}
2478
2490
2479
2491
return true ;
@@ -2835,18 +2847,6 @@ inline bool redirect(T &cli, const Request &req, Response &res,
2835
2847
return ret;
2836
2848
}
2837
2849
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
-
2850
2850
inline std::string params_to_query_str (const Params ¶ms) {
2851
2851
std::string query;
2852
2852
@@ -2871,7 +2871,7 @@ inline void parse_query_text(const std::string &s, Params ¶ms) {
2871
2871
}
2872
2872
});
2873
2873
2874
- if (!key.empty ()) {
2874
+ if (!key.empty ()) {
2875
2875
params.emplace (decode_url (key, true ), decode_url (val, true ));
2876
2876
}
2877
2877
});
@@ -2975,15 +2975,13 @@ class MultipartFormDataParser {
2975
2975
break ;
2976
2976
}
2977
2977
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 {
2980
2983
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)) {
2987
2985
file_.name = m[1 ];
2988
2986
file_.filename = m[2 ];
2989
2987
}
0 commit comments