From a49486bffc401f74009037b49fb7feb420c92452 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Mon, 4 Feb 2013 23:29:01 +0100 Subject: [PATCH] curl* plugins: Added support for POST and arbitrary headers These plugins can now be used for things like SOAP or XML-RPC calls. Signed-off-by: Florian Forster --- 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 7626a463..e85ac1d4 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 and are checked by default depends on the distribution you use. +=item B
I
+ +A HTTP header to add to the request. Multiple headers are added if this option +is specified more than once. + +=item B I + +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
option to set an appropriate +C for the post body (e.g. to +C). + =item B B|B Measure response time for the request. If this setting is enabled, B @@ -1002,31 +1015,15 @@ The following options are valid within B blocks: Sets the plugin instance to I. =item B I - -Username to use if authorization is required to read the page. - =item B I - -Password to use if authorization is required to read the page. - =item B B|B - -Enable or disable peer SSL certificate verification. See -L for details. Enabled by default. - =item B B|B - -Enable or disable peer host name verification. If enabled, the plugin checks if -the C or a C field of the SSL certificate -matches the host name provided by the B 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 I +=item B
I
+=item B I -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 -and are checked by default depends on the distribution you use. +These options behave exactly equivalent to the appropriate options of the +I plugin. Please see there for a detailed description. =back @@ -1100,9 +1097,11 @@ empty string (no plugin instance). =item B B|B =item B B|B =item B I +=item B
I
+=item B I These options behave exactly equivalent to the appropriate options of the -I and I plugins. Please see there for a detailed description. +I plugin. Please see there for a detailed description. =item EB IE diff --git a/src/curl.c b/src/curl.c index 32ba7452..c6e2ae9c 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 19efc5d6..deee460b 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]; @@ -367,6 +369,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 */ @@ -378,6 +382,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) { @@ -547,6 +567,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 */ @@ -608,6 +632,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 75f5cc33..fc02859e 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) @@ -769,6 +789,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 */ @@ -832,6 +856,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); -- 2.30.2