From 693c12d40bb51eb3a8029aba1a9c7248c081a44c Mon Sep 17 00:00:00 2001 From: C1-BA-B1-F3 Date: Sat, 3 Oct 2026 16:22:44 +0800 Subject: [PATCH 1/2] fix(http): use b64encode with explicit encode/decode for Python 3 base64.encodestring was removed in Python 3.9 and expected a str in Python 3 (raising TypeError: expected bytes-like object, not str). Use base64.b64encode with explicit UTF-8 encode/decode, which works on all Python 3 versions. Fixes #130 --- stetl/inputs/httpinput.py | 3 ++- stetl/outputs/httpoutput.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/stetl/inputs/httpinput.py b/stetl/inputs/httpinput.py index 90998af..b15be9e 100644 --- a/stetl/inputs/httpinput.py +++ b/stetl/inputs/httpinput.py @@ -113,7 +113,8 @@ def add_authorization(self, request): # Basic auth: http://mozgovipc.blogspot.nl/2012/06/python-http-basic-authentication-with.html # base64 encode username and password # write the Authorization header like: 'Basic base64encode(username + ':' + password) - auth_val = base64.encodestring('%s:%s' % (auth_creds['user'], auth_creds['password'])) + creds = '%s:%s' % (auth_creds['user'], auth_creds['password']) + auth_val = base64.b64encode(creds.encode('utf-8')).decode('utf-8') auth_val = "Basic %s" % auth_val elif auth_type == 'token': # Bearer Type, see eg. https://tools.ietf.org/html/rfc6750 diff --git a/stetl/outputs/httpoutput.py b/stetl/outputs/httpoutput.py index 03fafc4..ab8370f 100644 --- a/stetl/outputs/httpoutput.py +++ b/stetl/outputs/httpoutput.py @@ -107,8 +107,9 @@ def post(self, packet, payload): # basic auth: http://mozgovipc.blogspot.nl/2012/06/python-http-basic-authentication-with.html # base64 encode the username and password # write the Authorization header like: 'Basic base64encode(username + ':' + password) - if self.user is not None: - auth = base64.encodestring('%s:%s' % (self.user, self.password)).replace('\n', '') + if self.user is not None and self.password is not None: + creds = '%s:%s' % (self.user, self.password) + auth = base64.b64encode(creds.encode('utf-8')).decode('utf-8') webservice.putheader("Authorization", "Basic %s" % auth) webservice.endheaders() From 739d76cfd51d14cdda66a5d3996152954b802a83 Mon Sep 17 00:00:00 2001 From: C1-BA-B1-F3 Date: Sat, 3 Oct 2026 16:37:25 +0800 Subject: [PATCH 2/2] fix(etl): replace str.format with regex to avoid brace conflicts Config argument substitution used str.format(), which interprets any {} in the config string as a format placeholder. Config values like converter_args that contain dict literals (e.g. {'root_tag': ...}) triggered KeyError on the dict keys. Use a regex that only replaces {argname} placeholders, leaving literal braces untouched. Fixes #124 --- stetl/etl.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/stetl/etl.py b/stetl/etl.py index 33ce334..61ad287 100755 --- a/stetl/etl.py +++ b/stetl/etl.py @@ -86,9 +86,15 @@ def __init__(self, options_dict, args_dict=None): if args_dict: log.info("Substituting %d args in config file from args_dict: %s" % (len(args_names), str(args_names))) - # Do replacements see http://docs.python.org/2/library/string.html#formatstrings - # and render substituted config string - config_str = config_str.format(**args_dict) + # Do replacements. Use regex instead of str.format so that + # literal braces in config values (e.g. converter_args dicts) + # are not mistaken for format placeholders. + for key, value in args_dict.items(): + config_str = re.sub( + r'\{%s\}' % re.escape(key), + str(value), + config_str + ) log.info("Substituting args OK")