From c250082a7dc0b95308d2e58d787b38c1de3c326b Mon Sep 17 00:00:00 2001 From: nik-localstack Date: Sat, 23 May 2026 13:19:36 +0300 Subject: [PATCH 1/2] Fix query encoding --- postgresql_proxy/interceptors.py | 5 +++-- tests/test_proxy.py | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/postgresql_proxy/interceptors.py b/postgresql_proxy/interceptors.py index f80f4b9..a0da61f 100644 --- a/postgresql_proxy/interceptors.py +++ b/postgresql_proxy/interceptors.py @@ -101,7 +101,8 @@ def _intercept_context_data(self, data): def _intercept_query(self, query, interceptors): logging.getLogger("intercept").debug("intercepting query\n%s", query) # Remove null terminator - query = query.rstrip(b"\x00").decode("utf-8") + codec = self.get_codec() + query = query.rstrip(b"\x00").decode(codec) for interceptor in interceptors: func = self._get_plugin_interceptor_function(interceptor) query = func(query, self.context) @@ -113,7 +114,7 @@ def _intercept_query(self, query, interceptors): ) # Append the zero byte at the end - return query.encode("utf-8") + b"\x00" + return query.encode(codec) + b"\x00" class ResponseInterceptor(Interceptor): diff --git a/tests/test_proxy.py b/tests/test_proxy.py index f83f958..b934fdf 100644 --- a/tests/test_proxy.py +++ b/tests/test_proxy.py @@ -441,3 +441,26 @@ def test_extended_query_protocol_named_prepared_statement_passes_through_proxy( ) prepared_count = cur.fetchone() assert prepared_count is not None and prepared_count[0] >= 1 + + +def test_non_utf8_client_encoding_query_text_through_proxy( + postgres_settings, plain_proxy_port +): + """Proxy query interception should honor client_encoding when decoding query text.""" + with psycopg2.connect( + host="127.0.0.1", + port=plain_proxy_port, + user=postgres_settings["user"], + password=postgres_settings["password"], + dbname=postgres_settings["dbname"], + sslmode="disable", + connect_timeout=3, + client_encoding="LATIN1", + ) as conn: + conn.autocommit = True + with conn.cursor() as cur: + cur.execute("SHOW client_encoding") + assert cur.fetchone() == ("LATIN1",) + + cur.execute("SELECT 'olá'::text") + assert cur.fetchone() == ("olá",) From 3d83aec5d192ee3236400181932ed9807d492725 Mon Sep 17 00:00:00 2001 From: nik-localstack Date: Wed, 27 May 2026 10:33:25 +0300 Subject: [PATCH 2/2] chore: bump version to 0.3.3 and update changelog Co-Authored-By: Claude Sonnet 4.6 --- README.md | 4 ++++ setup.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c8bf70d..297352d 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,10 @@ Or run it without activating the venv: ``` ## Changelog +- v0.3.3 + - Fix query encoding: honor `client_encoding` instead of assuming UTF-8 [#19](https://github.com/localstack/postgresql-proxy/pull/19) + - Fix EQP Parse packet corruption with high-byte OIDs (e.g. jsonb) causing `UnicodeDecodeError` [#18](https://github.com/localstack/postgresql-proxy/pull/18) + - Improve SSL resilience under fragmented TCP delivery [#20](https://github.com/localstack/postgresql-proxy/pull/20) - v0.3.2 - Fix proxy hang on large responses by adding backpressure handling [#16](https://github.com/localstack/postgresql-proxy/pull/16) - Reduce SSL connection overhead by setting `TCP_NODELAY` [#15](https://github.com/localstack/postgresql-proxy/pull/15) diff --git a/setup.py b/setup.py index cc24be8..2221783 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ if __name__ == "__main__": setup( name="postgresql-proxy", - version="0.3.2", + version="0.3.3", description="Postgresql Proxy", packages=find_packages(exclude=("tests", "tests.*")), install_requires=install_requires,