import bottle from pretenders.server.log import get_logger from pretenders.server.base import in_parent_process, save_pid_file from pretenders.server import data, pretender_app, settings from pretenders.server.maintain import launch_maintainer LOGGER = get_logger('pretenders.server.server') def run(host='localhost', port=8000): "Start the mock HTTP server" data.BOSS_PORT = port if in_parent_process(): if settings.RUN_MAINTAINER: LOGGER.debug('Starting maintainer process') launch_maintainer() save_pid_file('pretenders-boss.pid') bottle.run(app=pretender_app, host=host, port=port, reloader=True) if __name__ == '__main__': import argparse parser = argparse.ArgumentParser(description='Start the server') parser.add_argument( '-H', '--host', dest='host', default='localhost', help='host/IP to run the server on (default: localhost)') parser.add_argument( '-p', '--port', dest='port', type=int, default=8000,
import bottle from pretenders.server.log import get_logger from pretenders.common.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 get_header(header, default=None): return bottle.request.headers.get(header, default)
import json import bottle from bottle import HTTPResponse from pretenders.common.http import Preset, RequestSerialiser from pretenders.server.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 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 argparse import socket from pretenders.server.base import (in_parent_process, save_pid_file) from pretenders.server.log import get_logger from pretenders.client import BossClient from pretenders.common.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()
from pretenders.server.apps.pretender import get_pretenders try: from collections import OrderedDict except ImportError: # 2.6 compatibility from pretenders.common.compat.ordered_dict import OrderedDict from collections import defaultdict from pretenders.server.log import get_logger from pretenders.common.constants import FOREVER from pretenders.common.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 smtpd import asyncore from pretenders.server.log import get_logger from pretenders.common.smtp import SMTPSerialiser from pretenders.server.pretender import Pretender LOGGER = get_logger('pretenders.server.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 os import signal import subprocess import sys import time from pretenders.common.constants import (RETURN_CODE_PORT_IN_USE, PRETEND_PORT_RANGE) from pretenders.common.exceptions import NoPortAvailableException from pretenders.server.log import get_logger from pretenders.server import data from pretenders.server.mock_servers import PretenderModel LOGGER = get_logger('pretenders.server.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, })
import sys from pretenders.server.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.common.http import Preset, RequestSerialiser from pretenders.server.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 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 HTTPResponse from pretenders.server.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 sys from pretenders.server.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 datetime import json from pretenders.common.constants import FOREVER from pretenders.server.log import get_logger from pretenders.server.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)