diff mbox series

channel_curl: Add ability to define a set of custom HTTP headers

Message ID 20210902100444.3702590-1-sava.jakovljev@teufel.de
State Changes Requested
Headers show
Series channel_curl: Add ability to define a set of custom HTTP headers | expand

Commit Message

Sava Jakovljev Sept. 2, 2021, 10:04 a.m. UTC
* Expand Suricatta/Hawkbit client with ability to define a custom set of
  HTTP requests, defined through command line or configuration file,
  using 'a' short option or "custom-http-header" long option.

Signed-off-by: Sava Jakovljev <sava.jakovljev@teufel.de>
---
 corelib/channel_curl.c     |  8 +++++---
 doc/source/swupdate.rst    |  7 +++++--
 include/channel_curl.h     |  3 ++-
 suricatta/server_general.c |  2 +-
 suricatta/server_hawkbit.c | 32 +++++++++++++++++++++++++++++---
 suricatta/server_hawkbit.h |  1 +
 6 files changed, 43 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/corelib/channel_curl.c b/corelib/channel_curl.c
index e910f76..3d7cba5 100644
--- a/corelib/channel_curl.c
+++ b/corelib/channel_curl.c
@@ -585,7 +585,7 @@  channel_op_res_t channel_set_options(channel_t *this, channel_data_t *channel_da
 		goto cleanup;
 	}
 
-	if (channel_data->headers) {
+	if (channel_data->received_headers) {
 		/*
 		 * Setup supply request and receive reply HTTP headers.
 		 * A LIST_INIT()'d dictionary is expected at channel_data->headers.
@@ -596,14 +596,16 @@  channel_op_res_t channel_set_options(channel_t *this, channel_data_t *channel_da
 			      CURLOPT_HEADERFUNCTION,
 			      channel_callback_headers) != CURLE_OK) ||
 		    (curl_easy_setopt(channel_curl->handle, CURLOPT_HEADERDATA,
-			      channel_data->headers) != CURLE_OK)) {
+			      channel_data->received_headers) != CURLE_OK)) {
 			result = CHANNEL_EINIT;
 			goto cleanup;
 		}
+	}
 
+	if (channel_data->user_headers) {
 		struct dict_entry *entry;
 		char *header;
-		LIST_FOREACH(entry, channel_data->headers, next)
+		LIST_FOREACH(entry, channel_data->user_headers, next)
 		{
 			if (ENOMEM_ASPRINTF ==
 			    asprintf(&header, "%s: %s",
diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst
index 317c54d..8b4f7af 100644
--- a/doc/source/swupdate.rst
+++ b/doc/source/swupdate.rst
@@ -184,7 +184,7 @@  Images fully streamed
 ---------------------
 
 In case of remote update, SWUpdate extracts relevant images from the stream
-and copies them into the directory pointed to by the environment variable 
+and copies them into the directory pointed to by the environment variable
 ``TMPDIR`` (if unset, to ``/tmp``) before calling the handlers.
 This guarantee that an update is initiated only if all parts are present and
 correct. However, on some systems with less resources, the amount of RAM
@@ -652,6 +652,9 @@  Mandatory arguments are marked with '\*':
 |                         |          | during this period - adapt this value to   |
 |                         |          | your use case!                             |
 +-------------------------+----------+--------------------------------------------+
+| -a <name> <value>       | strings  | Custom HTTP header with given value to be  |
+|						  |			 | send on every HTTP request made.			  |
++-------------------------+----------+--------------------------------------------+
 
 
 systemd Integration
@@ -706,7 +709,7 @@  files are also handed over on a "regular" start of SWUpdate via
 ``systemctl start swupdate.service``.
 
 Note that the socket paths in the two ``ListenStream=`` directives
-have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and 
+have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and
 ``CONFIG_SOCKET_PROGRESS_PATH`` in SWUpdate's configuration.
 Here, the default socket path configuration is depicted.
 
diff --git a/include/channel_curl.h b/include/channel_curl.h
index 4de098e..4e69eeb 100644
--- a/include/channel_curl.h
+++ b/include/channel_curl.h
@@ -72,5 +72,6 @@  typedef struct {
 	struct swupdate_digest *dgst;
 	char sha1hash[SWUPDATE_SHA_DIGEST_LENGTH * 2 + 1];
 	sourcetype source;
-	struct dict *headers;
+	struct dict *user_headers;
+	struct dict *received_headers;
 } channel_data_t;
diff --git a/suricatta/server_general.c b/suricatta/server_general.c
index 1d11ada..5062745 100644
--- a/suricatta/server_general.c
+++ b/suricatta/server_general.c
@@ -454,7 +454,7 @@  static server_op_res_t server_get_deployment_info(channel_t *channel, channel_da
 	channel_data->url= server_prepare_query(server_general.url, &server_general.configdata);
 
 	LIST_INIT(&server_general.httpheaders);
-	channel_data->headers = &server_general.httpheaders;
+	channel_data->received_headers = &server_general.httpheaders;
 
 	result = map_http_retcode(channel->get(channel, (void *)channel_data));
 
diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c
index 33d2eec..62431af 100644
--- a/suricatta/server_hawkbit.c
+++ b/suricatta/server_hawkbit.c
@@ -52,6 +52,7 @@  static struct option long_options[] = {
     {"cache", required_argument, NULL, '2'},
     {"initial-report-resend-period", required_argument, NULL, 'm'},
 	{"connection-timeout", required_argument, NULL, 's'},
+	{"custom-http-header", required_argument, NULL, 'a'},
     {NULL, 0, NULL, 0}};
 
 static unsigned short mandatory_argument_count = 0;
@@ -132,7 +133,9 @@  static channel_data_t channel_data_defaults = {.debug = false,
 					       .nocheckanswer = false,
 					       .nofollow = false,
 					       .strictssl = true,
-						   .connection_timeout = 0
+						   .connection_timeout = 0,
+						   .user_headers = NULL,
+						   .received_headers = NULL
 						};
 
 static struct timeval server_time;
@@ -1602,7 +1605,9 @@  void server_print_help(void)
 	    "\t  --cache <file>      Use cache file as starting SWU\n"
 		"\t  -m, --initial-report-resend-period <seconds> Time to wait prior to retry "
 		"sending initial state with '-c' option (default: %ds).\n"
-		"\t  -s, --connection-timeout Set the server connection timeout (default: 300s).\n",
+		"\t  -s, --connection-timeout Set the server connection timeout (default: 300s).\n"
+		"\t  -a, --custom-http-header <name> <value> Set custom HTTP header, "
+		"appended to every HTTP request being sent.",
 	    CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES,
 	    CHANNEL_DEFAULT_RESUME_DELAY,
 	    INITIAL_STATUS_REPORT_WAIT_DELAY);
@@ -1661,6 +1666,7 @@  server_op_res_t server_start(char *fname, int argc, char *argv[])
 	mandatory_argument_count = 0;
 
 	LIST_INIT(&server_hawkbit.configdata);
+	LIST_INIT(&server_hawkbit.httpheaders);
 
 	server_hawkbit.initial_report_resend_period = INITIAL_STATUS_REPORT_WAIT_DELAY;
 	if (fname) {
@@ -1677,6 +1683,9 @@  server_op_res_t server_start(char *fname, int argc, char *argv[])
 			 */
 			read_module_settings(&handle, "hawkbit", server_hawkbit_settings, NULL);
 			read_module_settings(&handle, "identify", settings_into_dict, &server_hawkbit.configdata);
+
+			read_module_settings(&handle, "custom-http-headers",
+					settings_into_dict, &server_hawkbit.httpheaders);
 		}
 		swupdate_cfg_destroy(&handle);
 	}
@@ -1689,7 +1698,7 @@  server_op_res_t server_start(char *fname, int argc, char *argv[])
 	/* reset to optind=1 to parse suricatta's argument vector */
 	optind = 1;
 	opterr = 0;
-	while ((choice = getopt_long(argc, argv, "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:",
+	while ((choice = getopt_long(argc, argv, "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:a:",
 				     long_options, NULL)) != -1) {
 		switch (choice) {
 		case 't':
@@ -1782,6 +1791,21 @@  server_op_res_t server_start(char *fname, int argc, char *argv[])
 			channel_data_defaults.connection_timeout =
 				(unsigned int)strtoul(optarg, NULL, 10);
 			break;
+		case 'a':
+			if (optind >= argc)
+				return SERVER_EINIT;
+
+			char *name = NULL;
+			SETSTRING(name, optarg);
+			char *value = NULL;
+			SETSTRING(value, argv[optind++]);
+
+			if (dict_insert_value(&server_hawkbit.httpheaders,
+						name,
+						value) < 0)
+				return SERVER_EINIT;
+
+			break;
 		/* Ignore not recognized options, they can be already parsed by the caller */
 		case '?':
 			break;
@@ -1799,6 +1823,8 @@  server_op_res_t server_start(char *fname, int argc, char *argv[])
 		return SERVER_EINIT;
 	}
 
+	channel_data_defaults.user_headers = &server_hawkbit.httpheaders;
+
 	if (channel_curl_init() != CHANNEL_OK)
 		return SERVER_EINIT;
 
diff --git a/suricatta/server_hawkbit.h b/suricatta/server_hawkbit.h
index aea4bb0..67f1c31 100644
--- a/suricatta/server_hawkbit.h
+++ b/suricatta/server_hawkbit.h
@@ -29,6 +29,7 @@  typedef struct {
 	bool polling_interval_from_server;
 	bool debug;
 	struct dict configdata;
+	struct dict httpheaders;
 	bool has_to_send_configData;
 	char *configData_url;
 	char *cancel_url;