From 4940f1228a25434876bd93e542fe4e42fdee5397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henryk=20Pl=C3=B6tz?= Date: Thu, 28 Mar 2024 09:40:38 +0100 Subject: [PATCH] Add configuration and code to opt-in to reduced logging. (#117) Currently this strips all the boilerplate prefix and suffix from the packet dump in FinTSHTTPSConnection.send(), only showing the net payload. --- fints/connection.py | 25 ++++++++++++++++++++----- fints/utils.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/fints/connection.py b/fints/connection.py index d0530b9..c01bb03 100644 --- a/fints/connection.py +++ b/fints/connection.py @@ -3,14 +3,27 @@ import logging import requests -from fints.utils import Password +from fints.utils import Password, log_configuration from .exceptions import * from .message import FinTSInstituteMessage, FinTSMessage +from .types import SegmentSequence logger = logging.getLogger(__name__) +def reduce_message_for_log(msg): + log_msg = msg + if log_configuration.reduced: + # Try to find a single inner message + if len(log_msg.segments) == 4 and log_msg.segments[2].header.type == 'HNVSD': + log_msg = log_msg.segments[2] + if len(log_msg.data.segments) > 2 and log_msg.data.segments[0].header.type == "HNSHK" and \ + log_msg.data.segments[-1].header.type == "HNSHA": + log_msg = SegmentSequence(segments=log_msg.data.segments[1:-1]) + return log_msg + + class FinTSHTTPSConnection: def __init__(self, url): self.url = url @@ -19,8 +32,9 @@ def __init__(self, url): def send(self, msg: FinTSMessage): log_out = io.StringIO() with Password.protect(): - msg.print_nested(stream=log_out, prefix="\t") - logger.debug("Sending >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n{}\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n".format(log_out.getvalue())) + log_msg = reduce_message_for_log(msg) + log_msg.print_nested(stream=log_out, prefix="\t") + logger.debug("Sending {}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n{}\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n".format("(abbrv.)" if log_configuration.reduced else "", log_out.getvalue())) log_out.truncate(0) r = self.session.post( @@ -37,6 +51,7 @@ def send(self, msg: FinTSMessage): retval = FinTSInstituteMessage(segments=response) with Password.protect(): - retval.print_nested(stream=log_out, prefix="\t") - logger.debug("Received <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n{}\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n".format(log_out.getvalue())) + log_msg = reduce_message_for_log(retval) + log_msg.print_nested(stream=log_out, prefix="\t") + logger.debug("Received {}<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n{}\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n".format("(abbrv.)" if log_configuration.reduced else "", log_out.getvalue())) return retval diff --git a/fints/utils.py b/fints/utils.py index 6d63fe2..fa408d6 100644 --- a/fints/utils.py +++ b/fints/utils.py @@ -2,6 +2,7 @@ import inspect import json import re +import threading import zlib from contextlib import contextmanager from datetime import datetime @@ -308,3 +309,30 @@ def minimal_interactive_cli_bootstrap(client): p=mm)) choice = input("Choice: ").strip() client.set_tan_medium(m[1][int(choice)]) + + +class LogConfiguration(threading.local): + """Thread-local configuration object to guide log output. + + reduced: Reduce verbosity of logging output by suppressing the encrypting/signature elements and outputting the payload only. + """ + def __init__(self, reduced=False): + super().__init__() + self.reduced = reduced + + @staticmethod + def set(reduced=False): + """Permanently change the log configuration for this thread.""" + log_configuration.reduced = reduced + + @staticmethod + @contextmanager + def changed(reduced=False): + """Temporarily change the log configuration for this thread.""" + old_reduced = log_configuration.reduced + log_configuration.set(reduced=reduced) + yield + log_configuration.set(reduced=old_reduced) + + +log_configuration = LogConfiguration()