[collectd] [PATCH] curl* plugins: Added support for POST and arbitrary headers
Dan Fandrich
dan at coneharvesters.com
Mon Feb 4 23:29:01 CET 2013
These plugins can now be used for things like SOAP or XML-RPC calls.
---
src/collectd.conf.pod | 41 ++++++++++++++++++++---------------------
src/curl.c | 29 +++++++++++++++++++++++++++++
src/curl_json.c | 28 ++++++++++++++++++++++++++++
src/curl_xml.c | 28 ++++++++++++++++++++++++++++
4 files changed, 105 insertions(+), 21 deletions(-)
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 70bc997..e70caad 100644
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
@@ -944,6 +944,19 @@ File that holds one or more SSL certificates. If you want to use HTTPS you will
possibly need this option. What CA certificates come bundled with C<libcurl>
and are checked by default depends on the distribution you use.
+=item B<Header> I<Header>
+
+A HTTP header to add to the request. Multiple headers are added if this option
+is specified more than once.
+
+=item B<Post> I<Body>
+
+Specifies that the HTTP operation should be a POST instead of a GET. The
+complete data to be posted is given as the argument. This option will usually
+need to be accompanied by a B<Header> option to set an appropriate
+C<Content-Type> for the post body (e.g. to
+C<application/x-www-form-urlencoded>).
+
=item B<MeasureResponseTime> B<true>|B<false>
Measure response time for the request. If this setting is enabled, B<Match>
@@ -1002,31 +1015,15 @@ The following options are valid within B<URL> blocks:
Sets the plugin instance to I<Instance>.
=item B<User> I<Name>
-
-Username to use if authorization is required to read the page.
-
=item B<Password> I<Password>
-
-Password to use if authorization is required to read the page.
-
=item B<VerifyPeer> B<true>|B<false>
-
-Enable or disable peer SSL certificate verification. See
-L<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
-
=item B<VerifyHost> B<true>|B<false>
-
-Enable or disable peer host name verification. If enabled, the plugin checks if
-the C<Common Name> or a C<Subject Alternate Name> field of the SSL certificate
-matches the host name provided by the B<URL> option. If this identity check
-fails, the connection is aborted. Obviously, only works when connecting to a
-SSL enabled server. Enabled by default.
-
=item B<CACert> I<file>
+=item B<Header> I<Header>
+=item B<Post> I<Body>
-File that holds one or more SSL certificates. If you want to use HTTPS you will
-possibly need this option. What CA certificates come bundled with C<libcurl>
-and are checked by default depends on the distribution you use.
+These options behave exactly equivalent to the appropriate options of the
+I<cURL> plugin. Please see there for a detailed description.
=back
@@ -1100,9 +1097,11 @@ empty string (no plugin instance).
=item B<VerifyPeer> B<true>|B<false>
=item B<VerifyHost> B<true>|B<false>
=item B<CACert> I<CA Cert File>
+=item B<Header> I<Header>
+=item B<Post> I<Body>
These options behave exactly equivalent to the appropriate options of the
-I<cURL> and I<cURL-JSON> plugins. Please see there for a detailed description.
+I<cURL> plugin. Please see there for a detailed description.
=item E<lt>B<XPath> I<XPath-expression>E<gt>
diff --git a/src/curl.c b/src/curl.c
index 30d6e45..cb352bf 100644
--- a/src/curl.c
+++ b/src/curl.c
@@ -60,6 +60,8 @@ struct web_page_s /* {{{ */
int verify_peer;
int verify_host;
char *cacert;
+ struct curl_slist *headers;
+ char *post_body;
int response_time;
CURL *curl;
@@ -148,6 +150,8 @@ static void cc_web_page_free (web_page_t *wp) /* {{{ */
sfree (wp->pass);
sfree (wp->credentials);
sfree (wp->cacert);
+ sfree (wp->post_body);
+ curl_slist_free_all (wp->headers);
sfree (wp->buffer);
@@ -173,6 +177,23 @@ static int cc_config_add_string (const char *name, char **dest, /* {{{ */
return (0);
} /* }}} int cc_config_add_string */
+static int cc_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
+ oconfig_item_t *ci)
+{
+ if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("curl plugin: `%s' needs exactly one string argument.", name);
+ return (-1);
+ }
+
+ *dest = curl_slist_append(*dest, ci->values[0].value.string);
+ if (*dest == NULL)
+ return (-1);
+
+ return (0);
+} /* }}} int cc_config_append_string */
+
+
static int cc_config_set_boolean (const char *name, int *dest, /* {{{ */
oconfig_item_t *ci)
{
@@ -405,6 +426,10 @@ static int cc_page_init_curl (web_page_t *wp) /* {{{ */
wp->verify_host ? 2L : 0L);
if (wp->cacert != NULL)
curl_easy_setopt (wp->curl, CURLOPT_CAINFO, wp->cacert);
+ if (wp->headers != NULL)
+ curl_easy_setopt (wp->curl, CURLOPT_HTTPHEADER, wp->headers);
+ if (wp->post_body != NULL)
+ curl_easy_setopt (wp->curl, CURLOPT_POSTFIELDS, wp->post_body);
return (0);
} /* }}} int cc_page_init_curl */
@@ -466,6 +491,10 @@ static int cc_config_add_page (oconfig_item_t *ci) /* {{{ */
else if (strcasecmp ("Match", child->key) == 0)
/* Be liberal with failing matches => don't set `status'. */
cc_config_add_match (page, child);
+ else if (strcasecmp ("Header", child->key) == 0)
+ status = cc_config_append_string ("Header", &page->headers, child);
+ else if (strcasecmp ("Post", child->key) == 0)
+ status = cc_config_add_string ("Post", &page->post_body, child);
else
{
WARNING ("curl plugin: Option `%s' not allowed here.", child->key);
diff --git a/src/curl_json.c b/src/curl_json.c
index 2ddaff3..1494327 100644
--- a/src/curl_json.c
+++ b/src/curl_json.c
@@ -67,6 +67,8 @@ struct cj_s /* {{{ */
_Bool verify_peer;
_Bool verify_host;
char *cacert;
+ struct curl_slist *headers;
+ char *post_body;
CURL *curl;
char curl_errbuf[CURL_ERROR_SIZE];
@@ -374,6 +376,8 @@ static void cj_free (void *arg) /* {{{ */
sfree (db->pass);
sfree (db->credentials);
sfree (db->cacert);
+ sfree (db->post_body);
+ curl_slist_free_all (db->headers);
sfree (db);
} /* }}} void cj_free */
@@ -385,6 +389,22 @@ static c_avl_tree_t *cj_avl_create(void)
return c_avl_create ((int (*) (const void *, const void *)) strcmp);
}
+static int cj_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
+ oconfig_item_t *ci)
+{
+ if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("curl_json plugin: `%s' needs exactly one string argument.", name);
+ return (-1);
+ }
+
+ *dest = curl_slist_append(*dest, ci->values[0].value.string);
+ if (*dest == NULL)
+ return (-1);
+
+ return (0);
+} /* }}} int cj_config_append_string */
+
static int cj_config_add_key (cj_t *db, /* {{{ */
oconfig_item_t *ci)
{
@@ -554,6 +574,10 @@ static int cj_init_curl (cj_t *db) /* {{{ */
db->verify_host ? 2L : 0L);
if (db->cacert != NULL)
curl_easy_setopt (db->curl, CURLOPT_CAINFO, db->cacert);
+ if (db->headers != NULL)
+ curl_easy_setopt (db->curl, CURLOPT_HTTPHEADER, db->headers);
+ if (db->post_body != NULL)
+ curl_easy_setopt (db->curl, CURLOPT_POSTFIELDS, db->post_body);
return (0);
} /* }}} int cj_init_curl */
@@ -615,6 +639,10 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
status = cf_util_get_boolean (child, &db->verify_host);
else if (strcasecmp ("CACert", child->key) == 0)
status = cf_util_get_string (child, &db->cacert);
+ else if (strcasecmp ("Header", child->key) == 0)
+ status = cj_config_append_string ("Header", &db->headers, child);
+ else if (strcasecmp ("Post", child->key) == 0)
+ status = cf_util_get_string (child, &db->post_body);
else if (strcasecmp ("Key", child->key) == 0)
status = cj_config_add_key (db, child);
else
diff --git a/src/curl_xml.c b/src/curl_xml.c
index da90d7c..2a36608 100644
--- a/src/curl_xml.c
+++ b/src/curl_xml.c
@@ -70,6 +70,8 @@ struct cx_s /* {{{ */
_Bool verify_peer;
_Bool verify_host;
char *cacert;
+ char *post_body;
+ struct curl_slist *headers;
CURL *curl;
char curl_errbuf[CURL_ERROR_SIZE];
@@ -184,10 +186,28 @@ static void cx_free (void *arg) /* {{{ */
sfree (db->pass);
sfree (db->credentials);
sfree (db->cacert);
+ sfree (db->post_body);
+ curl_slist_free_all (db->headers);
sfree (db);
} /* }}} void cx_free */
+static int cx_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
+ oconfig_item_t *ci)
+{
+ if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("curl_xml plugin: `%s' needs exactly one string argument.", name);
+ return (-1);
+ }
+
+ *dest = curl_slist_append(*dest, ci->values[0].value.string);
+ if (*dest == NULL)
+ return (-1);
+
+ return (0);
+} /* }}} int cx_config_append_string */
+
static int cx_check_type (const data_set_t *ds, cx_xpath_t *xpath) /* {{{ */
{
if (!ds)
@@ -770,6 +790,10 @@ static int cx_init_curl (cx_t *db) /* {{{ */
db->verify_host ? 2L : 0L);
if (db->cacert != NULL)
curl_easy_setopt (db->curl, CURLOPT_CAINFO, db->cacert);
+ if (db->headers != NULL)
+ curl_easy_setopt (db->curl, CURLOPT_HTTPHEADER, db->headers);
+ if (db->post_body != NULL)
+ curl_easy_setopt (db->curl, CURLOPT_POSTFIELDS, db->post_body);
return (0);
} /* }}} int cx_init_curl */
@@ -833,6 +857,10 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */
status = cf_util_get_string (child, &db->cacert);
else if (strcasecmp ("xpath", child->key) == 0)
status = cx_config_add_xpath (db, child);
+ else if (strcasecmp ("Header", child->key) == 0)
+ status = cx_config_append_string ("Header", &db->headers, child);
+ else if (strcasecmp ("Post", child->key) == 0)
+ status = cf_util_get_string (child, &db->post_body);
else
{
WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key);
--
1.7.10
More information about the collectd
mailing list