我们从Python开源项目中,提取了以下47个代码示例,用于说明如何使用twisted.web.client.readBody()。
def twisted_coroutine_fetch(self, url, runner): body = [None] @gen.coroutine def f(): # This is simpler than the non-coroutine version, but it cheats # by reading the body in one blob instead of streaming it with # a Protocol. client = Agent(self.reactor) response = yield client.request(b'GET', utf8(url)) with warnings.catch_warnings(): # readBody has a buggy DeprecationWarning in Twisted 15.0: # https://twistedmatrix.com/trac/changeset/43379 warnings.simplefilter('ignore', category=DeprecationWarning) body[0] = yield readBody(response) self.stop_loop() self.io_loop.add_callback(f) runner() return body[0]
def test_key_not_found_is_raised_if_key_search_responds_404(self): """ Test if key search request comes back with a 404 response then KeyNotFound is raised, with corresponding error message. """ km = self._key_manager(url=NICKSERVER_URI) client.readBody = mock.Mock(return_value=defer.succeed(None)) km._nicknym._async_client_pinned.request = mock.Mock( return_value=defer.succeed(None)) url = NICKSERVER_URI + '?address=' + INVALID_MAIL_ADDRESS d = km._nicknym._fetch_and_handle_404_from_nicknym(url) def check_key_not_found_is_raised_if_404(_): used_kwargs = km._nicknym._async_client_pinned.request.call_args[1] check_404_callback = used_kwargs['callback'] fake_response = mock.Mock() fake_response.code = NOT_FOUND with self.assertRaisesRegexp(errors.KeyNotFound, '404: Key not found. Request: ' '%s' % url.replace('?', '\?')): check_404_callback(fake_response) d.addCallback(check_key_not_found_is_raised_if_404) return d
def _fetch_key_with_address(self, km, address, key): """ :returns: a Deferred that will fire with the OpenPGPKey """ data = json.dumps({'address': address, 'openpgp': key}) client.readBody = mock.Mock(return_value=defer.succeed(data)) # mock the fetcher so it returns the key for ADDRESS_2 km._nicknym._async_client_pinned.request = mock.Mock( return_value=defer.succeed(None)) km.ca_cert_path = 'cacertpath' # try to key get without fetching from server d_fail = km.get_key(address, fetch_remote=False) d = self.assertFailure(d_fail, errors.KeyNotFound) # try to get key fetching from server. d.addCallback(lambda _: km.get_key(address)) return d
def checkResponse(self, response, exp_result): # TODO: convert to log messages """ print 'Response version:', response.version print 'Response code:', response.code print 'Response phrase:', response.phrase print 'Response headers:' print pformat(list(response.headers.getAllRawHeaders())) """ """ LOG.debug("Response Body %s", str(response.version)) LOG.debug("Response Body %s", str(response.code)) LOG.debug("Response Body %s", str(response.phrase)) LOG.debug("Response Body %s", str(list(response.headers.getAllRawHeaders()))) LOG.debug("Expected Results %s", str(exp_result)) """ d = readBody(response) d.addCallback(self.assertResponse, exp_result) return d
def getResponse(self, response): # TODO: convert to log messages """ print 'Response version:', response.version print 'Response code:', response.code print 'Response phrase:', response.phrase print 'Response headers:' print pformat(list(response.headers.getAllRawHeaders())) """ """ LOG.debug("Response Body %s", str(response.version)) LOG.debug("Response Body %s", str(response.code)) LOG.debug("Response Body %s", str(response.phrase)) LOG.debug("Response Body %s", str(list(response.headers.getAllRawHeaders()))) LOG.debug("Expected Results %s", str(exp_result)) """ d = readBody(response) return d
def http_request(self, path="/", encode='zlib'): """ Do an http request on the broker :type path str """ url = "http://localhost:" + str(Broker.get_instance().http_port)+path print url # http"://localhost:broker.http_port request = self._http_agent.request( 'GET', url, Headers({'User-Agent': ['Twisted Web Client']}), None) request.addCallback(lambda response: readBody(response)) request.addCallback(lambda html: (base64.b64encode(html.encode(encode))) if encode == "zlib" else html) return request
def fetch(path, url, state): agent = OnionRoutedAgent(reactor, path=path, state=state) request = agent.request("GET", url) reactor.callLater(10, request.cancel) request.addCallback(readBody) def parse_ip(body): exit_ip = path[-1].ip try: checked_ip = re.search("<strong>(.*)</strong>", body).group(1) return exit_ip, checked_ip except AttributeError: return exit_ip, None request.addCallback(parse_ip) def err(failure): failure.trap(defer.CancelledError, ResponseNeverReceived, ResponseFailed, HostUnreachable, TTLExpired) log.err(failure) request.addErrback(err) return request
def test_withPotentialDataLoss(self): """ If the full body of the L{IResponse} passed to L{client.readBody} is not definitely received, the L{Deferred} returned by L{client.readBody} fires with a L{Failure} wrapping L{client.PartialDownloadError} with the content that was received. """ response = DummyResponse() d = client.readBody(response) response.protocol.dataReceived(b"first") response.protocol.dataReceived(b"second") response.protocol.connectionLost(Failure(PotentialDataLoss())) failure = self.failureResultOf(d) failure.trap(client.PartialDownloadError) self.assertEqual({ "status": failure.value.status, "message": failure.value.message, "body": failure.value.response, }, { "status": b"200", "message": b"OK", "body": b"firstsecond", })
def test_deprecatedTransport(self): """ Calling L{client.readBody} with a transport that does not implement L{twisted.internet.interfaces.ITCPTransport} produces a deprecation warning, but no exception when cancelling. """ response = DummyResponse(transportFactory=StringTransport) response.transport.abortConnection = None d = self.assertWarns( DeprecationWarning, 'Using readBody with a transport that does not have an ' 'abortConnection method', __file__, lambda: client.readBody(response)) d.cancel() self.failureResultOf(d, defer.CancelledError)
def test_noProxyPassthrough(self): """ The CGI script is never called with the Proxy header passed through. """ cgiFilename = self.writeCGI(HEADER_OUTPUT_CGI) portnum = self.startServer(cgiFilename) url = "http://localhost:%d/cgi" % (portnum,) agent = client.Agent(reactor) headers = http_headers.Headers({"Proxy": ["foo"], "X-Innocent-Header": ["bar"]}) d = agent.request(b"GET", url, headers=headers) def checkResponse(response): headers = json.loads(response) self.assertEqual( set(headers.keys()), {"HTTP_HOST", "HTTP_CONNECTION", "HTTP_X_INNOCENT_HEADER"}) d.addCallback(client.readBody) d.addCallback(checkResponse) return d
def testReadInput(self): cgiFilename = os.path.abspath(self.mktemp()) with open(cgiFilename, 'wt') as cgiFile: cgiFile.write(READINPUT_CGI) portnum = self.startServer(cgiFilename) agent = client.Agent(reactor) d = agent.request( uri="http://localhost:%d/cgi" % (portnum,), method=b"POST", bodyProducer=client.FileBodyProducer( BytesIO(b"Here is your stdin")), ) d.addCallback(client.readBody) d.addCallback(self._testReadInput_1) return d
def testDistrib(self): # site1 is the publisher r1 = resource.Resource() r1.putChild("there", static.Data("root", "text/plain")) site1 = server.Site(r1) self.f1 = PBServerFactory(distrib.ResourcePublisher(site1)) self.port1 = reactor.listenTCP(0, self.f1) self.sub = distrib.ResourceSubscription("127.0.0.1", self.port1.getHost().port) r2 = resource.Resource() r2.putChild("here", self.sub) f2 = MySite(r2) self.port2 = reactor.listenTCP(0, f2) agent = client.Agent(reactor) d = agent.request(b"GET", "http://127.0.0.1:%d/here/there" % \ (self.port2.getHost().port,)) d.addCallback(client.readBody) d.addCallback(self.assertEqual, 'root') return d
def _requestTest(self, child, **kwargs): """ Set up a resource on a distrib site using L{ResourcePublisher} and then retrieve it from a L{ResourceSubscription} via an HTTP client. @param child: The resource to publish using distrib. @param **kwargs: Extra keyword arguments to pass to L{Agent.request} when requesting the resource. @return: A L{Deferred} which fires with the result of the request. """ mainPort, mainAddr = self._setupDistribServer(child) agent = client.Agent(reactor) url = "http://%s:%s/child" % (mainAddr.host, mainAddr.port) d = agent.request(b"GET", url, **kwargs) d.addCallback(client.readBody) return d
def version(self): """ Issue a I{GET} for the Kubernetes server version. """ action = start_action( action_type=u"network-client:version", ) with action.context(): url = self.kubernetes.base_url.child(u"version") d = DeferredContext(self._get(url)) d.addCallback(check_status, (OK,), self.model) d.addCallback(readBody) d.addCallback(loads) d.addCallback(log_response_object, action) d.addCallback(self.model.version_type.create) return d.addActionFinish()
def create(self, obj): """ Issue a I{POST} to create the given object. """ action = start_action( action_type=u"network-client:create", ) with action.context(): url = self.kubernetes.base_url.child(*collection_location(obj)) document = self.model.iobject_to_raw(obj) Message.log(submitted_object=document) d = DeferredContext(self._post(url, document)) d.addCallback(check_status, (CREATED,), self.model) d.addCallback(readBody) d.addCallback(loads) d.addCallback(log_response_object, action) d.addCallback(self.model.iobject_from_raw) return d.addActionFinish()
def replace(self, obj): """ Issue a I{PUT} to replace an existing object with a new one. """ action = start_action( action_type=u"network-client:replace", ) with action.context(): url = self.kubernetes.base_url.child(*object_location(obj)) document = self.model.iobject_to_raw(obj) Message.log(submitted_object=document) d = DeferredContext(self._put(url, document)) d.addCallback(check_status, (OK,), self.model) d.addCallback(readBody) d.addCallback(loads) d.addCallback(log_response_object, action) d.addCallback(self.model.iobject_from_raw) return d.addActionFinish()
def get(self, obj): """ Issue a I{GET} to retrieve the given object. The object must have identifying metadata such as a namespace and a name but other fields are ignored. """ action = start_action( action_type=u"network-client:get", kind=obj.kind, name=obj.metadata.name, namespace=getattr(obj.metadata, "namespace", None), ) with action.context(): url = self.kubernetes.base_url.child(*object_location(obj)) d = DeferredContext(self._get(url)) d.addCallback(check_status, (OK,), self.model) d.addCallback(readBody) d.addCallback(loads) d.addCallback(log_response_object, action) d.addCallback(self.model.iobject_from_raw) return d.addActionFinish()
def list(self, kind): """ Issue a I{GET} to retrieve objects of a given kind. """ action = start_action( action_type=u"network-client:list", kind=kind.kind, apiVersion=kind.apiVersion, ) with action.context(): url = self.kubernetes.base_url.child(*collection_location(kind)) d = DeferredContext(self._get(url)) d.addCallback(check_status, (OK,), self.model) d.addCallback(readBody) d.addCallback( lambda body: self.model.iobject_from_raw(loads(body)), ) return d.addActionFinish()
def from_model_and_response(cls, model, response): """ Create a ``KubernetesError`` for the given error response from a Kubernetes server. :param model: The Kubernetes data model to use to convert the server response into a Python object. :param twisted.web.iweb.IResponse response: The response to inspect for the error details. :return Deferred(KubernetesError): The error with details attached. """ d = readBody(response) d.addCallback( lambda body: cls( response.code, model.iobject_from_raw(loads(body)), ), ) return d
def getPage(self, url): resp = yield self.http_agent.request(b'GET', url.encode()) body = yield web_client.readBody(resp) returnValue(body.decode()) # before-end calls
def _fetch_key_with_fingerprint(self, km, fingerprint, key): """ :returns: a Deferred that will fire with the OpenPGPKey """ data = json.dumps({'fingerprint': fingerprint, 'openpgp': key}) client.readBody = mock.Mock(return_value=defer.succeed(data)) # mock the fetcher so it returns the key for KEY_FINGERPRINT km._nicknym._async_client_pinned.request = mock.Mock( return_value=defer.succeed(None)) km.ca_cert_path = 'cacertpath' key = km._nicknym.fetch_key_with_fingerprint(fingerprint) return key
def _fetch_and_handle_404_from_nicknym(self, uri): """ Send a GET request to C{uri} containing C{data}. :param uri: The URI of the request. :type uri: str :return: A deferred that will be fired with GET content as json (dict) :rtype: Deferred """ def check_code(response): if response.code == NOT_FOUND: message = ' %s: Key not found. Request: %s' \ % (response.code, uri) self.log.warn(message) raise KeyNotFound(message), None, sys.exc_info()[2] if response.code == SERVICE_UNAVAILABLE: message = ' %s: Service unavailable (maybe in maintenance).' \ 'Request: %s' % (response.code, uri) self.log.warn(message) raise KeyNotFound(message), None, sys.exc_info()[2] if response.code == BAD_GATEWAY: message = ' %s: Bad gateway. Request: %s. Response: %s' \ % (response.code, uri, response) self.log.warn(message) raise KeyNotFound(message), None, sys.exc_info()[2] return response d = self._async_client_pinned.request(str(uri), 'GET', callback=check_code) d.addCallback(client.readBody) return d
def _handle_request(self, response): self.responding = True d = readBody(response) d.addCallback(self._handle_body) return d
def do_fetch(self): time_start = time.time() path = self.random_path() agent = OnionRoutedAgent(reactor, path=path, state=self.tor) url = "http://127.0.0.1:{}".format(self.port) request = yield agent.request("GET", url) body = yield readBody(request) assert len(body) == self.fetch_size circ = [c for c in self.tor.circuits.values() if c.path == path][0] assert isinstance(circ, Circuit) # XXX: Wait for circuit to close, then I think we can be sure that # the BW events have been emitted. yield circ.close(ifUnused=True) defer.returnValue({'duration': time.time() - time_start, 'circ': circ})
def test_do_request(self): agent = OnionRoutedAgent(reactor, path=self.random_path(), state=self.tor) url = "http://127.0.0.1:{}".format(self.port) request = yield agent.request("GET", url) body = yield readBody(request) yield self.assertEqual(body, 'GET')
def test_success(self): """ L{client.readBody} returns a L{Deferred} which fires with the complete body of the L{IResponse} provider passed to it. """ response = DummyResponse() d = client.readBody(response) response.protocol.dataReceived(b"first") response.protocol.dataReceived(b"second") response.protocol.connectionLost(Failure(ResponseDone())) self.assertEqual(self.successResultOf(d), b"firstsecond")
def test_cancel(self): """ When cancelling the L{Deferred} returned by L{client.readBody}, the connection to the server will be aborted. """ response = DummyResponse() deferred = client.readBody(response) deferred.cancel() self.failureResultOf(deferred, defer.CancelledError) self.assertTrue(response.transport.aborting)
def test_otherErrors(self): """ If there is an exception other than L{client.PotentialDataLoss} while L{client.readBody} is collecting the response body, the L{Deferred} returned by {client.readBody} fires with that exception. """ response = DummyResponse() d = client.readBody(response) response.protocol.dataReceived(b"first") response.protocol.connectionLost( Failure(ConnectionLost("mystery problem"))) reason = self.failureResultOf(d) reason.trap(ConnectionLost) self.assertEqual(reason.value.args, ("mystery problem",))
def testCGI(self): cgiFilename = self.writeCGI(DUMMY_CGI) portnum = self.startServer(cgiFilename) d = client.Agent(reactor).request( "GET", 'http://localhost:%d/cgi' % (portnum,)) d.addCallback(client.readBody) d.addCallback(self._testCGI_1) return d
def testReadEmptyInput(self): cgiFilename = os.path.abspath(self.mktemp()) with open(cgiFilename, 'wt') as cgiFile: cgiFile.write(READINPUT_CGI) portnum = self.startServer(cgiFilename) agent = client.Agent(reactor) d = agent.request(b"GET", "http://localhost:%d/cgi" % (portnum,)) d.addCallback(client.readBody) d.addCallback(self._testReadEmptyInput_1) return d
def testReadAllInput(self): cgiFilename = os.path.abspath(self.mktemp()) with open(cgiFilename, 'wt') as cgiFile: cgiFile.write(READALLINPUT_CGI) portnum = self.startServer(cgiFilename) d = client.Agent(reactor).request( uri="http://localhost:%d/cgi" % (portnum,), method=b"POST", bodyProducer=client.FileBodyProducer( BytesIO(b"Here is your stdin")), ) d.addCallback(client.readBody) d.addCallback(self._testReadAllInput_1) return d
def test_errorXMLContent(self): """ Test that an invalid XML input returns an L{xmlrpc.Fault}. """ agent = client.Agent(reactor) d = agent.request( uri=networkString("http://127.0.0.1:%d/" % (self.port,)), method=b"POST", bodyProducer=client.FileBodyProducer(BytesIO(b"foo"))) d.addCallback(client.readBody) def cb(result): self.assertRaises(xmlrpc.Fault, xmlrpclib.loads, result) d.addCallback(cb) return d
def test_lantern_circumvent(self): def addResultToReport(result): self.report['body'] = result if result.startswith(self.localOptions['expected-body']): log.msg("Got the HTTP response body I expected!") self.report['success'] = True else: self.report['success'] = False def addFailureToReport(failure): log.err("Failed to connect to lantern") log.failure(failure) self.report['failure'] = handleAllFailures(failure) self.report['success'] = False def doRequest(noreason): proxyEndpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 8787) agent = ProxyAgent(proxyEndpoint, reactor) log.msg("Doing HTTP request via Lantern (127.0.0.1:8787) for %s" % self.url) request = agent.request("GET", self.url) request.addCallback(readBody) request.addCallback(addResultToReport) request.addCallback(self.processDirector.close) return request self.bootstrapped.addCallback(doRequest) self.bootstrapped.addErrback(addFailureToReport) self.bootstrapped.addBoth(self.stop) self.d = self.run(self.command, env=os.environ, usePTY=1) return self.d
def test_openvpn_circumvent(self): def addResultToReport(result): log.debug("request_successful") self.report['body'] = result self.report['success'] = True def addFailureToReport(failure): log.debug("Failed: %s" % failureToString(failure)) self.report['failure'] = failureToString(failure) self.report['success'] = False def doRequest(noreason): """Make a HTTP request over initialized VPN connection""" agent = Agent(reactor) log.debug("Doing HTTP request to the OpenVPN subnet: %s" % self.url) request = agent.request("GET", self.url) request.addCallback(readBody) request.addCallback(addResultToReport) request.addErrback(addFailureToReport) return request log.debug("Spawning OpenVPN") self.d = self.run(self.command) # Monkeypatch inConnectionLost and processExited to log when OpenVPN exits early self.processDirector.inConnectionLost = self.inConnectionLost self.processDirector.processExited = self.processExited # Try to make a request when the OpenVPN connection successfully bootstraps self.bootstrapped.addCallback(doRequest) # Fire failure if OpenVPN connection fails self.bootstrapped.addErrback(addFailureToReport) # Close OpenVPN after each successful or failed test self.bootstrapped.addBoth(self.stop) return self.d
def test_redirect_works(self): if not is_internet_connected(): raise unittest.SkipTest("Internet connection missing") agent = FixedRedirectAgent(TrueHeadersAgent(reactor)) headers = TrueHeaders({"Spam": ["ham"]}) url = "http://httpbin.org/absolute-redirect/3" response = yield agent.request('GET', url, headers) body = yield readBody(response) j = json.loads(body) self.assertEqual(j['headers']['Spam'], 'ham')
def openapi(self): """ Issue a I{GET} for the Kubernetes OpenAPI specification. """ action = start_action( action_type=u"network-client:openapi", ) with action.context(): url = self.kubernetes.base_url.child(u"swagger.json") d = DeferredContext(self._get(url)) d.addCallback(check_status, (OK,), self.model) d.addCallback(readBody) d.addCallback(loads) return d.addActionFinish()
def put_key(self, uid, key_data, api_uri, api_version): """ Send a PUT request to C{uri} containing C{data}. The request will be sent using the configured CA certificate path to verify the server certificate and the configured session id for authentication. :param uid: The URI of the request. :type uid: str :param key_data: The body of the request. :type key_data: dict, str or file :return: A deferred that will be fired when PUT request finishes :rtype: Deferred """ data = { self.PUBKEY_KEY: key_data } uri = "%s/%s/users/%s.json" % ( api_uri, api_version, uid) leap_assert( self.token is not None, 'We need a token to interact with webapp!') if type(data) == dict: data = urllib.urlencode(data) headers = {'Authorization': [str('Token token=%s' % self.token)]} headers['Content-Type'] = ['application/x-www-form-urlencoded'] try: res = yield self._async_client_pinned.request(str(uri), 'PUT', body=str(data), headers=headers) except Exception as e: self.log.warn('Error uploading key: %r' % (e,)) raise e if 'error' in res: # FIXME: That's a workaround for 500, # we need to implement a readBody to assert response code self.log.warn('Error uploading key: %r' % (res,)) raise Exception(res)
def authenticate_bind_request(self, request): """ Given a LDAP bind request: * Check if it is contained in the bind cache. If yes: Return success and bind the service account. * If not: resolve the DN and redirect the request to privacyIDEA. :param request: An `pureldap.LDAPBindRequest` instance. :return: Deferred that fires a tuple ``(success, message)``, whereas ``success`` denotes whether privacyIDEA successfully validated the given password. If ``success`` is ``False``, ``message`` contains an error message. """ #: This 2-tuple has the following semantics: #: If the first element is True, authentication has succeeded! The second element then #: contains the app marker as a string. #: If the first element is False, authentication has failed. The second element then contains #: the error message. result = (False, '') try: app_marker, realm = yield self.factory.resolve_realm(request.dn) user = yield self.factory.resolve_user(request.dn) except UserMappingError: # User could not be found log.info('Could not resolve {dn!r} to user', dn=request.dn) result = (False, 'Invalid user.') except RealmMappingError, e: # Realm could not be mapped log.info('Could not resolve {dn!r} to realm: {message!r}', dn=request.dn, message=e.message) # TODO: too much information revealed? result = (False, 'Could not determine realm.') else: log.info('Resolved {dn!r} to {user!r}@{realm!r} ({marker!r})', dn=request.dn, user=user, realm=realm, marker=app_marker) password = request.auth if self.factory.is_bind_cached(request.dn, app_marker, request.auth): log.info('Combination found in bind cache!') result = (True, app_marker) else: response = yield self.request_validate(self.factory.validate_url, user, realm, password) json_body = yield readBody(response) if response.code == 200: body = json.loads(json_body) if body['result']['status']: if body['result']['value']: result = (True, app_marker) else: result = (False, 'Failed to authenticate.') else: result = (False, 'Failed to authenticate. privacyIDEA error.') else: result = (False, 'Failed to authenticate. Wrong HTTP response ({})'.format(response.code)) # TODO: Is this the right place to bind the service user? # (check that result[0] is actually True and not just truthy) if result[0] is True and self.factory.bind_service_account: log.info('Successful authentication, authenticating as service user ...') # Reset value in case the connection is re-used self.forwarded_passthrough_bind = False yield self.bind_service_account() defer.returnValue(result)
def fetch(self, path): url = self.choose_url(path) assert None not in path log.msg('Downloading {} over {}, {}'.format(url,path[0].id_hex, path[-1].id_hex)) file_size = self.choose_file_size(path) time_start = self.now() @defer.inlineCallbacks def get_circuit_bw(result): time_end = self.now() if len(result) < file_size: raise DownloadIncomplete report = dict() report['time_end'] = time_end report['time_start'] = time_start report['circ_bw'] = (len(result) * 1000) / (report['time_end'] - report['time_start']) report['path'] = [r.id_hex for r in path] # We need to wait for these deferreds to be ready, we can't serialize # deferreds. report['path_desc_bws'] = [] report['path_ns_bws'] = [] for relay in path: report['path_desc_bws'].append((yield self.get_r_desc_bw(relay))) report['path_ns_bws'].append((yield self.get_r_ns_bw(relay))) report['path_bws'] = [r.bandwidth for r in path] defer.returnValue(report) def circ_failure(failure): time_end = self.now() report = dict() report['time_end'] = time_end report['time_start'] = time_start report['path'] = [r.id_hex for r in path] report['failure'] = failure.__repr__() return report agent = OnionRoutedAgent(self.clock, path=path, state=self.state) request = agent.request("GET", url) timeout_circuit = self.clock.callLater(self.circuit_lifetime, request.cancel) request.addCallback(readBody) request.addCallbacks(get_circuit_bw, errback=circ_failure) request.addCallback(self.result_sink.send) # Stop circuit timeout callLater when we have been successful request.addCallback(lambda _: timeout_circuit.cancel()) self.tasks.append(request)
def _cbResponse(self, response, request, headers_processor, body_processor): """ This callback is fired once we have gotten a response for our request. If we are using a RedirectAgent then this will fire once we have reached the end of the redirect chain. Args: response (:twisted.web.iweb.IResponse:): a provider for getting our response request (dict): the dict containing our response (XXX this should be dropped) header_processor (func): a function to be called with argument a dict containing the response headers. This will lead self.headerProcessor to not be called. body_processor (func): a function to be called with as argument the body of the response. This will lead self.bodyProcessor to not be called. """ if not response: log.err("Got no response for request %s" % request) HTTPTest.addToReport(self, request, response) return else: log.debug("Got response") log.debug("code: %d" % response.code) log.debug("headers: %s" % response.headers.getAllRawHeaders()) if str(response.code).startswith('3'): self.processRedirect(response.headers.getRawHeaders('Location')[0]) # [!] We are passing to the headers_processor the headers dict and # not the Headers() object response_headers_dict = list(response.headers.getAllRawHeaders()) if headers_processor: headers_processor(response_headers_dict) else: self.processResponseHeaders(response_headers_dict) finished = readBody(response) finished.addErrback(self._processResponseBodyFail, request, response) finished.addCallback(self._processResponseBody, request, response, body_processor) return finished