@@ -91,9 +91,13 @@ struct ci {
91
91
enum class HttpVersion { v1_0 = 0 , v1_1 };
92
92
93
93
typedef std::multimap<std::string, std::string, detail::ci> Headers;
94
+
95
+ template <typename uint64_t , typename ... Args>
96
+ std::pair<std::string, std::string> make_range_header (uint64_t value, Args... args);
97
+
94
98
typedef std::multimap<std::string, std::string> Params;
95
99
typedef std::smatch Match;
96
- typedef std::function<void (int64_t current, int64_t total)> Progress;
100
+ typedef std::function<void (uint64_t current, uint64_t total)> Progress;
97
101
98
102
struct MultipartFile {
99
103
std::string filename;
@@ -111,11 +115,11 @@ struct Request {
111
115
Params params;
112
116
MultipartFiles files;
113
117
Match matches;
118
+
114
119
Progress progress;
115
120
116
121
bool has_header (const char * key) const ;
117
122
std::string get_header_value (const char * key) const ;
118
- void set_header (const char * key, const char * val);
119
123
120
124
bool has_param (const char * key) const ;
121
125
std::string get_param_value (const char * key) const ;
@@ -211,10 +215,17 @@ class Client {
211
215
Client (const char * host, int port, HttpVersion http_version = HttpVersion::v1_0);
212
216
virtual ~Client ();
213
217
214
- std::shared_ptr<Response> get (const char * path, Progress callback = [](int64_t ,int64_t ){});
218
+ std::shared_ptr<Response> get (const char * path, Progress progress = nullptr );
219
+ std::shared_ptr<Response> get (const char * path, const Headers& headers, Progress progress = nullptr );
220
+
215
221
std::shared_ptr<Response> head (const char * path);
222
+ std::shared_ptr<Response> head (const char * path, const Headers& headers);
223
+
216
224
std::shared_ptr<Response> post (const char * path, const std::string& body, const char * content_type);
225
+ std::shared_ptr<Response> post (const char * path, const Headers& headers, const std::string& body, const char * content_type);
226
+
217
227
std::shared_ptr<Response> post (const char * path, const Params& params);
228
+ std::shared_ptr<Response> post (const char * path, const Headers& headers, const Params& params);
218
229
219
230
bool send (const Request& req, Response& res);
220
231
@@ -633,7 +644,9 @@ bool read_content_with_length(Stream& strm, T& x, size_t len, Progress progress)
633
644
if (r_incr <= 0 ) {
634
645
return false ;
635
646
}
647
+
636
648
r += r_incr;
649
+
637
650
if (progress) {
638
651
progress (r, len);
639
652
}
@@ -702,7 +715,7 @@ bool read_content_chunked(Stream& strm, T& x)
702
715
}
703
716
704
717
template <typename T>
705
- bool read_content (Stream& strm, T& x, Progress progress = []( int64_t , int64_t ){} )
718
+ bool read_content (Stream& strm, T& x, Progress progress = Progress() )
706
719
{
707
720
auto len = get_header_value_int (x.headers , " Content-Length" , 0 );
708
721
@@ -980,6 +993,38 @@ inline bool parse_multipart_formdata(
980
993
return true ;
981
994
}
982
995
996
+ inline std::string to_lower (const char * beg, const char * end)
997
+ {
998
+ std::string out;
999
+ auto it = beg;
1000
+ while (it != end) {
1001
+ out += ::tolower (*it);
1002
+ it++;
1003
+ }
1004
+ return out;
1005
+ }
1006
+
1007
+ inline void make_range_header_core (std::string&) {}
1008
+
1009
+ template <typename uint64_t >
1010
+ inline void make_range_header_core (std::string& field, uint64_t value)
1011
+ {
1012
+ if (!field.empty ()) {
1013
+ field += " , " ;
1014
+ }
1015
+ field += std::to_string (value) + " -" ;
1016
+ }
1017
+
1018
+ template <typename uint64_t , typename ... Args>
1019
+ inline void make_range_header_core (std::string& field, uint64_t value1, uint64_t value2, Args... args)
1020
+ {
1021
+ if (!field.empty ()) {
1022
+ field += " , " ;
1023
+ }
1024
+ field += std::to_string (value1) + " -" + std::to_string (value2);
1025
+ make_range_header_core (field, args...);
1026
+ }
1027
+
983
1028
#ifdef _WIN32
984
1029
class WSInit {
985
1030
public:
@@ -996,19 +1041,18 @@ class WSInit {
996
1041
static WSInit wsinit_;
997
1042
#endif
998
1043
999
- inline std::string to_lower (const char * beg, const char * end)
1044
+ } // namespace detail
1045
+
1046
+ // Header utilities
1047
+ template <typename uint64_t , typename ... Args>
1048
+ inline std::pair<std::string, std::string> make_range_header (uint64_t value, Args... args)
1000
1049
{
1001
- std::string out;
1002
- auto it = beg;
1003
- while (it != end) {
1004
- out += ::tolower (*it);
1005
- it++;
1006
- }
1007
- return out;
1050
+ std::string field;
1051
+ detail::make_range_header_core (field, value, args...);
1052
+ field.insert (0 , " bytes=" );
1053
+ return std::make_pair (" Range" , field);
1008
1054
}
1009
1055
1010
- } // namespace detail
1011
-
1012
1056
// Request implementation
1013
1057
inline bool Request::has_header (const char * key) const
1014
1058
{
@@ -1020,11 +1064,6 @@ inline std::string Request::get_header_value(const char* key) const
1020
1064
return detail::get_header_value (headers, key, " " );
1021
1065
}
1022
1066
1023
- inline void Request::set_header (const char * key, const char * val)
1024
- {
1025
- headers.emplace (key, val);
1026
- }
1027
-
1028
1067
inline bool Request::has_param (const char * key) const
1029
1068
{
1030
1069
return params.find (key) != params.end ();
@@ -1485,22 +1524,34 @@ inline bool Client::read_and_close_socket(socket_t sock, const Request& req, Res
1485
1524
});
1486
1525
}
1487
1526
1488
- inline std::shared_ptr<Response> Client::get (const char * path, Progress callback)
1527
+ inline std::shared_ptr<Response> Client::get (const char * path, Progress progress)
1528
+ {
1529
+ return get (path, Headers (), progress);
1530
+ }
1531
+
1532
+ inline std::shared_ptr<Response> Client::get (const char * path, const Headers& headers, Progress progress)
1489
1533
{
1490
1534
Request req;
1491
1535
req.method = " GET" ;
1492
1536
req.path = path;
1493
- req.progress = callback;
1537
+ req.headers = headers;
1538
+ req.progress = progress;
1494
1539
1495
1540
auto res = std::make_shared<Response>();
1496
1541
1497
1542
return send (req, *res) ? res : nullptr ;
1498
1543
}
1499
1544
1500
1545
inline std::shared_ptr<Response> Client::head (const char * path)
1546
+ {
1547
+ return head (path, Headers ());
1548
+ }
1549
+
1550
+ inline std::shared_ptr<Response> Client::head (const char * path, const Headers& headers)
1501
1551
{
1502
1552
Request req;
1503
1553
req.method = " HEAD" ;
1554
+ req.headers = headers;
1504
1555
req.path = path;
1505
1556
1506
1557
auto res = std::make_shared<Response>();
@@ -1510,21 +1561,32 @@ inline std::shared_ptr<Response> Client::head(const char* path)
1510
1561
1511
1562
inline std::shared_ptr<Response> Client::post (
1512
1563
const char * path, const std::string& body, const char * content_type)
1564
+ {
1565
+ return post (path, Headers (), body, content_type);
1566
+ }
1567
+
1568
+ inline std::shared_ptr<Response> Client::post (
1569
+ const char * path, const Headers& headers, const std::string& body, const char * content_type)
1513
1570
{
1514
1571
Request req;
1515
1572
req.method = " POST" ;
1573
+ req.headers = headers;
1516
1574
req.path = path;
1517
1575
1518
- req.set_header (" Content-Type" , content_type);
1576
+ req.headers . emplace (" Content-Type" , content_type);
1519
1577
req.body = body;
1520
1578
1521
1579
auto res = std::make_shared<Response>();
1522
1580
1523
1581
return send (req, *res) ? res : nullptr ;
1524
1582
}
1525
1583
1526
- inline std::shared_ptr<Response> Client::post (
1527
- const char * path, const Params& params)
1584
+ inline std::shared_ptr<Response> Client::post (const char * path, const Params& params)
1585
+ {
1586
+ return post (path, Headers (), params);
1587
+ }
1588
+
1589
+ inline std::shared_ptr<Response> Client::post (const char * path, const Headers& headers, const Params& params)
1528
1590
{
1529
1591
std::string query;
1530
1592
for (auto it = params.begin (); it != params.end (); ++it) {
@@ -1536,7 +1598,7 @@ inline std::shared_ptr<Response> Client::post(
1536
1598
query += it->second ;
1537
1599
}
1538
1600
1539
- return post (path, query, " application/x-www-form-urlencoded" );
1601
+ return post (path, headers, query, " application/x-www-form-urlencoded" );
1540
1602
}
1541
1603
1542
1604
/*
0 commit comments