def request(self, method, uri, headers=None, bodyProducer=None): """ Implement IAgent.request. """ # We want to use Agent to parse the HTTP response, so let's ask it to # make a request against our in-memory reactor. response = self._realAgent.request(method, uri, headers, bodyProducer) # That will try to establish an HTTP connection with the reactor's # connectTCP method, and MemoryReactor will place Agent's factory into # the tcpClients list. We'll extract that. host, port, factory, timeout, bindAddress = ( self._memoryReactor.tcpClients[0]) # Then we need to convince that factory it's connected to something and # it will give us a protocol for that connection. protocol = factory.buildProtocol(None) # We want to capture the output of that connection so we'll make an # in-memory transport. clientTransport = AbortableStringTransport() # When the protocol is connected to a transport, it ought to send the # whole request because callers of this should not use an asynchronous # bodyProducer. protocol.makeConnection(clientTransport) # Get the data from the request. requestData = clientTransport.io.getvalue() # Now time for the server to do its job. Ask it to build an HTTP # channel. channel = get_site(self._rootResource).buildProtocol(None) # Connect the channel to another in-memory transport so we can collect # the response. serverTransport = StringTransport() serverTransport.hostAddr = IPv4Address('TCP', '127.0.0.1', 80) channel.makeConnection(serverTransport) # Feed it the data that the Agent synthesized. channel.dataReceived(requestData) # Tell it that the connection is now complete so it can clean up. channel.connectionLost(Failure(ConnectionDone())) # Now we have the response data, let's give it back to the Agent. protocol.dataReceived(serverTransport.io.getvalue()) # By now the Agent should have all it needs to parse a response. protocol.connectionLost(Failure(ConnectionDone())) # Return the response in the accepted format (Deferred firing # IResponse). This should be synchronously fired, and if not, it's the # system under test's problem. return response
def makeService(config): """ Set up the otter-api service. """ s = MultiService() if config['realtime']: from twisted.internet import reactor as clock else: clock = Clock() core = MimicCore.fromPlugins(clock) root = MimicRoot(core, clock) site = get_site(root.app.resource(), logging=bool(config['verbose'])) service(config['listen'], site).setServiceParent(s) return s
def makeService(config): """ Set up the service. """ s = MultiService() if config['realtime']: from twisted.internet import reactor as clock else: clock = Clock() core = MimicCore.fromPlugins(clock) root = MimicRoot(core, clock) site = get_site(root.app.resource(), logging=bool(config['verbose'])) # The Twisted code currently (v16.6.0, 17.1.0) compares the type of # this argument to 'str' in order to determine how to handle it. description = str(config['listen']) service(description, site).setServiceParent(s) return s