stoobly-agent 0.30.1__py3-none-any.whl → 0.30.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- stoobly_agent/__init__.py +1 -1
- stoobly_agent/app/cli/config_cli.py +6 -4
- stoobly_agent/app/cli/helpers/handle_mock_service.py +1 -1
- stoobly_agent/app/proxy/handle_mock_service.py +6 -5
- stoobly_agent/app/proxy/handle_record_service.py +6 -7
- stoobly_agent/app/proxy/handle_replay_service.py +2 -2
- stoobly_agent/app/proxy/intercept_handler.py +6 -0
- stoobly_agent/app/proxy/mitmproxy/request_facade.py +9 -2
- stoobly_agent/app/proxy/utils/allowed_request_service.py +2 -2
- stoobly_agent/app/settings/types/proxy_settings.py +2 -1
- stoobly_agent/app/settings/url_rule.py +10 -4
- stoobly_agent/db/migrations/2022_03_17_060144_create_requests.py +1 -1
- stoobly_agent/db/migrations/2022_03_17_074916_create_responses.py +1 -1
- stoobly_agent/db/migrations/2022_05_10_003705_create_traces.py +1 -1
- stoobly_agent/db/migrations/2022_05_10_003840_create_trace_aliases.py +1 -1
- stoobly_agent/db/migrations/2022_06_29_234516_create_trace_requests.py +1 -1
- stoobly_agent/db/migrations/2022_06_29_235155_add_trace_request_reference_to_trace_aliases.py +1 -1
- stoobly_agent/db/migrations/2022_12_12_092437_align_requests.py +1 -1
- stoobly_agent/db/migrations/2022_12_28_092917_add_filter_columns_to_requests.py +1 -1
- stoobly_agent/db/migrations/2023_01_21_055426_create_scenarios.py +1 -1
- stoobly_agent/db/migrations/2023_01_21_060225_add_scenario_id_reference_to_requests.py +1 -1
- stoobly_agent/db/migrations/2023_02_02_022229_create_replayed_responses.py +1 -1
- stoobly_agent/db/migrations/2023_03_20_192909_add_http_version_column_to_requests.py +1 -1
- stoobly_agent/db/migrations/2023_03_20_220448_add_http_version_column_to_responses.py +1 -1
- stoobly_agent/db/migrations/2023_04_18_071327_align_requests.py +1 -1
- stoobly_agent/db/migrations/2023_05_15_212505_add_uuid_column_to_requests.py +1 -1
- stoobly_agent/db/migrations/2023_05_15_213119_add_uuid_column_to_scenarios.py +1 -1
- stoobly_agent/db/migrations/2023_05_29_053649_add_overwritable_column_to_scenarios.py +1 -1
- stoobly_agent/lib/orm/__init__.py +1 -1
- stoobly_agent/lib/orm/migrate_service.py +1 -1
- stoobly_agent/lib/orm/replayed_response.py +1 -1
- stoobly_agent/lib/orm/request.py +1 -1
- stoobly_agent/lib/orm/response.py +1 -1
- stoobly_agent/lib/orm/scenario.py +1 -1
- stoobly_agent/lib/orm/trace.py +1 -1
- stoobly_agent/lib/orm/trace_alias.py +1 -1
- stoobly_agent/lib/orm/trace_request.py +1 -1
- stoobly_agent/public/11-es2015.f88178b1234331d8bcb6.js +1 -0
- stoobly_agent/public/11-es5.f88178b1234331d8bcb6.js +1 -0
- stoobly_agent/public/{18-es2015.46d337c47cb41abec8ad.js → 18-es2015.ad1de4189b713d5a04ec.js} +1 -1
- stoobly_agent/public/{18-es5.46d337c47cb41abec8ad.js → 18-es5.ad1de4189b713d5a04ec.js} +1 -1
- stoobly_agent/public/dashboard.agent-alpha-0.30.5.tar.gz +0 -0
- stoobly_agent/public/index.html +1 -1
- stoobly_agent/public/{runtime-es2015.3a15c6ce90c8f8cce796.js → runtime-es2015.f2afb0be12804827d0a0.js} +1 -1
- stoobly_agent/public/{runtime-es5.3a15c6ce90c8f8cce796.js → runtime-es5.f2afb0be12804827d0a0.js} +1 -1
- {stoobly_agent-0.30.1.dist-info → stoobly_agent-0.30.7.dist-info}/METADATA +4 -4
- {stoobly_agent-0.30.1.dist-info → stoobly_agent-0.30.7.dist-info}/RECORD +51 -51
- {stoobly_agent-0.30.1.dist-info → stoobly_agent-0.30.7.dist-info}/WHEEL +1 -1
- stoobly_agent/public/11-es2015.25f04c94499eb7fe8383.js +0 -1
- stoobly_agent/public/11-es5.25f04c94499eb7fe8383.js +0 -1
- stoobly_agent/public/dashboard.agent-alpha-0.30.0.tar.gz +0 -0
- {stoobly_agent-0.30.1.dist-info → stoobly_agent-0.30.7.dist-info}/LICENSE +0 -0
- {stoobly_agent-0.30.1.dist-info → stoobly_agent-0.30.7.dist-info}/entry_points.txt +0 -0
- {stoobly_agent-0.30.1.dist-info → stoobly_agent-0.30.7.dist-info}/top_level.txt +0 -0
stoobly_agent/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
COMMAND = 'stoobly-agent'
|
2
|
-
VERSION = '0.30.
|
2
|
+
VERSION = '0.30.7'
|
@@ -146,7 +146,7 @@ def rewrite(ctx):
|
|
146
146
|
@rewrite.command(
|
147
147
|
help="Set rewrite rule."
|
148
148
|
)
|
149
|
-
@click.option('--
|
149
|
+
@click.option('--hostname', help='Request URL hostname.')
|
150
150
|
@click.option(
|
151
151
|
'--method',
|
152
152
|
multiple=True,
|
@@ -169,6 +169,7 @@ def rewrite(ctx):
|
|
169
169
|
type=click.Choice([request_component.BODY_PARAM, request_component.HEADER, request_component.QUERY_PARAM]),
|
170
170
|
help='Request component type.'
|
171
171
|
)
|
172
|
+
@click.option('--scheme', help='Request URL scheme.')
|
172
173
|
@click.option('--value', help='Rewrite value.')
|
173
174
|
def set(**kwargs):
|
174
175
|
if kwargs['name'] or kwargs['value'] or kwargs['type']:
|
@@ -209,7 +210,7 @@ def set(**kwargs):
|
|
209
210
|
settings.proxy.rewrite.set_rewrite_rules(project_key.id, rewrite_rules)
|
210
211
|
else:
|
211
212
|
parameter_rule_filter = lambda rule: rule.name == kwargs['name'] and rule.type == kwargs['type'] and rule.modes == modes
|
212
|
-
url_rule_filter = lambda rule: rule.
|
213
|
+
url_rule_filter = lambda rule: rule.modes == modes
|
213
214
|
|
214
215
|
for rewrite_rule in filtered_rewrite_rules:
|
215
216
|
# Parameter rules
|
@@ -485,13 +486,14 @@ def __select_parameter_rule(kwargs):
|
|
485
486
|
}
|
486
487
|
|
487
488
|
def __select_url_rule(kwargs):
|
488
|
-
if kwargs['
|
489
|
+
if kwargs['hostname'] == None or kwargs['port'] == None:
|
489
490
|
return
|
490
491
|
|
491
492
|
return {
|
492
|
-
'
|
493
|
+
'hostname': kwargs['hostname'],
|
493
494
|
'modes': list(kwargs['mode']),
|
494
495
|
'port': kwargs['port'],
|
496
|
+
'scheme': kwargs['scheme'],
|
495
497
|
}
|
496
498
|
|
497
499
|
def __project_key(settings):
|
@@ -32,10 +32,14 @@ class MockOptions(TypedDict):
|
|
32
32
|
# @param settings [Dict]
|
33
33
|
#
|
34
34
|
def handle_request_mock_generic(context: MockContext, **options: MockOptions):
|
35
|
+
__mock_hook(lifecycle_hooks.BEFORE_MOCK, context)
|
36
|
+
|
35
37
|
intercept_settings = context.intercept_settings
|
36
38
|
request: MitmproxyRequest = context.flow.request
|
37
39
|
request_model = RequestModel(intercept_settings.settings)
|
38
40
|
|
41
|
+
policy = get_active_mode_policy(request, intercept_settings)
|
42
|
+
|
39
43
|
rewrite_rules = intercept_settings.mock_rewrite_rules
|
40
44
|
if len(rewrite_rules) > 0:
|
41
45
|
# Rewrite request with paramter rules for mock
|
@@ -43,8 +47,6 @@ def handle_request_mock_generic(context: MockContext, **options: MockOptions):
|
|
43
47
|
request_facade = MitmproxyRequestFacade(request)
|
44
48
|
request_facade.with_parameter_rules(rewrite_rules).with_url_rules(rewrite_rules).rewrite()
|
45
49
|
|
46
|
-
__mock_hook(lifecycle_hooks.BEFORE_MOCK, context)
|
47
|
-
|
48
50
|
# If ignore rules are set, then ignore specified request parameters
|
49
51
|
ignore_rules = intercept_settings.ignore_rules
|
50
52
|
if len(ignore_rules) > 0:
|
@@ -57,7 +59,6 @@ def handle_request_mock_generic(context: MockContext, **options: MockOptions):
|
|
57
59
|
handle_failure = options['failure'] if 'failure' in options and callable(options['failure']) else None
|
58
60
|
|
59
61
|
eval_request = inject_eval_request(request_model, intercept_settings)
|
60
|
-
policy = get_active_mode_policy(request, intercept_settings)
|
61
62
|
|
62
63
|
if policy == mock_policy.NONE:
|
63
64
|
if handle_failure:
|
@@ -83,8 +84,8 @@ def handle_request_mock_generic(context: MockContext, **options: MockOptions):
|
|
83
84
|
else:
|
84
85
|
return bad_request(
|
85
86
|
context.flow,
|
86
|
-
"Valid env MOCK_POLICY: %s,
|
87
|
-
[mock_policy.ALL, mock_policy.FOUND, policy
|
87
|
+
"Valid env MOCK_POLICY: %s, Got: %s" %
|
88
|
+
([mock_policy.ALL, mock_policy.FOUND, mock_policy.NONE], policy)
|
88
89
|
)
|
89
90
|
|
90
91
|
__mock_hook(lifecycle_hooks.AFTER_MOCK, context)
|
@@ -23,18 +23,17 @@ LOG_ID = 'HandleRecord'
|
|
23
23
|
|
24
24
|
def handle_response_record(context: RecordContext):
|
25
25
|
flow = context.flow
|
26
|
-
intercept_settings = context.intercept_settings
|
27
|
-
request: MitmproxyRequest = flow.request
|
28
|
-
|
29
26
|
disable_transfer_encoding(flow.response)
|
30
27
|
|
28
|
+
__record_hook(lifecycle_hooks.BEFORE_RECORD, context)
|
29
|
+
|
30
|
+
intercept_settings = context.intercept_settings
|
31
|
+
request: MitmproxyRequest = flow.request
|
31
32
|
request_model = RequestModel(intercept_settings.settings)
|
32
33
|
|
33
34
|
active_record_policy = get_active_mode_policy(request, intercept_settings)
|
34
35
|
Logger.instance().debug(f"{LOG_ID}:RecordPolicy: {active_record_policy}")
|
35
36
|
|
36
|
-
__record_hook(lifecycle_hooks.BEFORE_RECORD, context)
|
37
|
-
|
38
37
|
if active_record_policy == record_policy.ALL:
|
39
38
|
__record_request(context, request_model)
|
40
39
|
elif active_record_policy == record_policy.FOUND:
|
@@ -55,8 +54,8 @@ def handle_response_record(context: RecordContext):
|
|
55
54
|
if active_record_policy != record_policy.NONE:
|
56
55
|
return bad_request(
|
57
56
|
flow,
|
58
|
-
"Valid env RECORD_POLICY: %s,
|
59
|
-
[record_policy.ALL, record_policy.FOUND, record_policy.NOT_FOUND, active_record_policy
|
57
|
+
"Valid env RECORD_POLICY: %s, Got: %s" %
|
58
|
+
([record_policy.ALL, record_policy.FOUND, record_policy.NOT_FOUND], active_record_policy)
|
60
59
|
)
|
61
60
|
|
62
61
|
def __record_handler(context: RecordContext, request_model: RequestModel):
|
@@ -12,6 +12,8 @@ from .utils.allowed_request_service import get_active_mode_policy
|
|
12
12
|
LOG_ID = 'HandleReplay'
|
13
13
|
|
14
14
|
def handle_request_replay(replay_context: ReplayContext):
|
15
|
+
__replay_hook(lifecycle_hooks.BEFORE_REPLAY, replay_context)
|
16
|
+
|
15
17
|
request: MitmproxyRequest = replay_context.flow.request
|
16
18
|
intercept_settings: InterceptSettings = replay_context.intercept_settings
|
17
19
|
|
@@ -34,8 +36,6 @@ def __replay_request(replay_context: ReplayContext):
|
|
34
36
|
request_facade = MitmproxyRequestFacade(request)
|
35
37
|
request_facade.with_parameter_rules(rewrite_rules).with_url_rules(rewrite_rules).rewrite()
|
36
38
|
|
37
|
-
__replay_hook(lifecycle_hooks.BEFORE_REPLAY, replay_context)
|
38
|
-
|
39
39
|
def __replay_hook(hook: str, replay_context: ReplayContext):
|
40
40
|
intercept_settings: InterceptSettings = replay_context.intercept_settings
|
41
41
|
|
@@ -30,6 +30,9 @@ def request(flow: MitmproxyHTTPFlow):
|
|
30
30
|
|
31
31
|
intercept_settings = InterceptSettings(Settings.instance(), request)
|
32
32
|
|
33
|
+
if not intercept_settings.active:
|
34
|
+
return
|
35
|
+
|
33
36
|
__intercept_hook(lifecycle_hooks.BEFORE_REQUEST, flow, intercept_settings)
|
34
37
|
|
35
38
|
active_mode = intercept_settings.mode
|
@@ -59,6 +62,9 @@ def response(flow: MitmproxyHTTPFlow):
|
|
59
62
|
intercept_settings = InterceptSettings(Settings.instance(), request)
|
60
63
|
intercept_settings.for_response()
|
61
64
|
|
65
|
+
if not intercept_settings.active:
|
66
|
+
return
|
67
|
+
|
62
68
|
__intercept_hook(lifecycle_hooks.BEFORE_RESPONSE, flow, intercept_settings)
|
63
69
|
|
64
70
|
active_mode = intercept_settings.mode
|
@@ -106,6 +106,10 @@ class MitmproxyRequestFacade(Request):
|
|
106
106
|
def parameter_rules(self) -> List[ParameterRule]:
|
107
107
|
return self.__parameter_rules
|
108
108
|
|
109
|
+
@property
|
110
|
+
def scheme(self):
|
111
|
+
return self.request.scheme
|
112
|
+
|
109
113
|
def with_parameter_rules(self, rules: List[RewriteRule]):
|
110
114
|
if type(rules) == list:
|
111
115
|
self.__parameter_rules = self.select_parameter_rules(rules)
|
@@ -181,12 +185,15 @@ class MitmproxyRequestFacade(Request):
|
|
181
185
|
|
182
186
|
def __rewrite_url(self, rewrites: List[UrlRule]):
|
183
187
|
for rewrite in rewrites:
|
184
|
-
if rewrite.
|
185
|
-
self.request.host = rewrite.
|
188
|
+
if rewrite.hostname:
|
189
|
+
self.request.host = rewrite.hostname
|
186
190
|
|
187
191
|
if rewrite.port:
|
188
192
|
self.request.port = int(rewrite.port)
|
189
193
|
|
194
|
+
if rewrite.scheme:
|
195
|
+
self.request.scheme = rewrite.scheme
|
196
|
+
|
190
197
|
def __rewrite_headers(self, rewrites: List[ParameterRule]):
|
191
198
|
self.__apply_headers(rewrites, self.__rewrite_handler)
|
192
199
|
|
@@ -13,7 +13,7 @@ def get_active_mode_policy(request: MitmproxyRequest, intercept_settings: Interc
|
|
13
13
|
if intercept_settings.request_origin == request_origin.CLI:
|
14
14
|
return intercept_settings.policy
|
15
15
|
|
16
|
-
if
|
16
|
+
if allowed_request(request, intercept_settings):
|
17
17
|
return intercept_settings.policy
|
18
18
|
else:
|
19
19
|
# If the request path does not match accepted paths, do not mock
|
@@ -27,7 +27,7 @@ def allowed_request(request: MitmproxyRequest, intercept_settings: InterceptSett
|
|
27
27
|
|
28
28
|
# If an include rule(s) exists, then only requests matching these pattern(s) are allowed
|
29
29
|
include_rules = intercept_settings.include_rules
|
30
|
-
if not __request_included(request, include_rules)
|
30
|
+
if not __request_included(request, include_rules):
|
31
31
|
return False
|
32
32
|
|
33
33
|
# If there are no exclude or include patterns, request is allowed
|
@@ -8,8 +8,8 @@ class UrlRule:
|
|
8
8
|
self.update(url_rule)
|
9
9
|
|
10
10
|
@property
|
11
|
-
def
|
12
|
-
return self.
|
11
|
+
def hostname(self):
|
12
|
+
return self.__hostname
|
13
13
|
|
14
14
|
@property
|
15
15
|
def modes(self):
|
@@ -19,15 +19,21 @@ class UrlRule:
|
|
19
19
|
def port(self):
|
20
20
|
return self.__port
|
21
21
|
|
22
|
+
@property
|
23
|
+
def scheme(self):
|
24
|
+
return self.__scheme
|
25
|
+
|
22
26
|
def update(self, url_rule: IUrlRule):
|
23
27
|
self.__url_rule = url_rule
|
24
|
-
self.
|
28
|
+
self.__hostname = self.__url_rule.get('hostname')
|
25
29
|
self.__modes = self.__url_rule.get('modes')
|
26
30
|
self.__port = self.__url_rule.get('port')
|
31
|
+
self.__scheme = self.__url_rule.get('scheme')
|
27
32
|
|
28
33
|
def to_dict(self):
|
29
34
|
return {
|
30
|
-
'
|
35
|
+
'hostname': self.__hostname,
|
31
36
|
'modes': self.__modes,
|
32
37
|
'port': self.__port,
|
38
|
+
'scheme': self.__scheme,
|
33
39
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import requests
|
2
2
|
import pdb
|
3
3
|
|
4
|
-
from
|
4
|
+
from stoobly_orator.migrations import Migration
|
5
5
|
|
6
6
|
from stoobly_agent.app.models.adapters.raw_http_response_adapter import RawHttpResponseAdapter
|
7
7
|
from stoobly_agent.lib.orm.request import Request
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
import pdb
|
3
3
|
|
4
|
-
from
|
4
|
+
from stoobly_orator.migrations import Migrator, DatabaseMigrationRepository
|
5
5
|
|
6
6
|
from stoobly_agent.config.data_dir import DataDir
|
7
7
|
from stoobly_agent.config.source_dir import SourceDir
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import pdb
|
2
2
|
import requests
|
3
3
|
|
4
|
-
from
|
4
|
+
from stoobly_orator.orm import belongs_to
|
5
5
|
|
6
6
|
from stoobly_agent.app.proxy.mitmproxy.response_facade import MitmproxyResponseFacade
|
7
7
|
from stoobly_agent.app.proxy.record.response_string import ResponseString
|
stoobly_agent/lib/orm/request.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import pdb
|
2
2
|
import uuid
|
3
3
|
|
4
|
-
from
|
4
|
+
from stoobly_orator.orm import belongs_to, has_many, has_one
|
5
5
|
|
6
6
|
from stoobly_agent.lib.api.keys.project_key import LOCAL_PROJECT_ID
|
7
7
|
from stoobly_agent.lib.api.keys.request_key import RequestKey
|
stoobly_agent/lib/orm/trace.py
CHANGED