1
1
"""
2
2
MobiData BW Proxy
3
3
Copyright (c) 2023, binary butterfly GmbH
4
- All rights reserved.
4
+
5
+ Licensed under the EUPL, Version 1.2 or – as soon they will be approved by
6
+ the European Commission - subsequent versions of the EUPL (the "Licence");
7
+ You may not use this work except in compliance with the Licence.
8
+ You may obtain a copy of the Licence at:
9
+
10
+ https://joinup.ec.europa.eu/software/page/eupl
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the Licence is distributed on an "AS IS" basis,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the Licence for the specific language governing permissions and
16
+ limitations under the Licence.
5
17
"""
6
18
7
19
import json
8
20
import logging
21
+ import traceback
9
22
from importlib import import_module
10
23
from inspect import isclass
11
24
from json import JSONDecodeError
25
+ from logging .config import dictConfig
12
26
from pathlib import Path
13
27
from pkgutil import iter_modules
14
28
from typing import Dict , List
15
29
16
- from mitmproxy .http import HTTPFlow
30
+ from mitmproxy .http import HTTPFlow , Response
17
31
18
32
from app .base_converter import BaseConverter
19
33
from app .config_helper import ConfigHelper
34
+ from app .utils import ContextHelper
35
+ from app .utils .context_helper import context_helper
36
+ from app .utils .default_json_encoder import DefaultJSONEncoder
20
37
21
- logger = logging .getLogger ('converters.requests' )
38
+ logger = logging .getLogger (__name__ )
22
39
23
40
24
41
class App :
42
+ config_helper : ConfigHelper
43
+ context_helper : ContextHelper
44
+
25
45
json_converters : Dict [str , List [BaseConverter ]]
26
46
27
47
def __init__ (self ):
28
48
self .config_helper = ConfigHelper ()
49
+ self .context_helper = context_helper
50
+
51
+ # configure logging
52
+ dictConfig (self .config_helper .get ('LOGGING' ))
29
53
30
54
self .json_converters = {}
31
55
@@ -48,29 +72,60 @@ def __init__(self):
48
72
self .json_converters [hostname ].append (obj )
49
73
50
74
def request (self , flow : HTTPFlow ):
75
+ self .context_helper .initialize_context ()
76
+
51
77
if flow .request .host in self .config_helper .get ('HTTP_TO_HTTPS_HOSTS' , []):
52
78
flow .request .scheme = 'https'
53
79
flow .request .port = 443
54
80
81
+ self .context_helper .set_attribute ('url.host' , flow .request .host )
82
+ self .context_helper .set_attribute ('url.scheme' , flow .request .scheme )
83
+ self .context_helper .set_attribute ('url.port' , flow .request .port )
84
+ self .context_helper .set_attribute ('url.path' , flow .request .path )
85
+
55
86
def response (self , flow : HTTPFlow ):
56
87
# Log requests
57
- logger .info (f'{ flow .request .method } { flow .request .url } : HTTP { "-" if flow .response is None else flow .response .status_code } ' )
88
+ logger .debug (f'{ flow .request .method } { flow .request .url } : HTTP { "-" if flow .response is None else flow .response .status_code } ' )
58
89
59
90
# if there is no converter for the requested host, don't do anything
60
91
if flow .request .host not in self .json_converters :
92
+ logger .warning ('No JSON converter for request.' )
61
93
return
62
94
63
95
# try to load the response. If there is any error, return.
64
- if not flow .response or not flow .response .text :
96
+ if not flow .response :
97
+ logger .warning ('No response for request.' )
65
98
return
99
+
100
+ response : Response = flow .response
101
+
102
+ if not response .text :
103
+ logger .warning ('Empty response for request.' )
104
+ return
105
+
66
106
try :
67
- json_data = json .loads (flow . response .text )
107
+ json_data = json .loads (response .text )
68
108
except (JSONDecodeError , TypeError ):
109
+ logger .warning (f'Invalid JSON in request: { response .text } .' )
69
110
return
70
111
71
112
# iterate all converters and apply them
72
113
for json_converter in self .json_converters [flow .request .host ]:
73
- json_data = json_converter .convert (data = json_data , path = flow .request .path )
114
+ self .context_helper .set_attribute ('converter' , json_converter .__class__ .__name__ )
115
+ try :
116
+ json_data = json_converter .convert (data = json_data , path = flow .request .path )
117
+ except Exception as e :
118
+ logger .error (
119
+ f'Converter { json_converter .__class__ .__name__ } threw an exception { e .__class__ .__name__ } : { e } ' ,
120
+ extra = {
121
+ 'attributes' : {
122
+ # This needs to be json_data, as json_data is maybe already transformed
123
+ 'data' : json .dumps (json_data ),
124
+ 'traceback' : traceback .format_exc (),
125
+ },
126
+ },
127
+ )
128
+ return
74
129
75
130
# set the returning json content
76
- flow .response .text = json .dumps (json_data )
131
+ flow .response .text = json .dumps (json_data , cls = DefaultJSONEncoder )
0 commit comments