stoobly-agent 0.21.2__py3-none-any.whl → 0.22.3__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.
Files changed (216) hide show
  1. stoobly_agent/__init__.py +2 -1
  2. stoobly_agent/app/api/bodies_controller.py +2 -2
  3. stoobly_agent/app/api/requests_controller.py +28 -10
  4. stoobly_agent/app/api/simple_http_request_handler.py +1 -1
  5. stoobly_agent/app/cli/ca_cert_installer.py +16 -5
  6. stoobly_agent/app/cli/config_cli.py +32 -20
  7. stoobly_agent/app/cli/helpers/context.py +7 -0
  8. stoobly_agent/app/cli/helpers/handle_mock_service.py +14 -0
  9. stoobly_agent/app/cli/helpers/print_service.py +1 -1
  10. stoobly_agent/app/cli/intercept.py +46 -2
  11. stoobly_agent/app/cli/main_group.py +3 -3
  12. stoobly_agent/app/cli/project_cli.py +3 -1
  13. stoobly_agent/app/cli/request_cli.py +6 -10
  14. stoobly_agent/app/models/adapters/mitmproxy/__init__.py +2 -0
  15. stoobly_agent/app/models/adapters/mitmproxy/request/__init__.py +12 -0
  16. stoobly_agent/app/models/adapters/mitmproxy/request/python_adapter.py +16 -0
  17. stoobly_agent/app/models/adapters/mitmproxy/response/__init__.py +12 -0
  18. stoobly_agent/app/models/adapters/mitmproxy/response/python_adapter.py +24 -0
  19. stoobly_agent/app/models/adapters/python/__init__.py +2 -0
  20. stoobly_agent/app/models/adapters/python/request/__init__.py +18 -0
  21. stoobly_agent/app/models/adapters/python/request/mitmproxy_adapter.py +53 -0
  22. stoobly_agent/app/models/adapters/python/request/stoobly_adapter.py +49 -0
  23. stoobly_agent/app/models/adapters/python/response/__init__.py +13 -0
  24. stoobly_agent/app/models/adapters/{mitmproxy_response_adapter.py → python/response/mitmproxy_adapter.py} +15 -7
  25. stoobly_agent/app/models/adapters/raw_http_response_adapter.py +10 -3
  26. stoobly_agent/app/models/adapters/stoobly/request/__init__.py +11 -0
  27. stoobly_agent/app/models/adapters/stoobly/request/mitmproxy_adapter.py +32 -0
  28. stoobly_agent/app/models/body_model.py +2 -2
  29. stoobly_agent/app/models/factories/__init__.py +0 -0
  30. stoobly_agent/app/models/factories/resource/__init__.py +0 -0
  31. stoobly_agent/app/models/{adapters/body_adapter_factory.py → factories/resource/body.py} +1 -1
  32. stoobly_agent/app/models/{adapters/header_adapter_factory.py → factories/resource/header.py} +1 -1
  33. stoobly_agent/app/models/factories/resource/local_db/__init__.py +0 -0
  34. stoobly_agent/app/models/{adapters → factories/resource}/local_db/replayed_response_adapter.py +1 -2
  35. stoobly_agent/app/models/{adapters → factories/resource}/local_db/request_adapter.py +15 -8
  36. stoobly_agent/app/models/{adapters → factories/resource}/local_db/scenario_adapter.py +13 -7
  37. stoobly_agent/app/models/{adapters/query_param_adapter_factory.py → factories/resource/query_param.py} +1 -1
  38. stoobly_agent/app/models/{adapters/replayed_response_adapter_factory.py → factories/resource/replayed_response.py} +1 -1
  39. stoobly_agent/app/models/{adapters/request_adapter_factory.py → factories/resource/request.py} +2 -2
  40. stoobly_agent/app/models/{adapters/response_adapter_factory.py → factories/resource/response.py} +1 -1
  41. stoobly_agent/app/models/{adapters/response_header_adapter_factory.py → factories/resource/response_header.py} +1 -1
  42. stoobly_agent/app/models/{adapters/scenario_adapter_factory.py → factories/resource/scenario.py} +2 -2
  43. stoobly_agent/app/models/factories/resource/stoobly/__init__.py +0 -0
  44. stoobly_agent/app/models/{adapters/stoobly_request_adapter.py → factories/resource/stoobly/request_adapter.py} +1 -2
  45. stoobly_agent/app/models/{adapters/stoobly_scenario_adapter.py → factories/resource/stoobly/scenario_adapter.py} +1 -2
  46. stoobly_agent/app/models/header_model.py +2 -2
  47. stoobly_agent/app/models/query_param_model.py +2 -2
  48. stoobly_agent/app/models/replayed_response_model.py +2 -2
  49. stoobly_agent/app/models/request_model.py +4 -5
  50. stoobly_agent/app/models/response_header_model.py +2 -2
  51. stoobly_agent/app/models/response_model.py +2 -2
  52. stoobly_agent/app/models/scenario_model.py +4 -4
  53. stoobly_agent/app/models/schemas/request.py +8 -1
  54. stoobly_agent/app/models/types/__init__.py +6 -0
  55. stoobly_agent/app/proxy/__init__.py +0 -5
  56. stoobly_agent/app/proxy/handle_mock_service.py +0 -3
  57. stoobly_agent/app/proxy/handle_test_service.py +1 -1
  58. stoobly_agent/app/proxy/intercept_handler.py +0 -1
  59. stoobly_agent/app/proxy/mitmproxy/flow_mock.py +35 -0
  60. stoobly_agent/app/proxy/mitmproxy/request_facade.py +11 -2
  61. stoobly_agent/app/proxy/replay/replay_request_service.py +57 -40
  62. stoobly_agent/app/proxy/simulate_intercept_service.py +30 -0
  63. stoobly_agent/app/proxy/test/__init__.py +1 -0
  64. stoobly_agent/app/proxy/test/context.py +2 -1
  65. stoobly_agent/app/proxy/test/context_abc.py +155 -0
  66. stoobly_agent/app/proxy/test/matchers/context.py +1 -1
  67. stoobly_agent/app/proxy/test/matchers/contract.py +1 -1
  68. stoobly_agent/app/proxy/test/matchers/custom.py +1 -1
  69. stoobly_agent/app/proxy/test/matchers/diff.py +1 -1
  70. stoobly_agent/app/proxy/test/matchers/fuzzy.py +1 -1
  71. stoobly_agent/app/proxy/test/test_service.py +1 -1
  72. stoobly_agent/app/proxy/upload/joined_request.py +0 -1
  73. stoobly_agent/app/proxy/upload/proxy_request.py +4 -1
  74. stoobly_agent/app/proxy/upload/request_string.py +1 -1
  75. stoobly_agent/app/settings/constants/mode.py +3 -0
  76. stoobly_agent/cli.py +76 -7
  77. stoobly_agent/config/constants/env_vars.py +2 -1
  78. stoobly_agent/config/data_dir.py +11 -8
  79. stoobly_agent/lib/api/api.py +4 -4
  80. stoobly_agent/lib/api/keys/organization_key.py +2 -0
  81. stoobly_agent/lib/api/keys/project_key.py +9 -0
  82. stoobly_agent/lib/api/scenarios_resource.py +1 -1
  83. stoobly_agent/lib/api/stoobly_api.py +9 -5
  84. stoobly_agent/lib/orm/__init__.py +1 -1
  85. stoobly_agent/lib/orm/replayed_response.py +3 -3
  86. stoobly_agent/lib/orm/request.py +25 -5
  87. stoobly_agent/lib/orm/transformers/orm_to_stoobly_request_transformer.py +1 -1
  88. stoobly_agent/mock.py +94 -0
  89. stoobly_agent/public/{2-es2015.3d54569af612a07a2e06.js → 1-es2015.37917aa26708d8f35d36.js} +1 -1
  90. stoobly_agent/public/{2-es5.3d54569af612a07a2e06.js → 1-es5.37917aa26708d8f35d36.js} +1 -1
  91. stoobly_agent/public/10-es2015.e9556b0d0f0e92fb548b.js +1 -0
  92. stoobly_agent/public/10-es5.e9556b0d0f0e92fb548b.js +1 -0
  93. stoobly_agent/public/11-es2015.bc6212fccbe72a623f81.js +1 -0
  94. stoobly_agent/public/11-es5.bc6212fccbe72a623f81.js +1 -0
  95. stoobly_agent/public/{13-es2015.76b6c147b0c46f995cd7.js → 12-es2015.d0768894ddffd6efa5e5.js} +1 -1
  96. stoobly_agent/public/{13-es5.76b6c147b0c46f995cd7.js → 12-es5.d0768894ddffd6efa5e5.js} +1 -1
  97. stoobly_agent/public/13-es2015.8a044490a76fd298162d.js +1 -0
  98. stoobly_agent/public/13-es5.8a044490a76fd298162d.js +1 -0
  99. stoobly_agent/public/{15-es2015.60c3b41c385f5bdedb7b.js → 14-es2015.1cd1a021e51ca0e62e1c.js} +1 -1
  100. stoobly_agent/public/{15-es5.60c3b41c385f5bdedb7b.js → 14-es5.1cd1a021e51ca0e62e1c.js} +1 -1
  101. stoobly_agent/public/{16-es2015.5d395009a77978db4405.js → 15-es2015.587781d19864ff0eb4f5.js} +1 -1
  102. stoobly_agent/public/{16-es5.5d395009a77978db4405.js → 15-es5.587781d19864ff0eb4f5.js} +1 -1
  103. stoobly_agent/public/16-es2015.ec6a175b1f9578203cd8.js +1 -0
  104. stoobly_agent/public/16-es5.ec6a175b1f9578203cd8.js +1 -0
  105. stoobly_agent/public/17-es2015.ad9c4756c96a15bd29d7.js +1 -0
  106. stoobly_agent/public/17-es5.ad9c4756c96a15bd29d7.js +1 -0
  107. stoobly_agent/public/{19-es2015.517f68e08f4c582dae66.js → 18-es2015.8583df0f8eccb3e47c0b.js} +1 -1
  108. stoobly_agent/public/{19-es5.517f68e08f4c582dae66.js → 18-es5.8583df0f8eccb3e47c0b.js} +1 -1
  109. stoobly_agent/public/{20-es2015.473486aabfa4d4a6431b.js → 19-es2015.d0225852a844dc03a09f.js} +1 -1
  110. stoobly_agent/public/{20-es5.473486aabfa4d4a6431b.js → 19-es5.d0225852a844dc03a09f.js} +1 -1
  111. stoobly_agent/public/{3-es5.1dad290844ea619e4c16.js → 2-es2015.8f184ac63348ba447b1f.js} +1 -1
  112. stoobly_agent/public/{3-es2015.1dad290844ea619e4c16.js → 2-es5.8f184ac63348ba447b1f.js} +1 -1
  113. stoobly_agent/public/{21-es2015.56aa10803cc1348a55a3.js → 20-es2015.f7c107847935264d58aa.js} +1 -1
  114. stoobly_agent/public/{21-es5.56aa10803cc1348a55a3.js → 20-es5.f7c107847935264d58aa.js} +1 -1
  115. stoobly_agent/public/{22-es2015.46d81010003b2a50eeab.js → 21-es2015.dd358e1edaf3d32dd2c0.js} +1 -1
  116. stoobly_agent/public/{22-es5.46d81010003b2a50eeab.js → 21-es5.dd358e1edaf3d32dd2c0.js} +1 -1
  117. stoobly_agent/public/26-es2015.6332c32f1b7c8c288f2f.js +1 -0
  118. stoobly_agent/public/26-es5.6332c32f1b7c8c288f2f.js +1 -0
  119. stoobly_agent/public/27-es2015.af505e744b0c869a93d1.js +1 -0
  120. stoobly_agent/public/27-es5.af505e744b0c869a93d1.js +1 -0
  121. stoobly_agent/public/28-es2015.7c7c0f64e4af29d2e4d4.js +1 -0
  122. stoobly_agent/public/28-es5.7c7c0f64e4af29d2e4d4.js +1 -0
  123. stoobly_agent/public/32-es2015.2ab8267be7275dee9059.js +1 -0
  124. stoobly_agent/public/32-es5.2ab8267be7275dee9059.js +1 -0
  125. stoobly_agent/public/{34-es2015.ef24f6f7630620a38b19.js → 33-es2015.5b575f3a87c6c2c6b93b.js} +1 -1
  126. stoobly_agent/public/{34-es5.ef24f6f7630620a38b19.js → 33-es5.5b575f3a87c6c2c6b93b.js} +1 -1
  127. stoobly_agent/public/{35-es2015.0667e742725cc828f59f.js → 34-es2015.6a1160649c718cdb9338.js} +1 -1
  128. stoobly_agent/public/{35-es5.0667e742725cc828f59f.js → 34-es5.6a1160649c718cdb9338.js} +1 -1
  129. stoobly_agent/public/35-es2015.1b9dc7a46a6d5296c3ae.js +1 -0
  130. stoobly_agent/public/35-es5.1b9dc7a46a6d5296c3ae.js +1 -0
  131. stoobly_agent/public/{37-es2015.50d0c2d3fe4d0a74fc8f.js → 36-es2015.2fc9151fe6a5ff2bff31.js} +1 -1
  132. stoobly_agent/public/{37-es5.50d0c2d3fe4d0a74fc8f.js → 36-es5.2fc9151fe6a5ff2bff31.js} +1 -1
  133. stoobly_agent/public/{38-es2015.c14bde0b8d0cc14e915e.js → 37-es2015.ac7108c3625fd6e1d981.js} +1 -1
  134. stoobly_agent/public/{38-es5.c14bde0b8d0cc14e915e.js → 37-es5.ac7108c3625fd6e1d981.js} +1 -1
  135. stoobly_agent/public/38-es2015.9c183b14373c0e449932.js +1 -0
  136. stoobly_agent/public/38-es5.9c183b14373c0e449932.js +1 -0
  137. stoobly_agent/public/39-es2015.4624cdeb29fe9850b216.js +1 -0
  138. stoobly_agent/public/39-es5.4624cdeb29fe9850b216.js +1 -0
  139. stoobly_agent/public/40-es2015.24d981230c0c8f369cde.js +1 -0
  140. stoobly_agent/public/40-es5.24d981230c0c8f369cde.js +1 -0
  141. stoobly_agent/public/{46-es2015.abc7e4fd207d54277fcb.js → 45-es2015.c76937ed45d460bcd36f.js} +1 -1
  142. stoobly_agent/public/{46-es5.abc7e4fd207d54277fcb.js → 45-es5.c76937ed45d460bcd36f.js} +1 -1
  143. stoobly_agent/public/6-es2015.53acc5d2ca7f48ef857f.js +1 -0
  144. stoobly_agent/public/6-es5.53acc5d2ca7f48ef857f.js +1 -0
  145. stoobly_agent/public/7-es2015.1c6b3d315d50ccd228cb.js +1 -0
  146. stoobly_agent/public/7-es5.1c6b3d315d50ccd228cb.js +1 -0
  147. stoobly_agent/public/{9-es2015.ef0f7cb32f5fadb085d0.js → 8-es2015.0fe7492f7b61eb4699b6.js} +1 -1
  148. stoobly_agent/public/{9-es5.ef0f7cb32f5fadb085d0.js → 8-es5.0fe7492f7b61eb4699b6.js} +1 -1
  149. stoobly_agent/public/common-es2015.86f70de6df2c705a87f6.js +1 -0
  150. stoobly_agent/public/common-es5.86f70de6df2c705a87f6.js +1 -0
  151. stoobly_agent/public/dashboard.agent-alpha-0.22.3.tar.gz +0 -0
  152. stoobly_agent/public/index.html +1 -1
  153. stoobly_agent/public/main-es2015.aceb967cb4cccc0bc521.js +1 -0
  154. stoobly_agent/public/main-es5.aceb967cb4cccc0bc521.js +1 -0
  155. stoobly_agent/public/{polyfills-es2015.2b40b2ecdf98a9210572.js → polyfills-es2015.580f7a6e775c2c348c9d.js} +1 -1
  156. stoobly_agent/public/{polyfills-es5.d9fb2eee68607c3f7f64.js → polyfills-es5.4c3461a071d35be3dd81.js} +1 -1
  157. stoobly_agent/public/runtime-es2015.49eaebd2913fa7fe2b97.js +1 -0
  158. stoobly_agent/public/runtime-es5.49eaebd2913fa7fe2b97.js +1 -0
  159. stoobly_agent/test/test_helper.py +4 -5
  160. {stoobly_agent-0.21.2.dist-info → stoobly_agent-0.22.3.dist-info}/METADATA +1 -1
  161. {stoobly_agent-0.21.2.dist-info → stoobly_agent-0.22.3.dist-info}/RECORD +175 -157
  162. {stoobly_agent-0.21.2.dist-info → stoobly_agent-0.22.3.dist-info}/WHEEL +1 -1
  163. stoobly_agent/app/models/adapters/mitmproxy_request_adapter.py +0 -60
  164. stoobly_agent/app/models/adapters/types/__init__.py +0 -3
  165. stoobly_agent/public/11-es2015.b85bdc528bab0ee542fe.js +0 -1
  166. stoobly_agent/public/11-es5.b85bdc528bab0ee542fe.js +0 -1
  167. stoobly_agent/public/12-es2015.72399d40488de533bb97.js +0 -1
  168. stoobly_agent/public/12-es5.72399d40488de533bb97.js +0 -1
  169. stoobly_agent/public/14-es2015.7cedfd0829bd7a64677a.js +0 -1
  170. stoobly_agent/public/14-es5.7cedfd0829bd7a64677a.js +0 -1
  171. stoobly_agent/public/17-es2015.f6f28ba9f681063632a8.js +0 -1
  172. stoobly_agent/public/17-es5.f6f28ba9f681063632a8.js +0 -1
  173. stoobly_agent/public/18-es2015.b0cd6822ebd1090b0d60.js +0 -1
  174. stoobly_agent/public/18-es5.b0cd6822ebd1090b0d60.js +0 -1
  175. stoobly_agent/public/27-es2015.4635450ff709f7868796.js +0 -1
  176. stoobly_agent/public/27-es5.4635450ff709f7868796.js +0 -1
  177. stoobly_agent/public/28-es2015.1b29b35529772ab108f1.js +0 -1
  178. stoobly_agent/public/28-es5.1b29b35529772ab108f1.js +0 -1
  179. stoobly_agent/public/32-es2015.862b67803e6242451976.js +0 -1
  180. stoobly_agent/public/32-es5.862b67803e6242451976.js +0 -1
  181. stoobly_agent/public/33-es2015.4ff4325d1aec37e1b43c.js +0 -1
  182. stoobly_agent/public/33-es5.4ff4325d1aec37e1b43c.js +0 -1
  183. stoobly_agent/public/36-es2015.cd370fdf8990019d0c8e.js +0 -1
  184. stoobly_agent/public/36-es5.cd370fdf8990019d0c8e.js +0 -1
  185. stoobly_agent/public/39-es2015.4ec5fc16202c4759eac4.js +0 -1
  186. stoobly_agent/public/39-es5.4ec5fc16202c4759eac4.js +0 -1
  187. stoobly_agent/public/40-es2015.25287ce77b40050f3471.js +0 -1
  188. stoobly_agent/public/40-es5.25287ce77b40050f3471.js +0 -1
  189. stoobly_agent/public/45-es2015.fd110741ac0fbaada177.js +0 -1
  190. stoobly_agent/public/45-es5.fd110741ac0fbaada177.js +0 -1
  191. stoobly_agent/public/6-es2015.7219d596e3545ebaed3a.js +0 -1
  192. stoobly_agent/public/6-es5.7219d596e3545ebaed3a.js +0 -1
  193. stoobly_agent/public/7-es2015.98b085349ebd9d246060.js +0 -1
  194. stoobly_agent/public/7-es5.98b085349ebd9d246060.js +0 -1
  195. stoobly_agent/public/8-es2015.335fd5c122ad083aec65.js +0 -1
  196. stoobly_agent/public/8-es5.335fd5c122ad083aec65.js +0 -1
  197. stoobly_agent/public/common-es2015.81f870bf87411a04446d.js +0 -1
  198. stoobly_agent/public/common-es5.81f870bf87411a04446d.js +0 -1
  199. stoobly_agent/public/dashboard.agent-alpha-0.21.0.tar.gz +0 -0
  200. stoobly_agent/public/main-es2015.575c1d17fc866d3a6649.js +0 -1
  201. stoobly_agent/public/main-es5.575c1d17fc866d3a6649.js +0 -1
  202. stoobly_agent/public/runtime-es2015.8915d042dc9b55368999.js +0 -1
  203. stoobly_agent/public/runtime-es5.8915d042dc9b55368999.js +0 -1
  204. /stoobly_agent/app/models/adapters/{local_db → stoobly}/__init__.py +0 -0
  205. /stoobly_agent/app/models/{adapters → factories/resource}/local_db/body_adapter.py +0 -0
  206. /stoobly_agent/app/models/{adapters → factories/resource}/local_db/header_adapter.py +0 -0
  207. /stoobly_agent/app/models/{adapters → factories/resource}/local_db/query_param_adapter.py +0 -0
  208. /stoobly_agent/app/models/{adapters → factories/resource}/local_db/response_adapter.py +0 -0
  209. /stoobly_agent/app/models/{adapters → factories/resource}/local_db/response_header_adapter.py +0 -0
  210. /stoobly_agent/app/models/{adapters/types → types}/replayed_response.py +0 -0
  211. /stoobly_agent/app/models/{adapters/types → types}/request_create_params.py +0 -0
  212. /stoobly_agent/app/models/{adapters/types → types}/request_show_params.py +0 -0
  213. /stoobly_agent/app/models/{adapters/types → types}/scenario_create_params.py +0 -0
  214. {stoobly_agent-0.21.2.dist-info → stoobly_agent-0.22.3.dist-info}/LICENSE +0 -0
  215. {stoobly_agent-0.21.2.dist-info → stoobly_agent-0.22.3.dist-info}/entry_points.txt +0 -0
  216. {stoobly_agent-0.21.2.dist-info → stoobly_agent-0.22.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,35 @@
1
+ import requests
2
+
3
+ from mitmproxy.http import Request as MitmproxyRequest, Response as MitmproxyResponse
4
+ from typing import Union
5
+
6
+ from stoobly_agent.app.models.adapters.python import PythonRequestAdapterFactory, PythonResponseAdapterFactory
7
+ from stoobly_agent.app.models.adapters.raw_http_request_adapter import DEFAULT_HTTP_VERSION
8
+
9
+ class MitmproxyFlowMock():
10
+
11
+ def __init__(self):
12
+ self.__request: MitmproxyRequest = None
13
+ self.__response: MitmproxyResponse = None
14
+
15
+ @property
16
+ def request(self):
17
+ return self.__request
18
+
19
+ @property
20
+ def response(self):
21
+ return self.__response
22
+
23
+ @request.setter
24
+ def request(self, _request: Union[MitmproxyRequest, requests.Request]):
25
+ if isinstance(_request, requests.Request):
26
+ self.__request = PythonRequestAdapterFactory(_request).mitmproxy_request(DEFAULT_HTTP_VERSION)
27
+ else:
28
+ self.__request = _request
29
+
30
+ @response.setter
31
+ def response(self, _response: Union[MitmproxyResponse, requests.Response]):
32
+ if isinstance(_response, requests.Response):
33
+ self.__response = PythonResponseAdapterFactory(_response).mitmproxy_response()
34
+ else:
35
+ self.__response = _response
@@ -5,6 +5,7 @@ from mitmproxy.http import Headers, Request as MitmproxyRequest
5
5
  from mitmproxy.coretypes import multidict
6
6
  from typing import Callable, List, Union
7
7
  from urllib.parse import urlparse
8
+ import requests
8
9
 
9
10
  from stoobly_agent.app.settings.constants import request_component
10
11
  from stoobly_agent.app.settings.rewrite_rule import RewriteRule, ParameterRule
@@ -53,7 +54,7 @@ class MitmproxyRequestFacade(Request):
53
54
 
54
55
  @property
55
56
  def body(self):
56
- content = self.request.raw_content
57
+ content = self.request.raw_content or ''
57
58
 
58
59
  try:
59
60
  if isinstance(content, bytes):
@@ -96,6 +97,14 @@ class MitmproxyRequestFacade(Request):
96
97
  def rewrite_rules(self) -> List[ParameterRule]:
97
98
  return self.__rewrite_rules
98
99
 
100
+ def to_python_request(self):
101
+ return requests.Request(
102
+ method=self.request.method,
103
+ url=self.request.url,
104
+ headers=self.request.headers,
105
+ data=self.request.content
106
+ )
107
+
99
108
  def with_rewrite_rules(self, rules: List[RewriteRule]):
100
109
  if type(rules) == list:
101
110
  self.__rewrite_rules = self.select_parameter_rules(rules)
@@ -154,7 +163,7 @@ class MitmproxyRequestFacade(Request):
154
163
  })
155
164
 
156
165
  def __rewrite_handler(self, rewrite: ParameterRule) -> str:
157
- Logger.instance().debug(f"{bcolors.OKCYAN}Rewriting{bcolors.ENDC} {rewrite.name} => {rewrite.value}")
166
+ Logger.instance().info(f"{bcolors.OKCYAN}Rewriting {rewrite.type.lower()}{bcolors.ENDC} {rewrite.name} => {rewrite.value}")
158
167
  return rewrite.value
159
168
 
160
169
  def __rewrite_headers(self, rewrites: List[ParameterRule]):
@@ -5,16 +5,17 @@ import requests
5
5
  from http.cookies import SimpleCookie
6
6
  from typing import Callable, TypedDict, Union
7
7
 
8
+ from stoobly_agent.app.cli.ca_cert_installer import CACertInstaller
8
9
  from stoobly_agent.app.cli.helpers.context import ReplayContext
9
10
  from stoobly_agent.app.models.schemas.request import Request
10
11
  from stoobly_agent.app.proxy.intercept_settings import InterceptSettings
11
12
  from stoobly_agent.app.proxy.mitmproxy.request_facade import MitmproxyRequestFacade
12
13
  from stoobly_agent.app.proxy.replay.trace_context import TraceContext
14
+ from stoobly_agent.app.proxy.simulate_intercept_service import simulate_intercept
13
15
  from stoobly_agent.app.settings import Settings
14
16
  from stoobly_agent.config.constants import alias_resolve_strategy, custom_headers, request_origin, test_filter, test_strategy
15
17
  from stoobly_agent.config.mitmproxy import MitmproxyConfig
16
- from stoobly_agent.config.constants import mode
17
- from stoobly_agent.lib.api.api import Api
18
+ from stoobly_agent.config.constants import mock_policy, mode
18
19
 
19
20
  class ReplayRequestOptions(TypedDict):
20
21
  alias_resolve_strategy: alias_resolve_strategy.AliasResolveStrategy
@@ -25,6 +26,7 @@ class ReplayRequestOptions(TypedDict):
25
26
  before_replay: Union[Callable[[ReplayContext], None], None]
26
27
  after_replay: Union[Callable[[ReplayContext], Union[requests.Response, None]], None]
27
28
  project_key: Union[str, None]
29
+ proxies: dict
28
30
  report_key: Union[str, None]
29
31
  request_origin: Union[request_origin.CLI, None]
30
32
  scenario_key: Union[str, None]
@@ -37,17 +39,14 @@ def replay_with_trace(context: ReplayContext, trace_context: TraceContext, optio
37
39
  trace_context.alias_resolve_strategy = options.get('alias_resolve_strategy')
38
40
  return trace_context.with_replay_context(context, lambda context: replay(context, options))
39
41
 
40
- def replay_with_rewrite(context: ReplayContext) -> requests.Response:
41
- return replay(context, {
42
- 'before_replay': __handle_before_replay
43
- })
44
-
45
42
  def replay(context: ReplayContext, options: ReplayRequestOptions) -> requests.Response:
46
43
  if 'before_replay' in options and callable(options['before_replay']):
47
44
  options['before_replay'](context)
48
45
 
49
46
  request = context.request
50
47
  headers = request.headers
48
+ method = request.method
49
+ cookies = __get_cookies(headers)
51
50
 
52
51
  if options.get('host'):
53
52
  request.host = options['host']
@@ -56,48 +55,70 @@ def replay(context: ReplayContext, options: ReplayRequestOptions) -> requests.Re
56
55
  if options.get('scheme'):
57
56
  request.scheme = options['scheme']
58
57
 
59
- if 'alias_resolve_strategy' in options:
58
+ if options.get('alias_resolve_strategy'):
60
59
  headers[custom_headers.ALIAS_RESOLVE_STRATEGY] = options['alias_resolve_strategy']
61
60
 
62
- if 'lifecycle_hooks_script_path' in options:
61
+ if options.get('lifecycle_hooks_script_path'):
63
62
  __handle_lifecycle_hooks_script_path(options['lifecycle_hooks_script_path'], headers)
64
63
 
65
- if 'mode' in options:
64
+ if options.get('mode'):
66
65
  __handle_mode_option(options['mode'], request, headers)
67
66
 
68
- if 'project_key' in options:
67
+ if options.get('project_key'):
69
68
  headers[custom_headers.PROJECT_KEY] = options['project_key']
70
69
 
71
- if 'report_key' in options:
70
+ if options.get('report_key'):
72
71
  headers[custom_headers.REPORT_KEY] = options['report_key']
73
72
 
74
- if 'request_origin' in options:
73
+ if options.get('request_origin'):
75
74
  headers[custom_headers.REQUEST_ORIGIN] = options['request_origin']
76
75
 
77
- if 'scenario_key' in options:
76
+ if options.get('scenario_key'):
78
77
  headers[custom_headers.SCENARIO_KEY] = options['scenario_key']
79
78
 
80
- if 'test_filter' in options:
79
+ if options.get('test_filter'):
81
80
  headers[custom_headers.TEST_FILTER] = options['test_filter']
82
81
 
83
- if 'test_strategy' in options:
82
+ if options.get('test_strategy'):
84
83
  headers[custom_headers.TEST_STRATEGY] = options['test_strategy']
85
84
 
86
- method = request.method
87
- handler = getattr(requests, method.lower())
88
- cookies = __get_cookies(request.headers)
89
-
90
- # Set proxy env vars to ensure request gets sent to proxy
91
- res: requests.Response = Api().with_proxy(lambda: handler(
92
- request.url,
93
- allow_redirects = True,
94
- cookies = cookies,
95
- data=request.body,
96
- headers=headers,
97
- #params=request.query_params, # Do not send query params, they should be a part of the URL
98
- stream = True,
99
- verify = not MitmproxyConfig.instance().get('ssl_insecure')
100
- ))
85
+ request_config = {
86
+ 'allow_redirects': True,
87
+ 'stream': True,
88
+ 'verify': not MitmproxyConfig.instance().get('ssl_insecure')
89
+ }
90
+ request_dict = {
91
+ 'cookies': cookies,
92
+ 'data': request.body,
93
+ 'headers': headers,
94
+ #'params': request.query_params, # Do not send query params, they should be a part of the URL
95
+ }
96
+
97
+ res: requests.Response = None
98
+ if not options.get('proxy'):
99
+ request = requests.Request(**{
100
+ **request_dict,
101
+ 'method': method,
102
+ 'url': request.url,
103
+ })
104
+
105
+ res = simulate_intercept(request, **request_config)
106
+ else:
107
+ settings = Settings.instance()
108
+ handler = getattr(requests, method.lower())
109
+
110
+ res = handler(
111
+ request.url,
112
+ **{
113
+ **request_config,
114
+ **request_dict,
115
+ 'proxies': {
116
+ 'http': settings.proxy.url,
117
+ 'https': settings.proxy.url,
118
+ },
119
+ 'verify': CACertInstaller().mitm_crt_absolute_path if request_config['verify'] else False,
120
+ }
121
+ )
101
122
 
102
123
  if 'after_replay' in options and callable(options['after_replay']):
103
124
  context.with_response(res)
@@ -119,7 +140,10 @@ def __handle_mode_option(_mode, request: Request, headers):
119
140
 
120
141
  if _mode == mode.MOCK or _mode == mode.TEST:
121
142
  # If mocking or testing, we already know which request to get response from
122
- headers[custom_headers.MOCK_REQUEST_ID] = str(request.id)
143
+ if request.id:
144
+ headers[custom_headers.MOCK_REQUEST_ID] = str(request.id)
145
+
146
+ headers[custom_headers.MOCK_POLICY] = mock_policy.ALL
123
147
  elif _mode == mode.RECORD:
124
148
  # If recording, then it's actually a replay and record
125
149
  headers[custom_headers.PROXY_MODE] = mode.REPLAY
@@ -127,11 +151,4 @@ def __handle_mode_option(_mode, request: Request, headers):
127
151
 
128
152
  def __get_cookies(headers: Request.headers):
129
153
  cookies = SimpleCookie(headers.get('Cookie')).items()
130
- return {k: v.value for k, v in cookies}
131
-
132
- def __handle_before_replay(context: ReplayContext):
133
- request = context.request
134
- request_facade = MitmproxyRequestFacade(request)
135
- intercept_settings = InterceptSettings(Settings.instance())
136
- rewrite_rules = intercept_settings.replay_rewrite_rules
137
- request_facade.with_rewrite_rules(rewrite_rules).rewrite()
154
+ return {k: v.value for k, v in cookies}
@@ -0,0 +1,30 @@
1
+ import pdb
2
+ import requests
3
+
4
+ from mitmproxy.http import Request as MitmproxyRequest
5
+
6
+ from stoobly_agent.app.proxy.mitmproxy.flow_mock import MitmproxyFlowMock
7
+ from stoobly_agent.app.models.adapters.mitmproxy import MitmproxyRequestAdapterFactory, MitmproxyResponseAdapterFactory
8
+
9
+ from .intercept_handler import request as handle_request, response as handle_response
10
+
11
+ def simulate_intercept(request: requests.Request, **config):
12
+ flow = MitmproxyFlowMock()
13
+
14
+ flow.request = request
15
+
16
+ handle_request(flow)
17
+
18
+ if not flow.response:
19
+ session = requests.Session()
20
+ prepared_request = __prepare_mitmproxy_request(flow.request)
21
+ res = session.send(prepared_request, **config)
22
+ flow.response = res
23
+
24
+ handle_response(flow)
25
+
26
+ return MitmproxyResponseAdapterFactory(flow.response).python_response()
27
+
28
+ def __prepare_mitmproxy_request(request: MitmproxyRequest) -> requests.Request:
29
+ _request = MitmproxyRequestAdapterFactory(request).python_request()
30
+ return _request.prepare()
@@ -1,2 +1,3 @@
1
1
  from .context import TestContext
2
+ from .context_abc import TestContextABC
2
3
  from .context_response import TestContextResponse
@@ -20,10 +20,11 @@ from stoobly_agent.lib.api.interfaces.endpoints import EndpointShowResponse
20
20
  from stoobly_agent.lib.orm.trace import Trace
21
21
 
22
22
  from .context_response import TestContextResponse
23
+ from .context_abc import TestContextABC
23
24
 
24
25
  FuzzyContent = Union[dict, list, str]
25
26
 
26
- class TestContext():
27
+ class TestContext(TestContextABC):
27
28
  def __init__(self, replay_context: ReplayContext, mock_context: MockContext):
28
29
  self.__flow = mock_context.flow
29
30
  self.__intercept_settings = mock_context.intercept_settings
@@ -0,0 +1,155 @@
1
+ import abc
2
+
3
+ from mitmproxy.http import Request
4
+ from typing import Union
5
+
6
+ from stoobly_agent.app.proxy.test.helpers.endpoint_facade import EndpointFacade
7
+ from stoobly_agent.app.proxy.test.helpers.request_component_names_facade import RequestComponentNamesFacade
8
+
9
+ from stoobly_agent.lib.api.interfaces.endpoints import EndpointShowResponse
10
+ from stoobly_agent.lib.orm.trace import Trace
11
+
12
+ from .context_response import TestContextResponse
13
+
14
+ FuzzyContent = Union[dict, list, str]
15
+
16
+ class TestContextABC(abc.ABC):
17
+
18
+ @abc.abstractmethod
19
+ def with_endpoints_resource(self, resource: EndpointShowResponse):
20
+ pass
21
+
22
+ @property
23
+ @abc.abstractmethod
24
+ def cached_expected_response_content(self) -> Union[bytes, None, str]:
25
+ pass
26
+
27
+ @property
28
+ @abc.abstractmethod
29
+ def endpoint(self) -> EndpointFacade:
30
+ pass
31
+
32
+ @property
33
+ @abc.abstractmethod
34
+ def lifecycle_hooks(self):
35
+ pass
36
+
37
+ @property
38
+ @abc.abstractmethod
39
+ def lifecycle_hooks_script_path(self):
40
+ pass
41
+
42
+ @property
43
+ @abc.abstractmethod
44
+ def end_time(self):
45
+ pass
46
+
47
+ @property
48
+ @abc.abstractmethod
49
+ def expected_response(self) -> TestContextResponse:
50
+ pass
51
+
52
+ @property
53
+ @abc.abstractmethod
54
+ def decoded_response_content(self) -> FuzzyContent:
55
+ pass
56
+
57
+ @property
58
+ @abc.abstractmethod
59
+ def decoded_expected_response_content(self) -> FuzzyContent:
60
+ pass
61
+
62
+ @property
63
+ @abc.abstractmethod
64
+ def filter(self):
65
+ pass
66
+
67
+ @property
68
+ @abc.abstractmethod
69
+ def flow(self):
70
+ pass
71
+
72
+ @property
73
+ @abc.abstractmethod
74
+ def intercept_settings(self):
75
+ pass
76
+
77
+ @property
78
+ @abc.abstractmethod
79
+ def log(self):
80
+ pass
81
+
82
+ @log.setter
83
+ @abc.abstractmethod
84
+ def log(self, v: str):
85
+ pass
86
+
87
+ @property
88
+ @abc.abstractmethod
89
+ def mock_request_id(self) -> Union[str, None]:
90
+ pass
91
+
92
+ @property
93
+ @abc.abstractmethod
94
+ def mock_request_endpoint_id(self) -> Union[str, None]:
95
+ pass
96
+
97
+ @property
98
+ @abc.abstractmethod
99
+ def passed(self):
100
+ pass
101
+
102
+ @passed.setter
103
+ @abc.abstractmethod
104
+ def passed(self, v):
105
+ pass
106
+
107
+ @property
108
+ @abc.abstractmethod
109
+ def request(self) -> Request:
110
+ pass
111
+
112
+ @property
113
+ @abc.abstractmethod
114
+ def request_headers(self):
115
+ pass
116
+
117
+ @property
118
+ @abc.abstractmethod
119
+ def response(self) -> TestContextResponse:
120
+ pass
121
+
122
+ @property
123
+ @abc.abstractmethod
124
+ def response_param_names(self) -> RequestComponentNamesFacade:
125
+ pass
126
+
127
+ @property
128
+ @abc.abstractmethod
129
+ def rewritten_expected_response_content(self):
130
+ pass
131
+
132
+ @property
133
+ @abc.abstractmethod
134
+ def skipped(self):
135
+ pass
136
+
137
+ @skipped.setter
138
+ @abc.abstractmethod
139
+ def skipped(self, v: bool):
140
+ pass
141
+
142
+ @property
143
+ @abc.abstractmethod
144
+ def start_time(self):
145
+ pass
146
+
147
+ @property
148
+ @abc.abstractmethod
149
+ def strategy(self):
150
+ pass
151
+
152
+ @property
153
+ @abc.abstractmethod
154
+ def trace(self) -> Union[Trace, None]:
155
+ pass
@@ -2,7 +2,7 @@ import pdb
2
2
 
3
3
  from typing import Iterable, List, TypedDict, Union
4
4
 
5
- from stoobly_agent.app.proxy.test.context import TestContext
5
+ from stoobly_agent.app.proxy.test.context_abc import TestContextABC as TestContext
6
6
  from stoobly_agent.app.proxy.test.helpers.request_component_names_facade import RequestComponentNamesFacade
7
7
  from stoobly_agent.lib.api.interfaces.endpoints import RequestComponentName, ResponseParamName
8
8
  from stoobly_agent.lib.utils.python_to_ruby_type import convert
@@ -5,7 +5,7 @@ from typing import List, Tuple, TypedDict, Union
5
5
  from stoobly_agent.app.proxy.test.helpers.request_component_names_facade import RequestComponentNamesFacade
6
6
  from stoobly_agent.lib.api.interfaces.endpoints import RequestComponentName
7
7
 
8
- from ..context import TestContext
8
+ from ..context_abc import TestContextABC as TestContext
9
9
  from .context import MatchContext, build_match_context
10
10
  from .errors import length_match_error, param_name_exists_error, param_name_missing_error, type_match_error, valid_type_error
11
11
 
@@ -1,4 +1,4 @@
1
- from stoobly_agent.app.proxy.test.context import TestContext
1
+ from stoobly_agent.app.proxy.test.context_abc import TestContextABC as TestContext
2
2
 
3
3
  def matches(context: TestContext):
4
4
  lifecycle_hooks = context.lifecycle_hooks
@@ -1,7 +1,7 @@
1
1
  import pdb
2
2
 
3
3
  from typing import Tuple
4
- from stoobly_agent.app.proxy.test.context import TestContext
4
+ from stoobly_agent.app.proxy.test.context_abc import TestContextABC as TestContext
5
5
 
6
6
  from stoobly_agent.app.proxy.test.helpers.request_component_names_facade import RequestComponentNamesFacade
7
7
  from stoobly_agent.app.proxy.test.matchers.errors import length_match_error, param_name_missing_error, type_match_error, value_match_error
@@ -1,7 +1,7 @@
1
1
  import pdb
2
2
 
3
3
  from typing import Iterable, Tuple
4
- from stoobly_agent.app.proxy.test.context import TestContext
4
+ from stoobly_agent.app.proxy.test.context_abc import TestContextABC as TestContext
5
5
  from stoobly_agent.app.proxy.test.helpers.request_component_names_facade import RequestComponentNamesFacade
6
6
  from stoobly_agent.app.proxy.test.matchers.errors import param_name_missing_error, type_match_error, valid_type_error
7
7
 
@@ -4,7 +4,7 @@ from stoobly_agent.app.proxy.replay.body_parser_service import decode_response,
4
4
 
5
5
  from stoobly_agent.config.constants import test_strategy
6
6
 
7
- from .context import TestContext
7
+ from .context_abc import TestContextABC as TestContext
8
8
  from .matchers.custom import matches as custom_matches
9
9
  from .matchers.contract import matches as contract_matches
10
10
  from .matchers.diff import matches as diff_matches
@@ -53,5 +53,4 @@ class JoinedRequest:
53
53
  response_string = self.__response_string.get(control=True)
54
54
 
55
55
  joined = self.REQUEST_DELIMITTER.join([request_string, response_string])
56
-
57
56
  return joined
@@ -1,7 +1,7 @@
1
1
  from ..mitmproxy.request_facade import MitmproxyRequestFacade
2
2
 
3
3
  class ProxyRequest:
4
- def __init__(self, request: MitmproxyRequestFacade, upstream_url: str):
4
+ def __init__(self, request: MitmproxyRequestFacade, upstream_url: str = None):
5
5
  self.request = request
6
6
 
7
7
  self.upstream_url = upstream_url
@@ -9,4 +9,7 @@ class ProxyRequest:
9
9
  def url(self):
10
10
  url = self.request.url
11
11
 
12
+ if not self.upstream_url:
13
+ return url
14
+
12
15
  return url.replace(self.request.base_url, self.upstream_url)
@@ -74,7 +74,7 @@ class RequestString:
74
74
  toks = header.split('_')
75
75
 
76
76
  for index, tok in enumerate(toks):
77
- toks[index] = tok.lower().capitalize()
77
+ toks[index] = tok.lower().title()
78
78
 
79
79
  return "-".join(toks)
80
80
 
@@ -0,0 +1,3 @@
1
+ TEST = 'test'
2
+ DEVELOPMENT = 'development'
3
+ PRODUCTION = 'production'
stoobly_agent/cli.py CHANGED
@@ -1,16 +1,21 @@
1
1
  import click
2
2
  import os
3
3
  import pdb
4
+ import requests
4
5
  import sys
5
6
 
6
7
  from stoobly_agent import VERSION
7
- from stoobly_agent.config.constants import env_vars
8
+ from stoobly_agent.app.cli.helpers.context import ReplayContext
9
+ from stoobly_agent.app.cli.helpers.handle_mock_service import print_raw_response, RAW_FORMAT
10
+ from stoobly_agent.app.proxy.constants import custom_response_codes
11
+ from stoobly_agent.app.proxy.replay.replay_request_service import replay as replay_request
12
+ from stoobly_agent.config.constants import env_vars, mode
8
13
  from stoobly_agent.config.data_dir import DataDir
9
14
  from stoobly_agent.lib.utils.conditional_decorator import ConditionalDecorator
10
15
 
11
16
  from .app.api import run as run_api
12
17
  from .app.cli import ca_cert, config, feature, intercept, MainGroup, request, scenario, trace
13
- from .app.proxy import CONNECTION_STRATEGIES, INTERCEPT_MODES, run as run_proxy
18
+ from .app.proxy import CONNECTION_STRATEGIES, run as run_proxy
14
19
  from .app.settings import Settings
15
20
  from .lib import logger
16
21
  from .lib.orm.migrate_service import migrate as migrate_database
@@ -67,7 +72,6 @@ def init(**kwargs):
67
72
  @ConditionalDecorator(lambda f: click.option('--api-url', help='API URL.')(f), is_remote)
68
73
  @click.option('--headless', is_flag=True, default=False, help='Disable starting UI.')
69
74
  @click.option('--connection-strategy', help=', '.join(CONNECTION_STRATEGIES), type=click.Choice(CONNECTION_STRATEGIES))
70
- @click.option('--intercept-mode', help=', '.join(INTERCEPT_MODES), type=click.Choice(INTERCEPT_MODES))
71
75
  @click.option('--log-level', default=logger.INFO, type=click.Choice([logger.DEBUG, logger.INFO, logger.WARNING, logger.ERROR]), help='''
72
76
  Log levels can be "debug", "info", "warning", or "error"
73
77
  ''')
@@ -94,8 +98,73 @@ def run(**kwargs):
94
98
  if 'headless' in kwargs and not kwargs['headless']:
95
99
  run_api(**kwargs)
96
100
 
97
- if kwargs['intercept_mode'] and kwargs['intercept_mode'] not in INTERCEPT_MODES:
98
- print(f"Error: Invalid value for --intercept-mode, values: {', '.join(INTERCEPT_MODES)}", file=sys.stderr)
99
- sys.exit(1)
101
+ run_proxy(**kwargs)
100
102
 
101
- run_proxy(**kwargs)
103
+ @main.command(
104
+ help="Mock request"
105
+ )
106
+ @click.option('-d', '--data', default='', help='HTTP POST data')
107
+ @click.option('--format', type=click.Choice([RAW_FORMAT]), help='Format response')
108
+ @click.option('-H', '--header', multiple=True, help='Pass custom header(s) to server')
109
+ @ConditionalDecorator(lambda f: click.option('--project-key')(f), is_remote)
110
+ @click.option('-X', '--request', default='GET', help='Specify request command to use')
111
+ @click.option('--scenario-key')
112
+ @click.argument('url')
113
+ def mock(**kwargs):
114
+ request = __build_request_from_curl(**kwargs)
115
+
116
+ context = ReplayContext.from_python_request(request)
117
+ response: requests.Response = replay_request(context, {
118
+ **kwargs,
119
+ 'mode': mode.MOCK,
120
+ })
121
+
122
+ if response.status_code == custom_response_codes.NOT_FOUND:
123
+ print(f"Error: {response.content.decode()}")
124
+ sys.exit(1)
125
+
126
+ if kwargs['format'] == RAW_FORMAT:
127
+ print_raw_response(response)
128
+ else:
129
+ print(response.content.decode())
130
+
131
+ @main.command(
132
+ help="Record request"
133
+ )
134
+ @click.option('-d', '--data', default='', help='HTTP POST data')
135
+ @click.option('--format', type=click.Choice([RAW_FORMAT]), help='Format response')
136
+ @click.option('-H', '--header', multiple=True, help='Pass custom header(s) to server')
137
+ @ConditionalDecorator(lambda f: click.option('--project-key')(f), is_remote)
138
+ @click.option('-X', '--request', default='GET', help='Specify request command to use')
139
+ @click.option('--scenario-key')
140
+ @click.argument('url')
141
+ def record(**kwargs):
142
+ request = __build_request_from_curl(**kwargs)
143
+
144
+ context = ReplayContext.from_python_request(request)
145
+ response: requests.Response = replay_request(context, {
146
+ **kwargs,
147
+ 'mode': mode.RECORD,
148
+ })
149
+
150
+ if kwargs['format'] == RAW_FORMAT:
151
+ print_raw_response(response)
152
+ else:
153
+ print(response.content.decode())
154
+
155
+ def __build_request_from_curl(**kwargs):
156
+ headers = {}
157
+ for header in kwargs['header']:
158
+ toks = header.split(':')
159
+
160
+ if len(toks) != 2:
161
+ continue
162
+
163
+ headers[toks[0]] = toks[1]
164
+
165
+ return requests.Request(
166
+ data=kwargs['data'],
167
+ headers=headers,
168
+ method=kwargs['request'],
169
+ url=kwargs['url']
170
+ )
@@ -1,8 +1,9 @@
1
1
  AGENT_ACTIVE_MODE = 'STOOBLY_AGENT_ACTIVE_MODE'
2
2
  AGENT_CONFIG_PATH = 'STOOBLY_AGENT_CONFIG_PATH'
3
3
  AGENT_ENABLED = 'STOOBLY_AGENT_ENABLED'
4
- AGENT_IS_HEADLESS = 'STOOBLY_AGENT_IS_HEADLESS'
4
+ AGENT_SELF_INTERCEPT_ENABLED = 'STOOBLY_AGENT_SELF_INTERCEPT_ENABLED'
5
5
  AGENT_INCLUDE_PATTERNS = 'STOOBLY_AGENT_INCLUDE_PATTERNS'
6
+ AGENT_IS_HEADLESS = 'STOOBLY_AGENT_IS_HEADLESS'
6
7
  AGENT_EXCLUDE_PATTERNS = 'STOOBLY_AGENT_EXCLUDE_PATTERNS'
7
8
  AGENT_POLICY = 'STOOBLY_AGENT_POLICY'
8
9
  AGENT_PROJECT_KEY = 'STOOBLY_AGENT_PROJECT_KEY'