inspire_mitmproxy package

INSPIRE MITMProxy for E2E Tests.

Submodules

inspire_mitmproxy.dispatcher module

Dispatcher forwards requests to Services.

class inspire_mitmproxy.dispatcher.Dispatcher → None

Bases: object

SERVICE_LIST = [<class 'inspire_mitmproxy.services.arxiv_service.ArxivService'>, <class 'inspire_mitmproxy.services.legacy_service.LegacyService'>, <class 'inspire_mitmproxy.services.rt_service.RTService'>, <class 'inspire_mitmproxy.services.whitelist_service.WhitelistService'>]
find_service_for_request(request: inspire_mitmproxy.http.MITMRequest) → inspire_mitmproxy.services.base_service.BaseService
static is_flow_passed_through() → bool
process_request(request: inspire_mitmproxy.http.MITMRequest) → inspire_mitmproxy.http.MITMResponse

Perform operations and give response.

process_response(request: inspire_mitmproxy.http.MITMRequest, response: inspire_mitmproxy.http.MITMResponse)

Hook for live responses.

request(flow: mitmproxy.http.HTTPFlow)

MITMProxy addon event interface for outgoing request.

response(flow: mitmproxy.http.HTTPFlow)

inspire_mitmproxy.errors module

INSPIRE-MITMProxy Errors

exception inspire_mitmproxy.errors.DoNotIntercept(service_name: str, request: inspire_mitmproxy.http.MITMRequest) → None

Bases: Exception

exception inspire_mitmproxy.errors.InvalidRequest(service_name: str, request: inspire_mitmproxy.http.MITMRequest) → None

Bases: inspire_mitmproxy.errors.MITMProxyHTTPError

exception inspire_mitmproxy.errors.MITMProxyHTTPError

Bases: Exception

http_status_code = 500
exception inspire_mitmproxy.errors.NoMatchingRecording(service_name: str, request: inspire_mitmproxy.http.MITMRequest) → None

Bases: inspire_mitmproxy.errors.MITMProxyHTTPError

exception inspire_mitmproxy.errors.NoServicesForRequest(request: inspire_mitmproxy.http.MITMRequest) → None

Bases: inspire_mitmproxy.errors.MITMProxyHTTPError

exception inspire_mitmproxy.errors.RequestNotHandledInService(service_name: str, request: inspire_mitmproxy.http.MITMRequest) → None

Bases: inspire_mitmproxy.errors.MITMProxyHTTPError

exception inspire_mitmproxy.errors.ScenarioNotInService(service_name: str, scenario: str) → None

Bases: inspire_mitmproxy.errors.MITMProxyHTTPError

exception inspire_mitmproxy.errors.ServiceNotFound(service_name: str) → None

Bases: inspire_mitmproxy.errors.MITMProxyHTTPError

inspire_mitmproxy.http module

Wrappers for HTTP objects.

class inspire_mitmproxy.http.MITMHeaders(headers: Dict[str, List[str]]) → None

Bases: object

classmethod from_dict(headers_dict: Dict[str, List[str]]) → inspire_mitmproxy.http.MITMHeaders
classmethod from_mitmproxy(headers: mitmproxy.net.http.headers.Headers) → inspire_mitmproxy.http.MITMHeaders
keys() → KeysView[str]
to_dict() → Dict[str, List[str]]
to_mitmproxy() → mitmproxy.net.http.headers.Headers
class inspire_mitmproxy.http.MITMRequest(url: str, method: str = 'GET', body: Union[str, bytes, NoneType] = None, headers: Union[inspire_mitmproxy.http.MITMHeaders, NoneType] = None, original_encoding: Union[str, NoneType] = None, http_version: Union[str, NoneType] = None) → None

Bases: object

classmethod from_dict(request: Dict[str, Any]) → inspire_mitmproxy.http.MITMRequest
classmethod from_mitmproxy(request: mitmproxy.http.HTTPRequest) → inspire_mitmproxy.http.MITMRequest
to_dict() → Dict[str, Any]
to_mitmproxy() → mitmproxy.http.HTTPRequest
class inspire_mitmproxy.http.MITMResponse(status_code: int = 200, status_message: Union[str, NoneType] = None, body: Union[str, bytes, NoneType] = None, headers: Union[inspire_mitmproxy.http.MITMHeaders, NoneType] = None, original_encoding: Union[str, NoneType] = None, http_version: Union[str, NoneType] = None) → None

Bases: object

classmethod from_dict(response: Dict[str, Any]) → inspire_mitmproxy.http.MITMResponse
classmethod from_mitmproxy(response: mitmproxy.http.HTTPResponse) → inspire_mitmproxy.http.MITMResponse
to_dict() → Dict[str, Any]
to_mitmproxy() → mitmproxy.http.HTTPResponse
inspire_mitmproxy.http.encoding_by_header(headers: inspire_mitmproxy.http.MITMHeaders) → str

Extract charset param from Content-Type or Accept headers

inspire_mitmproxy.http.response_to_string(res: requests.models.Response) → str
Parameters:resrequests.Response object

Parse the given request and generate an informative string from it

inspire_mitmproxy.interaction module

Interaction is a recording of a request-response pair that is to be replayed during the test.

Scenarios are what interactions are organised into. For inspire-next they reside at:

tests/e2e/scenarios

The directory structure is as follows:

scenarios/<scenario_name>/<service_name>/<interaction>.yaml

Scenario name can be anything, but by convention it is the name of the E2E test without the test_ prefix. Service name has to match one of the services defined in inspire_mitmproxy.services. Name of the interaction can be anything, and is only for informative purposes. When recorded automatically, interactions are named in sequence of interaction_0.yaml, interaction_1.yaml, and so on.

class inspire_mitmproxy.interaction.Interaction(name: str, request: inspire_mitmproxy.http.MITMRequest, response: inspire_mitmproxy.http.MITMResponse, match: Union[dict, NoneType] = None, callbacks: Union[typing.List[dict], NoneType] = None) → None

Bases: object

DEFAULT_CALLBACK_DELAY = 0.5
DEFAULT_EXACT_MATCH_FIELDS = ['url', 'method', 'body']
DEFAULT_NAME_MATCH_REGEX = re.compile('^interaction_(\\d+)$')
DEFAULT_NAME_PATTERN = 'interaction_{}'
DEFAULT_REGEX_MATCH_FIELDS = {}
exact_match_fields

Fields specified match exactly.

static execute_callback(delay: Union[int, float])
execute_callbacks()
classmethod from_file(interaction_file: Union[pathlib.Path, NoneType]) → inspire_mitmproxy.interaction.Interaction
classmethod get_next_sequence_number_in_dir(directory: pathlib.Path) → int
matches_request(request: inspire_mitmproxy.http.MITMRequest) → bool

Check if interaction matches the request.

By default the request is matching the prerecoded request if their urls, methods and bodies are equal (see DEFAULT_EXACT_MATCH_FIELDS and DEFAULT_REGEX_MATCH_FIELDS). You can specify custom matching rules per interaction by using the match field in the interaction YAML file.

classmethod next_in_dir(directory: pathlib.Path, request: inspire_mitmproxy.http.MITMRequest, response: inspire_mitmproxy.http.MITMResponse) → inspire_mitmproxy.interaction.Interaction

Create a new interaction with a name taking from next available in directory.

regex_match_fields

Fields specified (as key in the dictionary) match on the regex defined in value.

save_in_dir(directory: pathlib.Path)

Save the interaction to a file.

Structure of interactions:

request:
  body: 'Body of the request'           # string (or bytes)
  headers:
    Content-Type: ['text/plain']        # array of strings (case of repeated headers)
    Host: ['samplehost.local']
  method: 'PUT'                         # string (one of allowed HTTP method names)
  url: 'http://samplehost.local/path'   # string
response:
  body: 'Body of the response'          # string (or bytes)
  headers:
    Content-Type: ['text/plain']        # array of strings (ditto)
  status:
    code: 200                           # integer
    message: OK                         # string
match:
  exact:
  - method                              # array of one of the keys in request
  - uri
  regex:
    method: 'PUT|POST'                  # dict with keys of the keys in request
callbacks:
- delay: 10                             # integer (seconds)
  request: {}                           # follows request above (as callback is executed
                                        # using python-requests, which does not support
                                        # multiple header values, only first value of
                                        # each header will be used)
to_dict() → dict