44import sentry_sdk
55from sentry_sdk ._types import SENSITIVE_DATA_SUBSTITUTE
66from sentry_sdk .data_collection import _apply_key_value_collection_filtering
7- from sentry_sdk .utils import AnnotatedValue
7+ from sentry_sdk .scope import should_send_default_pii
8+ from sentry_sdk .utils import AnnotatedValue , has_data_collection_enabled
89
910try :
1011 from django .http .request import RawPostDataException
3435 "TRACE" ,
3536)
3637
38+ SENSITIVE_ENV_KEYS = (
39+ "REMOTE_ADDR" ,
40+ "HTTP_X_FORWARDED_FOR" ,
41+ "HTTP_SET_COOKIE" ,
42+ "HTTP_COOKIE" ,
43+ "HTTP_AUTHORIZATION" ,
44+ "HTTP_PROXY_AUTHORIZATION" ,
45+ "HTTP_X_API_KEY" ,
46+ "HTTP_X_FORWARDED_FOR" ,
47+ "HTTP_X_REAL_IP" ,
48+ )
49+
50+ SENSITIVE_HEADERS = tuple (
51+ x [len ("HTTP_" ) :] for x in SENSITIVE_ENV_KEYS if x .startswith ("HTTP_" )
52+ )
53+
3754
3855def request_body_within_bounds (
3956 client : "Optional[sentry_sdk.client.BaseClient]" , content_length : int
@@ -185,6 +202,63 @@ def env(self) -> "Dict[str, Any]":
185202 raise NotImplementedError ()
186203
187204
205+ class LegacyRequestExtractor (RequestExtractor ):
206+ def extract_into_event (self , event : "Event" ) -> None :
207+ client = sentry_sdk .get_client ()
208+ if not client .is_active ():
209+ return
210+
211+ data : "Optional[Union[AnnotatedValue, Dict[str, Any]]]" = None
212+ content_length = self .content_length ()
213+ request_info = event .get ("request" , {})
214+
215+ # Prior to data collection being implemented we unconditionally attached
216+ # the request body, which is why we default to True here.
217+ attach_request_body = True
218+ if has_data_collection_enabled (client .options ):
219+ cookies = _apply_key_value_collection_filtering (
220+ items = dict (self .cookies ()),
221+ behaviour = client .options ["data_collection" ]["cookies" ],
222+ )
223+ if cookies :
224+ request_info ["cookies" ] = cookies
225+
226+ attach_request_body = (
227+ "incoming_request" in client .options ["data_collection" ]["http_bodies" ]
228+ )
229+ elif should_send_default_pii ():
230+ request_info ["cookies" ] = dict (self .cookies ())
231+
232+ if attach_request_body :
233+ if not request_body_within_bounds (client , content_length ):
234+ data = AnnotatedValue .removed_because_over_size_limit ()
235+ else :
236+ # First read the raw body data
237+ # It is important to read this first because if it is Django
238+ # it will cache the body and then we can read the cached version
239+ # again in parsed_body() (or json() or wherever).
240+ raw_data = None
241+ try :
242+ raw_data = self .raw_data ()
243+ except _RAW_DATA_EXCEPTIONS :
244+ # If DjangoRestFramework is used it already read the body for us
245+ # so reading it here will fail. We can ignore this.
246+ pass
247+
248+ parsed_body = self .parsed_body ()
249+ if parsed_body is not None :
250+ data = parsed_body
251+ elif raw_data :
252+ data = AnnotatedValue .removed_because_raw_data ()
253+ else :
254+ data = None
255+
256+ if data is not None :
257+ request_info ["data" ] = data
258+
259+ event ["request" ] = deepcopy (request_info )
260+
261+
188262def _is_json_content_type (ct : "Optional[str]" ) -> bool :
189263 mt = (ct or "" ).split (";" , 1 )[0 ]
190264 return (
@@ -210,3 +284,42 @@ def _filter_headers(
210284 filtered [key ] = SENSITIVE_DATA_SUBSTITUTE
211285
212286 return filtered
287+
288+
289+ def _filter_headers_legacy (
290+ headers : "Mapping[str, str]" ,
291+ use_annotated_value : bool = True ,
292+ ) -> "Mapping[str, Union[AnnotatedValue, str]]" :
293+ client_options = sentry_sdk .get_client ().options
294+
295+ if has_data_collection_enabled (client_options ):
296+ data_collection_configuration = client_options ["data_collection" ]
297+ filtered = _apply_key_value_collection_filtering (
298+ items = headers ,
299+ behaviour = data_collection_configuration ["http_headers" ]["request" ],
300+ )
301+
302+ for key in filtered :
303+ if isinstance (key , str ) and key .lower () in ("cookie" , "set-cookie" ):
304+ filtered [key ] = SENSITIVE_DATA_SUBSTITUTE
305+
306+ return filtered
307+
308+ else :
309+ if should_send_default_pii ():
310+ return headers
311+
312+ substitute : "Union[AnnotatedValue, str]" = (
313+ SENSITIVE_DATA_SUBSTITUTE
314+ if not use_annotated_value
315+ else AnnotatedValue .removed_because_over_size_limit ()
316+ )
317+
318+ return {
319+ k : (
320+ v
321+ if k .upper ().replace ("-" , "_" ) not in SENSITIVE_HEADERS
322+ else substitute
323+ )
324+ for k , v in headers .items ()
325+ }
0 commit comments