class ConnectionManager(object): # The official instance instance = None # The original send method aiohttp_clientreq_send = None status_reason_map = { # 1xx Informational 100: "Continue", 101: "Switching Protocol", 102: "Processing", # 2xx Success 200: "OK", 201: "Created", 202: "Accepted", 203: "Non-Authoritative Information", 204: "No Content", 205: "Reset Content", 206: "Partial Content", 207: "Multi-Status", 208: "Already Reported", 226: "IM used", # 3xx Redirection 300: "Multiple Choices", 301: "Permanently Moved", 302: "Found", 303: "See Other", 304: "Not Modified", 305: "Use Proxy", 306: "Switch Proxy", 307: "Temporary Redirect", 308: "Resume Incomplete", # 4xx Client Errors 400: "Bad Request", 401: "Unauthorized", 402: "Payment Required", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable", 407: "Proxy Authentication Required", 408: "Request Time-out", 409: "Conflict", 410: "Gone", 411: "Length Required", 412: "Precondition Failed", 413: "Payload Too Large", 414: "Request-URI Too Long", 415: "Unsupported Media Type", 416: "Requested Range Not Satisfiable", 417: "Expectation Failed", 418: "I'm A Tea Pot", 419: "Authentication Time-out", 420: "Method Failure", 421: "Misdirected Request", 422: "Unprocessable Entity", 423: "Locked", 424: "Failed Dependency", 426: "Upgrade Required", 428: "Precondition Required", 429: "Too Many Requests", 431: "Request Header Fields Too Large", 440: "Login Time-out", 444: "No Response", 449: "Retry With", 450: "Blocked By Windows Parental Control", 451: "Unavailable For Legal Reasons", 494: "Request Header Too Large", 495: "Cert Error", 496: "No Cert", 497: "HTTP To HTTPS", 498: "Token Expired/Invalid", 499: "Client Closed Request", # 5xx Server Errors 500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Time-out", 505: "HTTP Version Not Supported", 506: "Variant Also Negotiates", 507: "Insufficient Storage", 508: "Loop Detected", 509: "Bandwidth Limit Exceeded", 510: "Not Extended", 511: "Network Authentication Required", 520: "Unknown Error", 522: "Origin Connection Time-out", 598: "Network Read Time-out Error", 599: "Network Connect Time-out Error" } @staticmethod def get_instance(): """Access the global instance or create one :returns: instance of ConnectionManager """ if ConnectionManager.instance is None: return ConnectionManager() else: return ConnectionManager.instance def __init__(self): self.managed_urls = [] self.router = ConnectionRouter() self.globify() def reset(self): """Reset Manager State Clear the known route supports """ self.deglobify() self.router.reset() @staticmethod def reset_global(): """Reset the global variables """ if ConnectionManager.instance is not None: ConnectionManager.instance = None def deglobify(self): """De-register the global instance If this instance is the official global instance then reset the global instance """ # if this is the official instance, then clear it if ConnectionManager.instance == self: ConnectionManager.instance = None def globify(self, force=False): """Register the global instance Attempts to register the instance as the official global instance. :param force: boolean - if true, forces this instance to become the official one """ # if this is the first instance, then make it the official one if ConnectionManager.instance is None or force == True: ConnectionManager.instance = self def is_managed(self, url): """Checks if the specific URL is managed by the instance :param url: string - URI of the route to check :returns: boolean - True if the URL is managed, otherwise False """ try: self.router.get_route(url) return True except RouteNotHandled: return False @staticmethod def get_reason_for_status(status_code): """Given an HTTP Status Code get the Associated HTTP Reason :param status_code: int - http response status code :returns: string - http reason for the status code """ if status_code in ConnectionManager.status_reason_map: return ConnectionManager.status_reason_map[status_code] else: return 'Unknown' @staticmethod def make_response(uri, method, status_code=200, body=None, add_headers=None): """Utility function for building a ClientResponse object :param uri: string - URI of the request being handled :param method: string - HTTP verb being responded to :param status_code: int - HTTP Response Status Code :param body: bytes - HTTP Response Body Data :param add_headers: dict - HTTP Response Headers :returns: ClientResponse instance """ content_length = 0 if body: content_length = len(body) response = ClientResponse(method, uri, host='aiohttp_mock') response.status = status_code response.reason = ConnectionManager.get_reason_for_status(status_code) response._should_code = False response._headers = cidict({ 'x-agent': 'aiohttp-mock', 'content-length': content_length }) return response def register(self, uri, method, response): """Register a response for a given URI and HTTP Method :param uri: string - URI of the request to be handled :param method: string - HTTP Verb to be responded to :param response: ClientResponse instance to be returned or a callable that returns a ClientResponse instance Note: callers can use make_response() to create a static ClientResponse object to use for a given URI+Method. """ if not isinstance(response, ClientResponse): if not hasattr(response, '__call__'): raise ConnectionManagerInvalidHandler self.router.add_route_handler(method, uri, response) def intercept(self, request): """Request Intercept Handler :param request: aiohttp.client_reqrep.ClientRequest the request is for :returns: aiohttp.client_reqrep.ClientResponse """ print('Managed URL!') uri = request.url method = request.method try: return self.router.handle(method, uri, request) except RouteNotHandled: raise ConnectionManagerUnhandled('no configured handler')
def __init__(self): self.managed_urls = [] self.router = ConnectionRouter() self.globify()