diff options
-rw-r--r-- | libbutl/curl.cxx | 9 | ||||
-rw-r--r-- | libbutl/curl.hxx | 52 | ||||
-rw-r--r-- | libbutl/curl.ixx | 73 | ||||
-rw-r--r-- | libbutl/curl.txx | 8 | ||||
-rw-r--r-- | libbutl/semantic-version.hxx | 8 | ||||
-rw-r--r-- | libbutl/semantic-version.ixx | 24 | ||||
-rw-r--r-- | tests/curl/driver.cxx | 13 | ||||
-rw-r--r-- | tests/curl/testscript | 10 |
8 files changed, 170 insertions, 27 deletions
diff --git a/libbutl/curl.cxx b/libbutl/curl.cxx index 0577391..7efd28d 100644 --- a/libbutl/curl.cxx +++ b/libbutl/curl.cxx @@ -142,7 +142,7 @@ namespace butl } curl::method_proto curl:: - translate (method_type m, const string& u, method_proto_options& o) + translate (method_type m, const string& u, method_proto_options& o, flags fs) { size_t n (u.find ("://")); @@ -161,8 +161,11 @@ namespace butl } else if (icasecmp (u, "http", n) == 0 || icasecmp (u, "https", n) == 0) { - o.push_back ("--fail"); // Fail on HTTP errors (e.g., 404). - o.push_back ("--location"); // Follow redirects. + if ((fs & flags::no_fail) == flags::none) + o.push_back ("--fail"); // Fail on HTTP errors (e.g., 404). + + if ((fs & flags::no_location) == flags::none) + o.push_back ("--location"); // Follow redirects. switch (m) { diff --git a/libbutl/curl.hxx b/libbutl/curl.hxx index 3fa7890..ea91807 100644 --- a/libbutl/curl.hxx +++ b/libbutl/curl.hxx @@ -91,6 +91,19 @@ namespace butl public: enum method_type {get, put, post}; + // By default the -sS and, for the HTTP protocol, --fail and --location + // options are passed to curl on the command line. Optionally, these + // options can be suppressed. + // + enum class flags: std::uint16_t + { + no_fail = 0x01, // Don't pass --fail. + no_location = 0x02, // Don't pass --location + no_sS = 0x04, // Don't pass -sS + + none = 0 // Default options set. + }; + ifdstream in; ofdstream out; @@ -121,6 +134,35 @@ namespace butl const std::string& url, A&&... options); + // Similar to the above, but allows to adjust the curl's default command + // line. + // + template <typename I, + typename O, + typename E, + typename... A> + curl (I&& in, + O&& out, + E&& err, + method_type, + flags, + const std::string& url, + A&&... options); + + template <typename C, + typename I, + typename O, + typename E, + typename... A> + curl (const C&, + I&& in, + O&& out, + E&& err, + method_type, + flags, + const std::string& url, + A&&... options); + // Read the HTTP response status from an input stream. // // Specifically, read and parse the HTTP status line, by default skip over @@ -159,7 +201,10 @@ namespace butl using method_proto_options = small_vector<const char*, 2>; method_proto - translate (method_type, const std::string& url, method_proto_options&); + translate (method_type, + const std::string& url, + method_proto_options&, + flags); private: template <typename T> @@ -199,6 +244,11 @@ namespace butl typename std::enable_if<is_other<O>::value, O>::type map_out (O&&, method_proto, io_data&); }; + + curl::flags operator& (curl::flags, curl::flags); + curl::flags operator| (curl::flags, curl::flags); + curl::flags operator&= (curl::flags&, curl::flags); + curl::flags operator|= (curl::flags&, curl::flags); } #include <libbutl/curl.ixx> diff --git a/libbutl/curl.ixx b/libbutl/curl.ixx index b7f6496..6dcfe13 100644 --- a/libbutl/curl.ixx +++ b/libbutl/curl.ixx @@ -16,6 +16,7 @@ namespace butl O&& out, E&& err, method_type m, + flags fs, const std::string& url, A&&... options) : curl ([] (const char* [], std::size_t) {}, @@ -23,8 +24,80 @@ namespace butl std::forward<O> (out), std::forward<E> (err), m, + fs, url, std::forward<A> (options)...) { } + + template <typename C, + typename I, + typename O, + typename E, + typename... A> + inline curl:: + curl (const C& cmdc, + I&& in, + O&& out, + E&& err, + method_type m, + const std::string& url, + A&&... options) + : curl (cmdc, + std::forward<I> (in), + std::forward<O> (out), + std::forward<E> (err), + m, + flags::none, + url, + std::forward<A> (options)...) + { + } + + template <typename I, + typename O, + typename E, + typename... A> + inline curl:: + curl (I&& in, + O&& out, + E&& err, + method_type m, + const std::string& url, + A&&... options) + : curl (std::forward<I> (in), + std::forward<O> (out), + std::forward<E> (err), + m, + flags::none, + url, + std::forward<A> (options)...) + { + } + + inline curl::flags + operator&= (curl::flags& x, curl::flags y) + { + return x = static_cast<curl::flags> (static_cast<std::uint16_t> (x) & + static_cast<std::uint16_t> (y)); + } + + inline curl::flags + operator|= (curl::flags& x, curl::flags y) + { + return x = static_cast<curl::flags> (static_cast<std::uint16_t> (x) | + static_cast<std::uint16_t> (y)); + } + + inline curl::flags + operator& (curl::flags x, curl::flags y) + { + return x &= y; + } + + inline curl::flags + operator| (curl::flags x, curl::flags y) + { + return x |= y; + } } diff --git a/libbutl/curl.txx b/libbutl/curl.txx index ee08145..fc74470 100644 --- a/libbutl/curl.txx +++ b/libbutl/curl.txx @@ -65,11 +65,12 @@ namespace butl O&& out, E&& err, method_type m, + flags fs, const std::string& url, A&&... options) { method_proto_options mpo; - method_proto mp (translate (m, url, mpo)); + method_proto mp (translate (m, url, mpo, fs)); io_data in_data; io_data out_data; @@ -81,8 +82,9 @@ namespace butl map_out (std::forward<O> (out), mp, out_data), std::forward<E> (err), "curl", - "-s", // Silent. - "-S", // But do show diagnostics. + ((fs & flags::no_sS) == flags::none + ? "-sS" // Silent but do show diagnostics. + : nullptr), mpo, in_data.options, out_data.options, diff --git a/libbutl/semantic-version.hxx b/libbutl/semantic-version.hxx index 1dc7d1d..4eba38a 100644 --- a/libbutl/semantic-version.hxx +++ b/libbutl/semantic-version.hxx @@ -177,16 +177,16 @@ namespace butl return o << x.string (); } - inline semantic_version::flags + semantic_version::flags operator& (semantic_version::flags, semantic_version::flags); - inline semantic_version::flags + semantic_version::flags operator| (semantic_version::flags, semantic_version::flags); - inline semantic_version::flags + semantic_version::flags operator&= (semantic_version::flags&, semantic_version::flags); - inline semantic_version::flags + semantic_version::flags operator|= (semantic_version::flags&, semantic_version::flags); } diff --git a/libbutl/semantic-version.ixx b/libbutl/semantic-version.ixx index 67cd8c0..8de1554 100644 --- a/libbutl/semantic-version.ixx +++ b/libbutl/semantic-version.ixx @@ -51,18 +51,6 @@ namespace butl } inline semantic_version::flags - operator& (semantic_version::flags x, semantic_version::flags y) - { - return x &= y; - } - - inline semantic_version::flags - operator| (semantic_version::flags x, semantic_version::flags y) - { - return x |= y; - } - - inline semantic_version::flags operator&= (semantic_version::flags& x, semantic_version::flags y) { return x = static_cast<semantic_version::flags> ( @@ -77,4 +65,16 @@ namespace butl static_cast<std::uint16_t> (x) | static_cast<std::uint16_t> (y)); } + + inline semantic_version::flags + operator& (semantic_version::flags x, semantic_version::flags y) + { + return x &= y; + } + + inline semantic_version::flags + operator| (semantic_version::flags x, semantic_version::flags y) + { + return x |= y; + } } diff --git a/tests/curl/driver.cxx b/tests/curl/driver.cxx index 4cf1815..bd12c29 100644 --- a/tests/curl/driver.cxx +++ b/tests/curl/driver.cxx @@ -105,6 +105,19 @@ http () assert (!c.wait ()); } + // POST from stream without --fail. + // + { + curl c (p, path ("-"), nullfd, 2, + curl::post, + curl::flags::no_fail, + u + "/bogus"); + + c.out << "bogus" << endl; + c.out.close (); + assert (c.wait ()); + } + // POST from /dev/null. // { diff --git a/tests/curl/testscript b/tests/curl/testscript index d26a39c..5818d1a 100644 --- a/tests/curl/testscript +++ b/tests/curl/testscript @@ -45,15 +45,17 @@ sudo /usr/sbin/in.tftpd \ { $* 'http' 2>>~%EOE% - curl -s -S --fail --location https://build2.org/bogus + curl -sS --fail --location https://build2.org/bogus %curl: \(22\) The requested URL returned error: 404( Not Found)?% - curl -s -S --fail --location https://build2.org + curl -sS --fail --location https://build2.org - curl -s -S --fail --location --data-binary @- https://build2.org/bogus + curl -sS --fail --location --data-binary @- https://build2.org/bogus %curl: \(22\) The requested URL returned error: 404( Not Found)?% - curl -s -S --fail --location https://build2.org/bogus + curl -sS --location --data-binary @- https://build2.org/bogus + + curl -sS --fail --location https://build2.org/bogus %curl: \(22\) The requested URL returned error: 404( Not Found)?% EOE } |