From bf99c426b0cc073c60c3be271768707b76d1bc94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20W=C3=B3jciak?= Date: Wed, 20 Nov 2024 08:41:05 +0100 Subject: [PATCH 1/4] [feature/recording-ignored-headers] --- mocket/async_mocket.py | 8 +++++++- mocket/inject.py | 2 ++ mocket/mocket.py | 5 +++++ mocket/mocketizer.py | 21 +++++++++++++++++++-- mocket/socket.py | 5 +++++ tests/test_http.py | 31 +++++++++++++++++++++++++++++++ 6 files changed, 69 insertions(+), 3 deletions(-) diff --git a/mocket/async_mocket.py b/mocket/async_mocket.py index 709d225f..274d1fb3 100644 --- a/mocket/async_mocket.py +++ b/mocket/async_mocket.py @@ -7,11 +7,17 @@ async def wrapper( truesocket_recording_dir=None, strict_mode=False, strict_mode_allowed=None, + recording_ignored_headers: list[str] | None = None, *args, **kwargs, ): async with Mocketizer.factory( - test, truesocket_recording_dir, strict_mode, strict_mode_allowed, args + test, + truesocket_recording_dir, + strict_mode, + strict_mode_allowed, + recording_ignored_headers, + args, ): return await test(*args, **kwargs) diff --git a/mocket/inject.py b/mocket/inject.py index cba0b40b..073cd9b7 100644 --- a/mocket/inject.py +++ b/mocket/inject.py @@ -41,6 +41,7 @@ def enable( namespace: str | None = None, truesocket_recording_dir: str | None = None, + recording_ignored_headers: list[str] | None = None, ) -> None: from mocket.mocket import Mocket from mocket.socket import MocketSocket, create_connection, socketpair @@ -48,6 +49,7 @@ def enable( Mocket._namespace = namespace Mocket._truesocket_recording_dir = truesocket_recording_dir + Mocket._recording_ignored_headers = recording_ignored_headers or [] if truesocket_recording_dir and not os.path.isdir(truesocket_recording_dir): # JSON dumps will be saved here diff --git a/mocket/mocket.py b/mocket/mocket.py index 3476902d..34e270ef 100644 --- a/mocket/mocket.py +++ b/mocket/mocket.py @@ -22,6 +22,7 @@ class Mocket: _requests: ClassVar[list] = [] _namespace: ClassVar[str] = str(id(_entries)) _truesocket_recording_dir: ClassVar[str | None] = None + _recording_ignored_headers: list[str] | None = None enable = mocket.inject.enable disable = mocket.inject.disable @@ -96,6 +97,10 @@ def get_namespace(cls) -> str: def get_truesocket_recording_dir(cls) -> str | None: return cls._truesocket_recording_dir + @classmethod + def get_recording_ignored_headers(cls): + return cls._recording_ignored_headers + @classmethod def assert_fail_if_entries_not_served(cls) -> None: """Mocket checks that all entries have been served at least once.""" diff --git a/mocket/mocketizer.py b/mocket/mocketizer.py index 2bf2b9cd..07ef4a21 100644 --- a/mocket/mocketizer.py +++ b/mocket/mocketizer.py @@ -11,9 +11,11 @@ def __init__( truesocket_recording_dir=None, strict_mode=False, strict_mode_allowed=None, + recording_ignored_headers: list[str] | None = None, ): self.instance = instance self.truesocket_recording_dir = truesocket_recording_dir + self.recording_ignored_headers = recording_ignored_headers self.namespace = namespace or str(id(self)) MocketMode().STRICT = strict_mode if strict_mode: @@ -27,6 +29,7 @@ def enter(self): Mocket.enable( namespace=self.namespace, truesocket_recording_dir=self.truesocket_recording_dir, + recording_ignored_headers=self.recording_ignored_headers, ) if self.instance: self.check_and_call("mocketize_setup") @@ -57,7 +60,14 @@ def check_and_call(self, method_name): method() @staticmethod - def factory(test, truesocket_recording_dir, strict_mode, strict_mode_allowed, args): + def factory( + test, + truesocket_recording_dir, + strict_mode, + strict_mode_allowed, + recording_ignored_headers, + args, + ): instance = args[0] if args else None namespace = None if truesocket_recording_dir: @@ -75,6 +85,7 @@ def factory(test, truesocket_recording_dir, strict_mode, strict_mode_allowed, ar truesocket_recording_dir=truesocket_recording_dir, strict_mode=strict_mode, strict_mode_allowed=strict_mode_allowed, + recording_ignored_headers=recording_ignored_headers, ) @@ -83,11 +94,17 @@ def wrapper( truesocket_recording_dir=None, strict_mode=False, strict_mode_allowed=None, + recording_ignored_headers: list[str] | None = None, *args, **kwargs, ): with Mocketizer.factory( - test, truesocket_recording_dir, strict_mode, strict_mode_allowed, args + test, + truesocket_recording_dir, + strict_mode, + strict_mode_allowed, + recording_ignored_headers, + args, ): return test(*args, **kwargs) diff --git a/mocket/socket.py b/mocket/socket.py index e4be00b6..0f7c10d5 100644 --- a/mocket/socket.py +++ b/mocket/socket.py @@ -6,6 +6,7 @@ import select import socket import ssl +import re from datetime import datetime, timedelta from json.decoder import JSONDecodeError @@ -293,6 +294,10 @@ def true_sendall(self, data, *args, **kwargs): # dump the resulting dictionary to a JSON file if Mocket.get_truesocket_recording_dir(): # update the dictionary with request and response lines + # for header in Mocket.get_recording_ignored_headers(): + # header_pattern = rf"{header}: .*\r\n" + # req = re.sub(header_pattern, "", req) + response_dict["request"] = req response_dict["response"] = hexdump(encoded_response) diff --git a/tests/test_http.py b/tests/test_http.py index d516068b..38c1f180 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -314,6 +314,37 @@ def test_truesendall_with_dump_from_recording(self): self.assertEqual(len(responses["httpbin.local"]["80"].keys()), 2) + # @mocketize( + # truesocket_recording_dir=os.path.dirname(__file__), + # recording_ignored_headers=["Authorization"], + # ) + # def test_truesendall_with_dump_from_recording_and_ignored_headers(self): + # requests.get( + # "http://httpbin.local/ip", + # headers={ + # "user-agent": "Fake-User-Agent", + # "Accept-Encoding": "gzip, deflate, zstd", + # "Authorization": "token", + # }, + # ) + # requests.get( + # "http://httpbin.local/gzip", + # headers={ + # "user-agent": "Fake-User-Agent", + # "Accept-Encoding": "gzip, deflate, zstd", + # "Authorization": "token", + # }, + # ) + + # dump_filename = os.path.join( + # Mocket.get_truesocket_recording_dir(), Mocket.get_namespace() + ".json" + # ) + # with open(dump_filename) as f: + # responses = json.load(f) + + # print(responses["httpbin.local"]["80"]) + # self.assertEqual(len(responses["httpbin.local"]["80"].keys()), 2) + @mocketize def test_post_file_object(self): url = "http://github.com/fluidicon.png" From eb9f9b3de71456c312e4bba8f47c0547d86bec58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20W=C3=B3jciak?= Date: Wed, 20 Nov 2024 09:25:23 +0100 Subject: [PATCH 2/4] [feature/recording-ignored-headers] --- mocket/async_mocket.py | 2 ++ mocket/mocketizer.py | 2 ++ mocket/socket.py | 9 +++--- tests/test_http.py | 63 ++++++++++++++++++++++-------------------- 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/mocket/async_mocket.py b/mocket/async_mocket.py index 274d1fb3..1aff7551 100644 --- a/mocket/async_mocket.py +++ b/mocket/async_mocket.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from mocket.mocketizer import Mocketizer from mocket.utils import get_mocketize diff --git a/mocket/mocketizer.py b/mocket/mocketizer.py index 07ef4a21..1c18ef8e 100644 --- a/mocket/mocketizer.py +++ b/mocket/mocketizer.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from mocket.mocket import Mocket from mocket.mode import MocketMode from mocket.utils import get_mocketize diff --git a/mocket/socket.py b/mocket/socket.py index 0f7c10d5..986838f5 100644 --- a/mocket/socket.py +++ b/mocket/socket.py @@ -293,11 +293,12 @@ def true_sendall(self, data, *args, **kwargs): # dump the resulting dictionary to a JSON file if Mocket.get_truesocket_recording_dir(): - # update the dictionary with request and response lines - # for header in Mocket.get_recording_ignored_headers(): - # header_pattern = rf"{header}: .*\r\n" - # req = re.sub(header_pattern, "", req) + # filter out unwanted headers + for header in Mocket.get_recording_ignored_headers(): + header_pattern = rf"{header}: .*\r\n" + req = re.sub(header_pattern, "", req) + # update the dictionary with request and response lines response_dict["request"] = req response_dict["response"] = hexdump(encoded_response) diff --git a/tests/test_http.py b/tests/test_http.py index 38c1f180..d7676cc7 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -314,36 +314,39 @@ def test_truesendall_with_dump_from_recording(self): self.assertEqual(len(responses["httpbin.local"]["80"].keys()), 2) - # @mocketize( - # truesocket_recording_dir=os.path.dirname(__file__), - # recording_ignored_headers=["Authorization"], - # ) - # def test_truesendall_with_dump_from_recording_and_ignored_headers(self): - # requests.get( - # "http://httpbin.local/ip", - # headers={ - # "user-agent": "Fake-User-Agent", - # "Accept-Encoding": "gzip, deflate, zstd", - # "Authorization": "token", - # }, - # ) - # requests.get( - # "http://httpbin.local/gzip", - # headers={ - # "user-agent": "Fake-User-Agent", - # "Accept-Encoding": "gzip, deflate, zstd", - # "Authorization": "token", - # }, - # ) - - # dump_filename = os.path.join( - # Mocket.get_truesocket_recording_dir(), Mocket.get_namespace() + ".json" - # ) - # with open(dump_filename) as f: - # responses = json.load(f) - - # print(responses["httpbin.local"]["80"]) - # self.assertEqual(len(responses["httpbin.local"]["80"].keys()), 2) + @mocketize( + truesocket_recording_dir=os.path.dirname(__file__), + recording_ignored_headers=["Authorization"], + ) + def test_truesendall_with_dump_from_recording_and_ignored_headers(self): + requests.get( + "http://httpbin.local/ip", + headers={ + "user-agent": "Fake-User-Agent", + "Accept-Encoding": "gzip, deflate, zstd", + "Authorization": "token", + }, + ) + requests.get( + "http://httpbin.local/gzip", + headers={ + "user-agent": "Fake-User-Agent", + "Accept-Encoding": "gzip, deflate, zstd", + "Authorization": "token", + }, + ) + + dump_filename = os.path.join( + Mocket.get_truesocket_recording_dir(), Mocket.get_namespace() + ".json" + ) + with open(dump_filename) as f: + responses = json.load(f) + + for key, value in responses["httpbin.local"]["80"].items(): + print(value["request"]) + assert ( + "Authorization" not in value["request"] + ), f"'Authorization' header found in request ID: {key}" @mocketize def test_post_file_object(self): From 17ecb82c750e0f70b0b6d066c5dd103df14d0d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20W=C3=B3jciak?= Date: Wed, 20 Nov 2024 09:30:27 +0100 Subject: [PATCH 3/4] [feature/recording-ignored-headers] --- tests/test_http.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_http.py b/tests/test_http.py index d7676cc7..d58ef2de 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -343,7 +343,6 @@ def test_truesendall_with_dump_from_recording_and_ignored_headers(self): responses = json.load(f) for key, value in responses["httpbin.local"]["80"].items(): - print(value["request"]) assert ( "Authorization" not in value["request"] ), f"'Authorization' header found in request ID: {key}" From 90d0063882a94c39be0000d20e55c8171bc2ea81 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciak Date: Wed, 20 Nov 2024 11:08:09 +0100 Subject: [PATCH 4/4] Update tests/test_http.py Co-authored-by: Clemens Wolff --- tests/test_http.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_http.py b/tests/test_http.py index d58ef2de..08436eb2 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -343,9 +343,7 @@ def test_truesendall_with_dump_from_recording_and_ignored_headers(self): responses = json.load(f) for key, value in responses["httpbin.local"]["80"].items(): - assert ( - "Authorization" not in value["request"] - ), f"'Authorization' header found in request ID: {key}" + self.assertNotIn("Authorization", value["request"]) @mocketize def test_post_file_object(self):