aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2024-02-23 18:50:28 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2024-02-26 16:38:49 +0300
commita1ea72d719b63a4d2b6421ce2e53b7e3ab12a8a1 (patch)
tree8c5e9e1c044586cee0cc16dd66e78f70b4d33c3f
parent14049ee7c5880b9e33a3e295d19ed6b36edab567 (diff)
Add curl constructors which allow to adjust curl command line
-rw-r--r--libbutl/curl.cxx9
-rw-r--r--libbutl/curl.hxx52
-rw-r--r--libbutl/curl.ixx73
-rw-r--r--libbutl/curl.txx8
-rw-r--r--libbutl/semantic-version.hxx8
-rw-r--r--libbutl/semantic-version.ixx24
-rw-r--r--tests/curl/driver.cxx13
-rw-r--r--tests/curl/testscript10
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
}