diff --git a/mockpy/core/cherrypy_mapper.py b/mockpy/core/cherrypy_mapper.py
index 96295e4..84f6acb 100644
--- a/mockpy/core/cherrypy_mapper.py
+++ b/mockpy/core/cherrypy_mapper.py
@@ -4,6 +4,7 @@
from mockpy.utils import log
from mockpy.utils.config import *
from mockpy.status.status import Status
+import mockpy.utils.cherrypy_extensions
class CherryPyMapper(object):
@@ -15,14 +16,15 @@ def __init__(self, mapping_handler=None, cherrypy=None):
def handle_request(self):
- if Status.is_status(self.cherrypy.url()):
+ log.log_url(self.cherrypy.url())
+
+ if self.status.is_status(self.cherrypy.url()):
info("Accessing Satus")
- self.print_seperator()
+ log.print_seperator()
return self.status.html_response()
- request = MappingRequest(self.cherry_request_dict())
+ request = self.cherrypy.to_mapper_request()
items = self.mapping_handler.mapping_item_for_mapping_request(request)
- log.log_url(self.cherrypy.url())
if len(items) == 0:
self.cherrypy.response.status = 500
@@ -43,16 +45,6 @@ def handle_request(self):
return response.body_response()
- def cherry_request_dict(self):
- dic = {"method": self.cherrypy.request.method,
- "url": self.cherrypy.url(),
- "headers": self.cherrypy.request.headers}
-
- if self.cherrypy.request.process_request_body:
- dic["body"] = self.cherrypy.request.body.read()
-
- return dic
-
def fill_headers(self, headers):
if type({}) is not type(headers):
return
diff --git a/mockpy/core/proxy_mapper.py b/mockpy/core/proxy_mapper.py
new file mode 100644
index 0000000..215e82a
--- /dev/null
+++ b/mockpy/core/proxy_mapper.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+import httplib
+from threading import Thread
+
+from libmproxy.protocol.http import HTTPRequest, HTTPResponse
+from netlib.odict import ODictCaseless
+
+import mockpy.utils.proxy_extensions
+from ..utils.config import *
+from mockpy.status.status import Status
+from ..utils import log
+from ..models.mapping_items_manager import *
+
+class ProxyMapper(object):
+
+ def __init__(self, mapping_handler, http_proxy):
+ self.http_proxy = http_proxy
+ self.mapping_handler = mapping_handler
+ self.status = Status(self.mapping_handler)
+
+ success("Proxy server started")
+
+ def handle_request(self, flow):
+ log.log_url(flow.request.url)
+
+ if self.status.is_status(flow.request.url):
+ info("Accessing Satus")
+ flow.reply(HTTPResponse.with_html(self.status.html_response()))
+ log.print_seperator()
+ return
+
+ request = flow.request.to_mapper_request()
+ mapping_items = self.mapping_handler.mapping_item_for_mapping_request(request)
+
+ if len(mapping_items) > 1:
+ log.log_multiple_matches(mapping_items)
+
+ if len(mapping_items) == 0:
+ self.perform_http_request(flow)
+ else:
+ self.perform_mapping_request(flow, mapping_items[0])
+
+ log.print_seperator()
+
+ def perform_mapping_request(self, flow, mapping_item):
+ response, request = mapping_item.response, mapping_item.request
+
+ log.log_request(request)
+ log.log_response(response)
+
+ response = HTTPResponse.from_intercepted_response(response)
+ flow.reply(response)
+
+ def perform_http_request(self, flow):
+ if self.http_proxy is None:
+ flow.reply()
+ else:
+ thread = Thread(target=self.threaded_perform_http_request,
+ args=(flow, self.http_proxy))
+ thread.start()
+
+ def threaded_perform_http_request(self, flow, proxy_settings):
+ response = self.perform_http_connection(flow.request, proxy_settings[0], proxy_settings[1])
+ flow.reply(response)
+
+ @staticmethod
+ def perform_http_connection(request, url, port):
+ try:
+ conn = httplib.HTTPConnection(url, port)
+ headers = dict(request.headers.items())
+
+ conn.request(request.method, request.url,
+ body=request.content, headers=headers)
+ httplib_response = conn.getresponse()
+
+ headers = ODictCaseless.from_httplib_headers(httplib_response.getheaders())
+ response = HTTPResponse(code=httplib_response.status,
+ content=httplib_response.read(),
+ msg="",
+ httpversion=(1, 1),
+ headers=headers)
+ return response
+ except Exception as ex:
+ error("Error Happened")
+ error(ex)
+ error("method: %s\nurl: %s\nbody: --\nheaders: --" %
+ (request.method, request.url))
+ return None
diff --git a/mockpy/core/proxy_server.py b/mockpy/core/proxy_server.py
index 1a98af7..5040a86 100755
--- a/mockpy/core/proxy_server.py
+++ b/mockpy/core/proxy_server.py
@@ -8,99 +8,28 @@
from libmproxy import controller, proxy
from libmproxy.proxy.server import ProxyServer
-from libmproxy.protocol.http import HTTPRequest, HTTPResponse
-from netlib.odict import ODictCaseless
-import mockpy.utils.extensions
-from ..utils.config import *
-from mockpy.status.status import Status
from ..utils import log
-from ..models.mapping_items_manager import *
-
+from .proxy_mapper import *
class MITMProxy(controller.Master):
- def __init__(self, server, inout_path, res_path, http_proxy):
+ def __init__(self, server, proxy_mapper):
controller.Master.__init__(self, server)
-
- self.http_proxy = http_proxy
- self.handler = MappingItemsManager(inout_path, res_path)
- self.status = Status(self.handler)
-
- success("Proxy server started")
+ self.proxy_mapper = proxy_mapper
def handle_request(self, flow):
- request = flow.request.to_mapper_request()
- mapping_items = self.handler.mapping_item_for_mapping_request(request)
-
- log.log_url(flow.request.url)
-
- if Status.is_status(flow.request.url):
- info("Accessing Satus")
- flow.reply(HTTPResponse.with_html(self.status.html_response()))
- log.print_seperator()
- return
-
- if len(mapping_items) > 1:
- log.log_multiple_matches(mapping_items)
-
- if len(mapping_items) == 0:
- self.perform_http_request(flow)
- else:
- self.perform_mapping_request(flow, mapping_items[0])
-
- log.print_seperator()
-
- def perform_mapping_request(self, flow, mapping_item):
- response, request = mapping_item.response, mapping_item.request
-
- log.log_request(request)
- log.log_response(response)
-
- response = HTTPResponse.from_intercepted_response(response)
- flow.reply(response)
-
- def perform_http_request(self, flow):
- if self.http_proxy is None:
- flow.reply()
- else:
- thread = Thread(target=self.threaded_perform_http_request,
- args=(flow, self.http_proxy))
- thread.start()
-
- def threaded_perform_http_request(self, flow, proxy_settings):
- response = self.perform_request(flow.request, proxy_settings[0], proxy_settings[1])
- flow.reply(response)
-
- @staticmethod
- def perform_request(request, url, port):
- try:
- conn = httplib.HTTPConnection(url, port)
- headers = dict(request.headers.items())
-
- conn.request(request.method, request.url,
- body=request.content, headers=headers)
- httplib_response = conn.getresponse()
-
- headers = ODictCaseless.from_httplib_headers(httplib_response.getheaders())
- response = HTTPResponse(code=httplib_response.status,
- content=httplib_response.read(),
- msg="",
- httpversion=(1, 1),
- headers=headers)
- return response
- except Exception as ex:
- error("Error Happened")
- error(ex)
- error("method: %s\nurl: %s\nbody: --\nheaders: --" %
- (request.method, request.url))
- return None
+ self.proxy_mapper.handle_request(flow)
def start_proxy_server(port, inout_path, res_path, http_proxy):
config = proxy.ProxyConfig(port=port)
server = ProxyServer(config)
- m = MITMProxy(server, inout_path, res_path, http_proxy)
+
+ mapping_handler = MappingItemsManager(inout_path, res_path)
+
+ proxy_mapper = ProxyMapper(mapping_handler, http_proxy)
+ m = MITMProxy(server, proxy_mapper)
def signal_handler(signal, frame):
info("\nShutting down proxy server")
diff --git a/mockpy/models/mapping_items_manager.py b/mockpy/models/mapping_items_manager.py
index a7f111c..cbc3984 100644
--- a/mockpy/models/mapping_items_manager.py
+++ b/mockpy/models/mapping_items_manager.py
@@ -1,15 +1,29 @@
__author__ = 'omarsubhiabdelhafith'
from .mapping_item import *
+from mockpy.utils import log
from functools import partial
import re
+from watchdog.observers import Observer
+from watchdog.events import FileSystemEventHandler
class MappingItemsManager(object):
def __init__(self, inout_path, res_path):
- self.yaml_files = get_yaml_files(inout_path)
- create_mapping_item_with_yaml = partial(create_mapping_item, inout_path, res_path)
- self.mappings = list(map(create_mapping_item_with_yaml, self.yaml_files))
+ self.inout_path = inout_path
+ self.res_path = res_path
+ self.parse_inout_and_res()
+ self.install_watchers()
+
+ def parse_inout_and_res(self):
+ self.yaml_files = get_yaml_files(self.inout_path)
+ self.mappings = list(map(self.create_mapping_item, self.yaml_files))
+
+ def create_mapping_item(self, yml_file):
+ full_path = self.inout_path + "/" + yml_file
+
+ with open(full_path, "r") as file:
+ return MappingItem(yaml.load(file), full_path, self.res_path)
def response_for_mapping_request(self, request):
return [item.response for item in self.mappings if item.handles_mapping_request(request)]
@@ -17,15 +31,35 @@ def response_for_mapping_request(self, request):
def mapping_item_for_mapping_request(self, request):
return [item for item in self.mappings if item.handles_mapping_request(request)]
+ def install_watchers(self):
+ self.event_handler = MapperDirectoryListener(self)
+ self.install_watcher(self.inout_path)
+ self.install_watcher(self.res_path)
+
+ def install_watcher(self, path):
+ observer = Observer()
+ observer.schedule(self.event_handler, path, recursive=True)
+ observer.start()
+
+
+class MapperDirectoryListener(FileSystemEventHandler):
+
+ def __init__(self, mapping_manager):
+ self.mapping_manager = mapping_manager
+
+ def on_any_event(self, event):
+ log.info("Inout or Res directory changed, rebuilding mapping settings\n"
+ "File path: %s" % event.src_path +
+ "\nEvent type: %s" % event.event_type)
+
+ self.mapping_manager.parse_inout_and_res()
+ log.success("Mapping settings rebuilt successfully")
+ log.print_seperator()
+
def get_yaml_files(path):
files = os.listdir(path)
return filter(lambda file: re.match(".*\.yml$", file), files)
-def create_mapping_item(inout_path, res_path, yml_file):
- file_to_open = inout_path + "/" + yml_file
- with open(file_to_open, "r") as file:
- return MappingItem(yaml.load(file), file_to_open, res_path)
-
diff --git a/mockpy/status/status.py b/mockpy/status/status.py
index 45d21bc..f013464 100644
--- a/mockpy/status/status.py
+++ b/mockpy/status/status.py
@@ -14,6 +14,7 @@ def html_response(self):
string += "Parsed interceptors:
"
string += "_" * 80
string += "
"
+
for item in self.mapping_handler.mappings:
string += " - " + item.file_name + "
"
@@ -27,7 +28,6 @@ def html_response(self):
string += "_" * 80
string += "
"
-
string += "