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})
python类readBody()的实例源码
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