@@ -39,7 +39,7 @@ async def test_request_body_caching():
39
39
result1 = await _read_request_body (mock_request )
40
40
assert result1 == test_data
41
41
assert "parsed_body" in mock_request .scope
42
- assert mock_request .scope ["parsed_body" ] == test_data
42
+ assert mock_request .scope ["parsed_body" ] == (( "key" ,), { "key" : "value" })
43
43
44
44
# Verify the body was read once
45
45
mock_request .body .assert_called_once ()
@@ -49,7 +49,7 @@ async def test_request_body_caching():
49
49
50
50
# Second call should use the cached body
51
51
result2 = await _read_request_body (mock_request )
52
- assert result2 == test_data
52
+ assert result2 == { "key" : "value" }
53
53
54
54
# Verify the body was not read again
55
55
mock_request .body .assert_not_called ()
@@ -75,7 +75,10 @@ async def test_form_data_parsing():
75
75
# Verify the form data was correctly parsed
76
76
assert result == test_data
77
77
assert "parsed_body" in mock_request .scope
78
- assert mock_request .scope ["parsed_body" ] == test_data
78
+ assert mock_request .scope ["parsed_body" ] == (
79
+ ("name" , "message" ),
80
+ {"name" : "test_user" , "message" : "hello world" },
81
+ )
79
82
80
83
# Verify form() was called
81
84
mock_request .form .assert_called_once ()
@@ -101,7 +104,46 @@ async def test_empty_request_body():
101
104
# Verify an empty dict is returned
102
105
assert result == {}
103
106
assert "parsed_body" in mock_request .scope
104
- assert mock_request .scope ["parsed_body" ] == {}
107
+ assert mock_request .scope ["parsed_body" ] == ((), {})
105
108
106
109
# Verify the body was read
107
110
mock_request .body .assert_called_once ()
111
+
112
+
113
+ @pytest .mark .asyncio
114
+ async def test_circular_reference_handling ():
115
+ """
116
+ Test that cached request body isn't modified when the returned result is modified.
117
+ Demonstrates the mutable dictionary reference issue.
118
+ """
119
+ # Create a mock request with initial data
120
+ mock_request = MagicMock ()
121
+ initial_body = {
122
+ "model" : "gpt-4" ,
123
+ "messages" : [{"role" : "user" , "content" : "Hello" }],
124
+ }
125
+
126
+ mock_request .body = AsyncMock (return_value = orjson .dumps (initial_body ))
127
+ mock_request .headers = {"content-type" : "application/json" }
128
+ mock_request .scope = {}
129
+
130
+ # First parse
131
+ result = await _read_request_body (mock_request )
132
+
133
+ # Verify initial parse
134
+ assert result ["model" ] == "gpt-4"
135
+ assert result ["messages" ] == [{"role" : "user" , "content" : "Hello" }]
136
+
137
+ # Modify the result by adding proxy_server_request
138
+ result ["proxy_server_request" ] = {
139
+ "url" : "http://0.0.0.0:4000/v1/chat/completions" ,
140
+ "method" : "POST" ,
141
+ "headers" : {"content-type" : "application/json" },
142
+ "body" : result , # Creates circular reference
143
+ }
144
+
145
+ # Second parse using the same request - will use the modified cached value
146
+ result2 = await _read_request_body (mock_request )
147
+ assert (
148
+ "proxy_server_request" not in result2
149
+ ) # This will pass, showing the cache pollution
0 commit comments