import datetime import json import os import signal import subprocess import sys import time from pretenders.constants import (RETURN_CODE_PORT_IN_USE, PRETEND_PORT_RANGE) from pretenders.log import get_logger from pretenders.server import data from pretenders.mock_servers import PretenderModel from pretenders.exceptions import NoPortAvailableException LOGGER = get_logger('pretenders.mock_servers.smtp.handler') class SMTPPretenderModel(PretenderModel): def __init__(self, start, name, timeout, last_call, port, pid): super(SMTPPretenderModel, self).__init__(start, name, timeout, last_call, protocol='smtp') self.__dict__.update({ 'port': port, 'pid': pid, }) class SmtpHandler(object):
import sys from pretenders.log import get_logger from bottle import html_escape LOGGER = get_logger('pretenders.server.middleware') class ExceptionLoggingMiddleware(object): """ Middleware that logs exceptions raised by the server. """ def __init__(self, app, *args, **kwargs): self.app = app def __call__(self, environ, start_response): try: return self.app(environ, start_response) except Exception: # This code is largely taken from ``def wsgi()`` in the bottle # code itself, but logs to the log file rather than writing to # environ['wsgi.errors'] LOGGER.exception("Error processing request") err = '<h1>Critical error while processing request: %s</h1>' \ % html_escape(environ.get('PATH_INFO', '/')) environ['wsgi.errors'].write(err) headers = [('Content-Type', 'text/html; charset=UTF-8')] start_response('500 INTERNAL SERVER ERROR', headers, sys.exc_info()) return []
import argparse import socket from pretenders.server.base import (in_parent_process, save_pid_file) from pretenders.log import get_logger from pretenders.client import BossClient from pretenders.constants import RETURN_CODE_PORT_IN_USE LOGGER = get_logger('pretenders.server.pretender') class Pretender(object): def __init__(self, uid, host, port, boss_port): self.uid = uid self.boss_port = boss_port self.host = host self.port = port self.boss_api_handler = BossClient(host, boss_port).boss_access if in_parent_process(): save_pid_file('pretenders-mock-{0}.pid'.format(uid)) def run(self): raise NotImplementedError("run() not defined in " "{0}".format(self.__class__)) @classmethod def start(cls): server = cls.from_command_line_args() try: server.run()
import argparse import socket from pretenders.server.base import ( in_parent_process, save_pid_file) from pretenders.log import get_logger from pretenders.client import BossClient from pretenders.constants import RETURN_CODE_PORT_IN_USE LOGGER = get_logger('pretenders.server.pretender') class Pretender(object): def __init__(self, uid, host, port, boss_port): self.uid = uid self.boss_port = boss_port self.host = host self.port = port self.boss_api_handler = BossClient(host, boss_port).boss_access if in_parent_process(): save_pid_file('pretenders-mock-{0}.pid'.format(uid)) def run(self): raise NotImplementedError("run() not defined in " "{0}".format(self.__class__)) @classmethod def start(cls):
import sys from pretenders.log import get_logger from bottle import html_escape LOGGER = get_logger('pretenders.server.middleware') class ExceptionLoggingMiddleware(object): """ Middleware that logs exceptions raised by the server. """ def __init__(self, app, *args, **kwargs): self.app = app def __call__(self, environ, start_response): try: return self.app(environ, start_response) except Exception: # This code is largely taken from ``def wsgi()`` in the bottle # code itself, but logs to the log file rather than writing to # environ['wsgi.errors'] LOGGER.exception("Error processing request") err = '<h1>Critical error while processing request: %s</h1>' \ % html_escape(environ.get('PATH_INFO', '/')) environ['wsgi.errors'].write(err) headers = [('Content-Type', 'text/html; charset=UTF-8')] start_response('500 INTERNAL SERVER ERROR', headers, sys.exc_info())
import json import bottle from bottle import HTTPResponse from pretenders.log import get_logger from pretenders.server import app from pretenders.server.apps import pretender from pretenders.server.apps.history import save_history from pretenders.server.apps.preset import preset_count, select_preset from pretenders.mock_servers.http import Preset, RequestSerialiser LOGGER = get_logger('pretenders.server.apps.replay') def replay(uid, body): "Save the request and replay response" mock_request = json.loads(body) LOGGER.debug('[UID:{0}] Saving history:\n{1}'.format(uid, mock_request)) save_history(uid, mock_request) if preset_count(uid) == 0: LOGGER.error("Cannot find matching request\n{0}".format(body)) raise HTTPResponse(b"No preset response", status=404) selected = select_preset(uid, mock_request) LOGGER.debug("SELECTED:\n{0}".format(selected)) return selected @app.post('/replay/<uid>') def replay_smtp(uid):
import json from collections import defaultdict from bottle import delete, get, HTTPResponse from pretenders.log import get_logger from pretenders.server import app LOGGER = get_logger('pretenders.server.apps.history') HISTORY = defaultdict(list) def save_history(uid, request): """ Save a value in history """ HISTORY[uid].append(request) @app.get('/history/<uid>/<ordinal:int>') def get_history(uid, ordinal): """ Access requests issued to the mock server """ try: return json.dumps(HISTORY[uid][ordinal]) except IndexError: raise HTTPResponse(b"No recorded request", status=404) except Exception: LOGGER.exception('Unexpected exception')
import datetime import json from pretenders.constants import FOREVER from pretenders.log import get_logger from pretenders.mock_servers import PretenderModel LOGGER = get_logger("pretenders.http.handler") class HTTPPretenderModel(PretenderModel): def __init__(self, path, **kwargs): super(HTTPPretenderModel, self).__init__(protocol="http", **kwargs) self.path = path class HttpHandler(object): PRETENDERS = {} def get_or_create_pretender(self, name, timeout): start = datetime.datetime.now() if name in self.PRETENDERS: pretender = self.PRETENDERS[name] else: path = "/mockhttp/{0}".format(name) if timeout != FOREVER: timeout = datetime.timedelta(seconds=timeout) pretender = HTTPPretenderModel(start=start, timeout=timeout, last_call=start, name=name, path=path)
from bottle import HTTPResponse try: from collections import OrderedDict except ImportError: #2.6 compatibility from pretenders.compat.ordered_dict import OrderedDict from collections import defaultdict from pretenders.log import get_logger from pretenders.constants import FOREVER from pretenders.mock_servers.http import Preset, match_rule_from_dict from pretenders.server import app LOGGER = get_logger('pretenders.server.apps.preset') PRESETS = defaultdict(OrderedDict) def preset_count(uid): """ Check whether there are any presets. """ return len(PRESETS[uid]) def select_preset(uid, request): """ Select a preset to respond with. Look through the presets for a match. If one is found pop off a preset
import datetime import json from pretenders.log import get_logger from pretenders.mock_servers import PretenderModel LOGGER = get_logger('pretenders.http.handler') class HTTPPretenderModel(PretenderModel): def __init__(self, path, **kwargs): super(HTTPPretenderModel, self).__init__(**kwargs) self.path = path class HttpHandler(object): PRETENDERS = {} PRETENDER_NAME_UID = {} def get_or_create_pretender(self, uid, timeout, name): start = datetime.datetime.now() if name in self.PRETENDER_NAME_UID: pretender = self.PRETENDERS[self.PRETENDER_NAME_UID[name]] else: if name: self.PRETENDER_NAME_UID[name] = uid path = "/mockhttp/{0}".format(name) else: path = "/mockhttp/{0}".format(uid)
import json try: from http import client as httplib except ImportError: # Python 2.6/2.7 import httplib import urllib from pretenders.log import get_logger from pretenders.mock_servers import PretenderModel from pretenders.exceptions import (ConfigurationError, ResourceNotFound, UnexpectedResponseStatus) from pretenders.mock_servers.http import binary_to_ascii, Preset LOGGER = get_logger('pretenders.client') class APIHelper(object): def __init__(self, connection, path): self.connection = connection self.path = path def _get_response(self, method, *args, **kwargs): self.connection.request(method=method, *args, **kwargs) return self.connection.getresponse() def http(self, method, *args, **kwargs): """ Issue an HTTP request.
import bottle try: from collections import OrderedDict except ImportError: #2.6 compatibility from pretenders.compat.ordered_dict import OrderedDict from pretenders.log import get_logger from pretenders.constants import REQUEST_ONLY_HEADERS LOGGER = get_logger('pretenders.server.utils') def acceptable_response_header(header): "Use to filter which HTTP headers in the request should be removed" return header not in REQUEST_ONLY_HEADERS def to_dict(wsgi_headers, include=lambda _: True): """ Convert WSGIHeaders to a dict so that it can be JSON-encoded """ ret = {} for k, v in wsgi_headers.items(): if include(k): ret[k] = v return ret def get_header(header, default=None):
try: from http import client as httplib except ImportError: # Python 2.6/2.7 import httplib import urllib from pretenders.log import get_logger from pretenders.mock_servers import PretenderModel from pretenders.exceptions import (ConfigurationError, ResourceNotFound, UnexpectedResponseStatus) from pretenders.mock_servers.http import binary_to_ascii, Preset LOGGER = get_logger('pretenders.client') class APIHelper(object): def __init__(self, connection, path): self.connection = connection self.path = path def _get_response(self, method, *args, **kwargs): self.connection.request(method=method, *args, **kwargs) return self.connection.getresponse() def http(self, method, *args, **kwargs): """ Issue an HTTP request.
import smtpd import asyncore from pretenders.log import get_logger from pretenders.server.pretender import Pretender from pretenders.mock_servers.smtp import SMTPSerialiser LOGGER = get_logger('pretenders.mock_servers.smtp.server') class MockSMTPServer(smtpd.SMTPServer, Pretender): def __init__(self, host, port, **kwargs): smtpd.SMTPServer.__init__(self, (host, port), None) Pretender.__init__(self, host=host, port=port, **kwargs) LOGGER.info("Initialised MockSMTPServer") def process_message(self, peer, mailfrom, rcpttos, data): smtp_info = SMTPSerialiser( peer=peer, mailfrom=mailfrom, rcpttos=rcpttos, data=data, rule='') body = smtp_info.serialize() LOGGER.info("Storing SMTP message: \n{0}".format(body)) self.store_history_retrieve_preset(body) return def run(self): "Runner for the MockSMTPServer" LOGGER.info("Running SMTP mock server") asyncore.loop()
import json import bottle from bottle import HTTPResponse from pretenders.log import get_logger from pretenders.server import app from pretenders.server.apps import pretender from pretenders.server.apps.history import save_history from pretenders.server.apps.preset import preset_count, select_preset from pretenders.mock_servers.http import Preset, RequestSerialiser LOGGER = get_logger('pretenders.server.apps.replay') def replay(uid, body): "Save the request and replay response" mock_request = json.loads(body) LOGGER.debug('[UID:{0}] Saving history:\n{1}'.format(uid, mock_request)) save_history(uid, mock_request) if preset_count(uid) == 0: LOGGER.error("Cannot find matching request\n{0}".format(body)) raise HTTPResponse(b"No preset response", status=404) selected = select_preset(uid, mock_request) LOGGER.debug("SELECTED:\n{0}".format(selected)) return selected @app.post('/replay/<uid>') def replay_smtp(uid): """
import datetime import json from pretenders.constants import FOREVER from pretenders.log import get_logger from pretenders.mock_servers import PretenderModel LOGGER = get_logger('pretenders.http.handler') class HTTPPretenderModel(PretenderModel): def __init__(self, path, **kwargs): super(HTTPPretenderModel, self).__init__(protocol='http', **kwargs) self.path = path class HttpHandler(object): PRETENDERS = {} def get_or_create_pretender(self, name, timeout): start = datetime.datetime.now() if name in self.PRETENDERS: pretender = self.PRETENDERS[name] else: path = "/mockhttp/{0}".format(name) if timeout != FOREVER: timeout = datetime.timedelta(seconds=timeout) pretender = HTTPPretenderModel(start=start,
import datetime import json import os import signal import subprocess import sys import time from pretenders.constants import RETURN_CODE_PORT_IN_USE, PRETEND_PORT_RANGE from pretenders.log import get_logger from pretenders.server import data from pretenders.mock_servers import PretenderModel from pretenders.exceptions import NoPortAvailableException LOGGER = get_logger("pretenders.mock_servers.smtp.handler") class SMTPPretenderModel(PretenderModel): def __init__(self, start, name, timeout, last_call, port, pid): super(SMTPPretenderModel, self).__init__(start, name, timeout, last_call, protocol="smtp") self.__dict__.update({"port": port, "pid": pid}) class SmtpHandler(object): PRETENDERS = {} def available_ports(self): """ Get a set of ports available for starting pretenders