@@ -84,3 +84,114 @@ def test_get_blocked_template_user_file_exists_json():
8484 assert utils ._get_blocked_template ("text/html" , BLOCK_ID ) == utils ._format_template (
8585 BLOCKED_RESPONSE_HTML , BLOCK_ID
8686 )
87+
88+
89+ def test_block_config_get_existing_attribute ():
90+ """
91+ Test that get() returns existing attribute values.
92+
93+ Regression test for PR #15042 which changed Block_config from dict to class,
94+ breaking Lambda integration that expects .get() method for dictionary-like access.
95+ """
96+ from ddtrace .appsec ._utils import Block_config
97+
98+ config = Block_config (status_code = 403 , type = "auto" , grpc_status_code = 10 )
99+
100+ assert config .get ("status_code" ) == 403
101+ assert config .get ("type" ) == "auto"
102+ assert config .get ("grpc_status_code" ) == 10
103+
104+
105+ def test_block_config_get_nonexistent_attribute_default_none ():
106+ """Test that get() returns None for nonexistent attributes when no default is provided."""
107+ from ddtrace .appsec ._utils import Block_config
108+
109+ config = Block_config ()
110+
111+ assert config .get ("nonexistent_field" ) is None
112+ assert config .get ("missing_attribute" ) is None
113+
114+
115+ def test_block_config_get_nonexistent_attribute_with_custom_default ():
116+ """Test that get() returns custom default for nonexistent attributes."""
117+ from ddtrace .appsec ._utils import Block_config
118+
119+ config = Block_config ()
120+
121+ assert config .get ("nonexistent_field" , "default_value" ) == "default_value"
122+ assert config .get ("missing_attribute" , 123 ) == 123
123+ assert config .get ("another_missing" , False ) is False
124+
125+
126+ def test_block_config_get_all_standard_attributes ():
127+ """Test that get() works for all standard Block_config attributes."""
128+ from ddtrace .appsec ._utils import Block_config
129+
130+ config = Block_config (
131+ type = "json" ,
132+ status_code = 404 ,
133+ grpc_status_code = 5 ,
134+ security_response_id = "custom-block-id" ,
135+ location = "/custom/location" ,
136+ )
137+
138+ # Test all standard attributes
139+ assert config .get ("block_id" ) == "custom-block-id"
140+ assert config .get ("status_code" ) == 404
141+ assert config .get ("grpc_status_code" ) == 5
142+ assert config .get ("type" ) == "json"
143+ assert config .get ("content_type" ) == "application/json"
144+ # Location should have the security_response_id replaced
145+ assert "/custom/location" in config .get ("location" )
146+
147+
148+ def test_block_config_get_method_lambda_compatibility ():
149+ """
150+ Test Lambda integration compatibility scenario.
151+
152+ This simulates the actual error from Lambda where code expects
153+ dictionary-like access: block_config.get("key", default)
154+
155+ Reproduces the error:
156+ AttributeError: 'Block_config' object has no attribute 'get'
157+ """
158+ from ddtrace .appsec ._utils import Block_config
159+
160+ # Simulate Lambda's get_asm_blocked_response usage
161+ block_config = Block_config (
162+ type = "auto" ,
163+ status_code = 403 ,
164+ grpc_status_code = 10 ,
165+ security_response_id = "block-001" ,
166+ )
167+
168+ # Lambda code does things like: block_config.get("status_code", 403)
169+ status = block_config .get ("status_code" , 403 )
170+ assert status == 403
171+
172+ # Lambda code might check for optional fields
173+ custom_field = block_config .get ("custom_field" , "default" )
174+ assert custom_field == "default"
175+
176+ # Verify block_id is accessible
177+ block_id = block_config .get ("block_id" )
178+ assert block_id == "block-001"
179+
180+
181+ def test_block_config_get_preserves_attribute_access ():
182+ """Test that adding get() doesn't break normal attribute access."""
183+ from ddtrace .appsec ._utils import Block_config
184+
185+ config = Block_config (status_code = 500 , type = "html" )
186+
187+ # Normal attribute access should still work
188+ assert config .status_code == 500
189+ assert config .type == "html"
190+
191+ # get() method should return the same values
192+ assert config .get ("status_code" ) == 500
193+ assert config .get ("type" ) == "html"
194+
195+ # Both access methods should return identical values
196+ assert config .status_code == config .get ("status_code" )
197+ assert config .type == config .get ("type" )
0 commit comments