1
0
mirror of synced 2025-07-17 17:40:57 +03:00
This commit is contained in:
yhirose
2025-07-05 20:30:31 -04:00
committed by GitHub
parent a636a094bf
commit a3f5569196
3 changed files with 334 additions and 51 deletions

161
httplib.h
View File

@ -1444,7 +1444,7 @@ public:
void set_keep_alive(bool on);
void set_follow_location(bool on);
void set_url_encode(bool on);
void set_path_encode(bool on);
void set_compress(bool on);
@ -1556,7 +1556,7 @@ protected:
bool keep_alive_ = false;
bool follow_location_ = false;
bool url_encode_ = true;
bool path_encode_ = true;
int address_family_ = AF_UNSPEC;
bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
@ -1794,6 +1794,7 @@ public:
void set_keep_alive(bool on);
void set_follow_location(bool on);
void set_path_encode(bool on);
void set_url_encode(bool on);
void set_compress(bool on);
@ -2248,6 +2249,16 @@ std::string hosted_at(const std::string &hostname);
void hosted_at(const std::string &hostname, std::vector<std::string> &addrs);
std::string encode_uri_component(const std::string &value);
std::string encode_uri(const std::string &value);
std::string decode_uri_component(const std::string &value);
std::string decode_uri(const std::string &value);
std::string encode_query_param(const std::string &value);
std::string append_query_params(const std::string &path, const Params &params);
std::pair<std::string, std::string> make_range_header(const Ranges &ranges);
@ -2289,9 +2300,7 @@ private:
int ret_ = -1;
};
std::string encode_query_param(const std::string &value);
std::string decode_url(const std::string &s, bool convert_plus_to_space);
std::string decode_path(const std::string &s, bool convert_plus_to_space);
std::string trim_copy(const std::string &s);
@ -2761,28 +2770,7 @@ inline bool FileStat::is_dir() const {
return ret_ >= 0 && S_ISDIR(st_.st_mode);
}
inline std::string encode_query_param(const std::string &value) {
std::ostringstream escaped;
escaped.fill('0');
escaped << std::hex;
for (auto c : value) {
if (std::isalnum(static_cast<uint8_t>(c)) || c == '-' || c == '_' ||
c == '.' || c == '!' || c == '~' || c == '*' || c == '\'' || c == '(' ||
c == ')') {
escaped << c;
} else {
escaped << std::uppercase;
escaped << '%' << std::setw(2)
<< static_cast<int>(static_cast<unsigned char>(c));
escaped << std::nouppercase;
}
}
return escaped.str();
}
inline std::string encode_url(const std::string &s) {
inline std::string encode_path(const std::string &s) {
std::string result;
result.reserve(s.size());
@ -2814,8 +2802,8 @@ inline std::string encode_url(const std::string &s) {
return result;
}
inline std::string decode_url(const std::string &s,
bool convert_plus_to_space) {
inline std::string decode_path(const std::string &s,
bool convert_plus_to_space) {
std::string result;
for (size_t i = 0; i < s.size(); i++) {
@ -4539,7 +4527,7 @@ inline bool parse_header(const char *beg, const char *end, T fn) {
case_ignore::equal(key, "Referer")) {
fn(key, val);
} else {
fn(key, decode_url(val, false));
fn(key, decode_path(val, false));
}
return true;
@ -5104,7 +5092,7 @@ inline std::string params_to_query_str(const Params &params) {
if (it != params.begin()) { query += "&"; }
query += it->first;
query += "=";
query += encode_query_param(it->second);
query += httplib::encode_uri_component(it->second);
}
return query;
}
@ -5127,7 +5115,7 @@ inline void parse_query_text(const char *data, std::size_t size,
});
if (!key.empty()) {
params.emplace(decode_url(key, true), decode_url(val, true));
params.emplace(decode_path(key, true), decode_path(val, true));
}
});
}
@ -5437,7 +5425,7 @@ public:
std::smatch m2;
if (std::regex_match(it->second, m2, re_rfc5987_encoding)) {
file_.filename = decode_url(m2[1], false); // override...
file_.filename = decode_path(m2[1], false); // override...
} else {
is_valid_ = false;
return false;
@ -6260,6 +6248,94 @@ inline void hosted_at(const std::string &hostname,
}
}
inline std::string encode_uri_component(const std::string &value) {
std::ostringstream escaped;
escaped.fill('0');
escaped << std::hex;
for (auto c : value) {
if (std::isalnum(static_cast<uint8_t>(c)) || c == '-' || c == '_' ||
c == '.' || c == '!' || c == '~' || c == '*' || c == '\'' || c == '(' ||
c == ')') {
escaped << c;
} else {
escaped << std::uppercase;
escaped << '%' << std::setw(2)
<< static_cast<int>(static_cast<unsigned char>(c));
escaped << std::nouppercase;
}
}
return escaped.str();
}
inline std::string encode_uri(const std::string &value) {
std::ostringstream escaped;
escaped.fill('0');
escaped << std::hex;
for (auto c : value) {
if (std::isalnum(static_cast<uint8_t>(c)) || c == '-' || c == '_' ||
c == '.' || c == '!' || c == '~' || c == '*' || c == '\'' || c == '(' ||
c == ')' || c == ';' || c == '/' || c == '?' || c == ':' || c == '@' ||
c == '&' || c == '=' || c == '+' || c == '$' || c == ',' || c == '#') {
escaped << c;
} else {
escaped << std::uppercase;
escaped << '%' << std::setw(2)
<< static_cast<int>(static_cast<unsigned char>(c));
escaped << std::nouppercase;
}
}
return escaped.str();
}
inline std::string decode_uri_component(const std::string &value) {
std::string result;
for (size_t i = 0; i < value.size(); i++) {
if (value[i] == '%' && i + 2 < value.size()) {
auto val = 0;
if (detail::from_hex_to_i(value, i + 1, 2, val)) {
result += static_cast<char>(val);
i += 2;
} else {
result += value[i];
}
} else {
result += value[i];
}
}
return result;
}
inline std::string decode_uri(const std::string &value) {
std::string result;
for (size_t i = 0; i < value.size(); i++) {
if (value[i] == '%' && i + 2 < value.size()) {
auto val = 0;
if (detail::from_hex_to_i(value, i + 1, 2, val)) {
result += static_cast<char>(val);
i += 2;
} else {
result += value[i];
}
} else {
result += value[i];
}
}
return result;
}
[[deprecated("Use encode_uri_component instead")]]
inline std::string encode_query_param(const std::string &value) {
return encode_uri_component(value);
}
inline std::string append_query_params(const std::string &path,
const Params &params) {
std::string path_with_query = path;
@ -7070,7 +7146,7 @@ inline bool Server::parse_request_line(const char *s, Request &req) const {
detail::divide(req.target, '?',
[&](const char *lhs_data, std::size_t lhs_size,
const char *rhs_data, std::size_t rhs_size) {
req.path = detail::decode_url(
req.path = detail::decode_path(
std::string(lhs_data, lhs_size), false);
detail::parse_query_text(rhs_data, rhs_size, req.params);
});
@ -7967,7 +8043,7 @@ inline void ClientImpl::copy_settings(const ClientImpl &rhs) {
#endif
keep_alive_ = rhs.keep_alive_;
follow_location_ = rhs.follow_location_;
url_encode_ = rhs.url_encode_;
path_encode_ = rhs.path_encode_;
address_family_ = rhs.address_family_;
tcp_nodelay_ = rhs.tcp_nodelay_;
ipv6_v6only_ = rhs.ipv6_v6only_;
@ -8332,7 +8408,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
if (next_host.empty()) { next_host = host_; }
if (next_path.empty()) { next_path = "/"; }
auto path = detail::decode_url(next_path, true) + next_query;
auto path = detail::decode_path(next_path, true) + next_query;
// Same host redirect - use current client
if (next_scheme == scheme && next_host == host_ && next_port == port_) {
@ -8427,7 +8503,7 @@ inline void ClientImpl::setup_redirect_client(ClientType &client) {
client.set_keep_alive(keep_alive_);
client.set_follow_location(
true); // Enable redirects to handle multi-step redirects
client.set_url_encode(url_encode_);
client.set_path_encode(path_encode_);
client.set_compress(compress_);
client.set_decompress(decompress_);
@ -8621,7 +8697,7 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
: append_query_params(req.path, req.params);
const auto &path =
url_encode_ ? detail::encode_url(path_with_query) : path_with_query;
path_encode_ ? detail::encode_path(path_with_query) : path_with_query;
detail::write_request_line(bstrm, req.method, path);
@ -9667,7 +9743,7 @@ inline void ClientImpl::set_keep_alive(bool on) { keep_alive_ = on; }
inline void ClientImpl::set_follow_location(bool on) { follow_location_ = on; }
inline void ClientImpl::set_url_encode(bool on) { url_encode_ = on; }
inline void ClientImpl::set_path_encode(bool on) { path_encode_ = on; }
inline void
ClientImpl::set_hostname_addr_map(std::map<std::string, std::string> addr_map) {
@ -11143,7 +11219,12 @@ inline void Client::set_follow_location(bool on) {
cli_->set_follow_location(on);
}
inline void Client::set_url_encode(bool on) { cli_->set_url_encode(on); }
inline void Client::set_path_encode(bool on) { cli_->set_path_encode(on); }
[[deprecated("Use set_path_encode instead")]]
inline void Client::set_url_encode(bool on) {
cli_->set_path_encode(on);
}
inline void Client::set_compress(bool on) { cli_->set_compress(on); }