From e00ad375803cfa151a0ec224a0b643ef0b2017cb Mon Sep 17 00:00:00 2001 From: Alex Hornung Date: Sat, 15 May 2021 13:48:25 +0100 Subject: [PATCH] Add option to bypass URL encode of path (#934) --- httplib.h | 13 ++++++++++++- test/test.cc | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/httplib.h b/httplib.h index b523e7a..6534828 100644 --- a/httplib.h +++ b/httplib.h @@ -1005,6 +1005,8 @@ public: void set_keep_alive(bool on); void set_follow_location(bool on); + void set_url_encode(bool on); + void set_compress(bool on); void set_decompress(bool on); @@ -1101,6 +1103,8 @@ protected: bool keep_alive_ = false; bool follow_location_ = false; + bool url_encode_ = true; + int address_family_ = AF_UNSPEC; bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY; SocketOptions socket_options_ = nullptr; @@ -1318,6 +1322,8 @@ public: void set_keep_alive(bool on); void set_follow_location(bool on); + void set_url_encode(bool on); + void set_compress(bool on); void set_decompress(bool on); @@ -5276,6 +5282,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_; tcp_nodelay_ = rhs.tcp_nodelay_; socket_options_ = rhs.socket_options_; compress_ = rhs.compress_; @@ -5703,7 +5710,7 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req, { detail::BufferStream bstrm; - const auto &path = detail::encode_url(req.path); + const auto &path = url_encode_ ? detail::encode_url(req.path) : req.path; bstrm.write_format("%s %s HTTP/1.1\r\n", req.method.c_str(), path.c_str()); detail::write_headers(bstrm, req.headers); @@ -6432,6 +6439,8 @@ 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_default_headers(Headers headers) { default_headers_ = std::move(headers); } @@ -7560,6 +7569,8 @@ 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_compress(bool on) { cli_->set_compress(on); } inline void Client::set_decompress(bool on) { cli_->set_decompress(on); } diff --git a/test/test.cc b/test/test.cc index ba3c14d..d502176 100644 --- a/test/test.cc +++ b/test/test.cc @@ -965,6 +965,42 @@ TEST(RedirectFromPageWithContent, Redirect) { #endif +TEST(PathUrlEncodeTest, PathUrlEncode) { + Server svr; + + svr.Get("/foo", [](const Request & req, Response &res) { + auto a = req.params.find("a"); + if (a != req.params.end()) { + res.set_content((*a).second, "text/plain"); + res.status = 200; + } else { + res.status = 400; + } + }); + + auto thread = std::thread([&]() { svr.listen(HOST, PORT); }); + + // Give GET time to get a few messages. + std::this_thread::sleep_for(std::chrono::seconds(1)); + + { + Client cli(HOST, PORT); + cli.set_url_encode(false); + + auto res = cli.Get("/foo?a=explicitly+encoded"); + ASSERT_TRUE(res); + EXPECT_EQ(200, res->status); + // This expects it back with a space, as the `+` won't have been + // url-encoded, and server-side the params get decoded turning `+` + // into spaces. + EXPECT_EQ("explicitly encoded", res->body); + } + + svr.stop(); + thread.join(); + ASSERT_FALSE(svr.is_running()); +} + TEST(BindServerTest, BindDualStack) { Server svr;