// Trailer
if (trailer) {
for (const auto &kv : *trailer) {
+ // Skip fields with invalid names or values to prevent response
+ // splitting via CR/LF injection, matching set_header().
+ if (!fields::is_field_name(kv.first) ||
+ !fields::is_field_value(kv.second)) {
+ continue;
+ }
std::string field_line = kv.first + ": " + kv.second + "\r\n";
if (!write_data(strm, field_line.data(), field_line.size())) {
ok = false;
}
}
- auto length = std::to_string(res.body.size());
- res.set_header("Content-Length", length);
+ res.content_length_ = res.body.size();
+ res.set_header("Content-Length", std::to_string(res.content_length_));
}
}
return Get(path, Headers(), std::move(progress));
}
+Result ClientImpl::Get(const std::string &path, const Params ¶ms,
+ DownloadProgress progress) {
+ return Get(path, params, Headers(), std::move(progress));
+}
+
Result ClientImpl::Get(const std::string &path, const Params ¶ms,
const Headers &headers,
DownloadProgress progress) {
return cli_->Get(path, headers, std::move(response_handler),
std::move(content_receiver), std::move(progress));
}
+Result Client::Get(const std::string &path, const Params ¶ms,
+ DownloadProgress progress) {
+ return cli_->Get(path, params, std::move(progress));
+}
Result Client::Get(const std::string &path, const Params ¶ms,
const Headers &headers, DownloadProgress progress) {
return cli_->Get(path, params, headers, std::move(progress));
// SSL HTTP client implementation
SSLClient::~SSLClient() {
- if (ctx_) { tls::free_context(ctx_); }
// Make sure to shut down SSL since shutdown_ssl will resolve to the
// base function rather than the derived function once we get to the
// base class destructor, and won't free the SSL (causing a leak).
+ // This must happen before the context is freed below: some backends
+ // (e.g. mbedTLS) have the SSL session borrow a raw pointer into the
+ // context, so freeing the context first leaves close_notify reading
+ // freed memory.
shutdown_ssl_impl(socket_, true);
+ if (ctx_) {
+ tls::free_context(ctx_);
+ ctx_ = nullptr;
+ }
}
bool SSLClient::is_valid() const { return ctx_ != nullptr; }
bool WebSocketClient::is_valid() const { return is_valid_; }
void WebSocketClient::shutdown_and_close() {
+ // Send the close frame while the TLS session is still alive: ws_ holds an
+ // SSLSocketStream that keeps a raw pointer to tls_session_, so the session
+ // must outlive ws_->close() and ws_.reset() to avoid a use-after-free.
+ if (ws_ && ws_->is_open()) { ws_->close(); }
+ ws_.reset();
#ifdef CPPHTTPLIB_SSL_ENABLED
if (is_ssl_) {
if (tls_session_) {
}
}
#endif
- if (ws_ && ws_->is_open()) { ws_->close(); }
- ws_.reset();
if (sock_ != INVALID_SOCKET) {
detail::shutdown_socket(sock_);
detail::close_socket(sock_);
#ifndef CPPHTTPLIB_HTTPLIB_H
#define CPPHTTPLIB_HTTPLIB_H
-#define CPPHTTPLIB_VERSION "0.49.0"
-#define CPPHTTPLIB_VERSION_NUM "0x003100"
+#define CPPHTTPLIB_VERSION "0.50.1"
+#define CPPHTTPLIB_VERSION_NUM "0x003201"
#ifdef _WIN32
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0A00
Result Get(const std::string &path, const Headers &headers, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
+ Result Get(const std::string &path, const Params ¶ms, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Params ¶ms, const Headers &headers, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Params ¶ms, const Headers &headers, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Params ¶ms, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Headers &headers, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
+ Result Get(const std::string &path, const Params ¶ms, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Params ¶ms, const Headers &headers, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Params ¶ms, const Headers &headers, ContentReceiver content_receiver, DownloadProgress progress = nullptr);
Result Get(const std::string &path, const Params ¶ms, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, DownloadProgress progress = nullptr);