diff options
author | Armin Ronacher <armin.ronacher@active-4.com> | 2016-11-22 15:01:03 +0100 |
---|---|---|
committer | Armin Ronacher <armin.ronacher@active-4.com> | 2016-11-22 15:01:03 +0100 |
commit | 2df48fbe62afeed75ce331430cf554ac6cbc533b (patch) | |
tree | f20061dc5e23aefbee376e57e3f26ee88c8be9bc | |
parent | 9a5757c070eb4cf3b06168bf1914ffee978c40f9 (diff) | |
download | raven-2df48fbe62afeed75ce331430cf554ac6cbc533b.tar.gz |
Refactor transports to support multiple URLs
-rw-r--r-- | raven/base.py | 4 | ||||
-rw-r--r-- | raven/conf/remote.py | 4 | ||||
-rw-r--r-- | raven/transport/base.py | 4 | ||||
-rw-r--r-- | raven/transport/eventlet.py | 17 | ||||
-rw-r--r-- | raven/transport/gevent.py | 8 | ||||
-rw-r--r-- | raven/transport/http.py | 9 | ||||
-rw-r--r-- | raven/transport/requests.py | 4 | ||||
-rw-r--r-- | raven/transport/threaded.py | 8 | ||||
-rw-r--r-- | raven/transport/threaded_requests.py | 8 | ||||
-rw-r--r-- | raven/transport/tornado.py | 10 | ||||
-rw-r--r-- | raven/transport/twisted.py | 8 | ||||
-rw-r--r-- | tests/base/tests.py | 4 | ||||
-rw-r--r-- | tests/transport/requests/test_threaded_requests.py | 8 | ||||
-rw-r--r-- | tests/transport/tests.py | 7 | ||||
-rw-r--r-- | tests/transport/threaded/tests.py | 20 |
15 files changed, 59 insertions, 64 deletions
diff --git a/raven/base.py b/raven/base.py index 7809823..50cad34 100644 --- a/raven/base.py +++ b/raven/base.py @@ -686,10 +686,10 @@ class Client(object): try: transport = self.remote.get_transport() if transport.async: - transport.async_send(data, headers, self._successful_send, + transport.async_send(url, data, headers, self._successful_send, failed_send) else: - transport.send(data, headers) + transport.send(url, data, headers) self._successful_send() except Exception as e: if self.raise_send_errors: diff --git a/raven/conf/remote.py b/raven/conf/remote.py index d7f0605..641741a 100644 --- a/raven/conf/remote.py +++ b/raven/conf/remote.py @@ -60,14 +60,12 @@ class RemoteConfig(object): def is_active(self): return all([self.base_url, self.project, self.public_key, self.secret_key]) - # TODO(dcramer): we dont want transports bound to a URL def get_transport(self): if not self.store_endpoint: return if not hasattr(self, '_transport'): - parsed = urlparse(self.store_endpoint) - self._transport = self._transport_cls(parsed, **self.options) + self._transport = self._transport_cls(**self.options) return self._transport def get_public_dsn(self): diff --git a/raven/transport/base.py b/raven/transport/base.py index f3adb28..f70a65b 100644 --- a/raven/transport/base.py +++ b/raven/transport/base.py @@ -22,7 +22,7 @@ class Transport(object): async = False scheme = [] - def send(self, data, headers): + def send(self, url, data, headers): """ You need to override this to do something with the actual data. Usually - this is sending to a server @@ -41,7 +41,7 @@ class AsyncTransport(Transport): async = True - def async_send(self, data, headers, success_cb, error_cb): + def async_send(self, url, data, headers, success_cb, error_cb): """ Override this method for asynchronous transports. Call `success_cb()` if the send succeeds or `error_cb(exception)` diff --git a/raven/transport/eventlet.py b/raven/transport/eventlet.py index 48b783f..46045ef 100644 --- a/raven/transport/eventlet.py +++ b/raven/transport/eventlet.py @@ -26,27 +26,26 @@ class EventletHTTPTransport(HTTPTransport): scheme = ['eventlet+http', 'eventlet+https'] - def __init__(self, parsed_url, pool_size=100, **kwargs): + def __init__(self, pool_size=100, **kwargs): if not has_eventlet: raise ImportError('EventletHTTPTransport requires eventlet.') - super(EventletHTTPTransport, self).__init__(parsed_url, **kwargs) - # remove the eventlet+ from the protocol, as it is not a real protocol - self._url = self._url.split('+', 1)[-1] + super(EventletHTTPTransport, self).__init__(**kwargs) def _send_payload(self, payload): - req = eventlet_urllib2.Request(self._url, headers=payload[1]) + url, data, headers = payload + req = eventlet_urllib2.Request(url, headers=headers) try: if sys.version_info < (2, 6): - response = eventlet_urllib2.urlopen(req, payload[0]).read() + response = eventlet_urllib2.urlopen(req, data).read() else: - response = eventlet_urllib2.urlopen(req, payload[0], + response = eventlet_urllib2.urlopen(req, data, self.timeout).read() return response except Exception as err: return err - def send(self, data, headers): + def send(self, url, data, headers): """ Spawn an async request to a remote webserver. """ - eventlet.spawn(self._send_payload, (data, headers)) + eventlet.spawn(self._send_payload, (url, data, headers)) diff --git a/raven/transport/gevent.py b/raven/transport/gevent.py index 3f7c208..c2cf409 100644 --- a/raven/transport/gevent.py +++ b/raven/transport/gevent.py @@ -26,15 +26,15 @@ class GeventedHTTPTransport(AsyncTransport, HTTPTransport): scheme = ['gevent+http', 'gevent+https'] - def __init__(self, parsed_url, maximum_outstanding_requests=100, *args, **kwargs): + def __init__(self, maximum_outstanding_requests=100, *args, **kwargs): if not has_gevent: raise ImportError('GeventedHTTPTransport requires gevent.') self._lock = Semaphore(maximum_outstanding_requests) - super(GeventedHTTPTransport, self).__init__(parsed_url, *args, **kwargs) + super(GeventedHTTPTransport, self).__init__(*args, **kwargs) - def async_send(self, data, headers, success_cb, failure_cb): + def async_send(self, url, data, headers, success_cb, failure_cb): """ Spawn an async request to a remote webserver. """ @@ -42,7 +42,7 @@ class GeventedHTTPTransport(AsyncTransport, HTTPTransport): # read the response since we don't use it. self._lock.acquire() return gevent.spawn( - super(GeventedHTTPTransport, self).send, data, headers + super(GeventedHTTPTransport, self).send, url, data, headers ).link(lambda x: self._done(x, success_cb, failure_cb)) def _done(self, greenlet, success_cb, failure_cb, *args): diff --git a/raven/transport/http.py b/raven/transport/http.py index fd84056..29ecdc8 100644 --- a/raven/transport/http.py +++ b/raven/transport/http.py @@ -18,11 +18,8 @@ from raven.utils.compat import urllib2 class HTTPTransport(Transport): scheme = ['sync+http', 'sync+https'] - def __init__(self, parsed_url, timeout=defaults.TIMEOUT, verify_ssl=True, + def __init__(self, timeout=defaults.TIMEOUT, verify_ssl=True, ca_certs=defaults.CA_BUNDLE): - self._parsed_url = parsed_url - self._url = parsed_url.geturl().rsplit('+', 1)[-1] - if isinstance(timeout, string_types): timeout = int(timeout) if isinstance(verify_ssl, string_types): @@ -32,11 +29,11 @@ class HTTPTransport(Transport): self.verify_ssl = verify_ssl self.ca_certs = ca_certs - def send(self, data, headers): + def send(self, url, data, headers): """ Sends a request to a remote webserver using HTTP POST. """ - req = urllib2.Request(self._url, headers=headers) + req = urllib2.Request(url, headers=headers) try: response = urlopen( diff --git a/raven/transport/requests.py b/raven/transport/requests.py index f51c32a..8310ef3 100644 --- a/raven/transport/requests.py +++ b/raven/transport/requests.py @@ -26,10 +26,10 @@ class RequestsHTTPTransport(HTTPTransport): super(RequestsHTTPTransport, self).__init__(*args, **kwargs) - def send(self, data, headers): + def send(self, url, data, headers): if self.verify_ssl: # If SSL verification is enabled use the provided CA bundle to # perform the verification. self.verify_ssl = self.ca_certs - requests.post(self._url, data=data, headers=headers, + requests.post(url, data=data, headers=headers, verify=self.verify_ssl, timeout=self.timeout) diff --git a/raven/transport/threaded.py b/raven/transport/threaded.py index 33777b4..080b9b7 100644 --- a/raven/transport/threaded.py +++ b/raven/transport/threaded.py @@ -169,14 +169,14 @@ class ThreadedHTTPTransport(AsyncTransport, HTTPTransport): self._worker = AsyncWorker() return self._worker - def send_sync(self, data, headers, success_cb, failure_cb): + def send_sync(self, url, data, headers, success_cb, failure_cb): try: - super(ThreadedHTTPTransport, self).send(data, headers) + super(ThreadedHTTPTransport, self).send(url, data, headers) except Exception as e: failure_cb(e) else: success_cb() - def async_send(self, data, headers, success_cb, failure_cb): + def async_send(self, url, data, headers, success_cb, failure_cb): self.get_worker().queue( - self.send_sync, data, headers, success_cb, failure_cb) + self.send_sync, url, data, headers, success_cb, failure_cb) diff --git a/raven/transport/threaded_requests.py b/raven/transport/threaded_requests.py index 431c2eb..cdc05a3 100644 --- a/raven/transport/threaded_requests.py +++ b/raven/transport/threaded_requests.py @@ -21,14 +21,14 @@ class ThreadedRequestsHTTPTransport(AsyncTransport, RequestsHTTPTransport): self._worker = AsyncWorker() return self._worker - def send_sync(self, data, headers, success_cb, failure_cb): + def send_sync(self, url, data, headers, success_cb, failure_cb): try: - super(ThreadedRequestsHTTPTransport, self).send(data, headers) + super(ThreadedRequestsHTTPTransport, self).send(url, data, headers) except Exception as e: failure_cb(e) else: success_cb() - def async_send(self, data, headers, success_cb, failure_cb): + def async_send(self, url, data, headers, success_cb, failure_cb): self.get_worker().queue( - self.send_sync, data, headers, success_cb, failure_cb) + self.send_sync, url, data, headers, success_cb, failure_cb) diff --git a/raven/transport/tornado.py b/raven/transport/tornado.py index c58967e..08343b4 100644 --- a/raven/transport/tornado.py +++ b/raven/transport/tornado.py @@ -24,13 +24,13 @@ class TornadoHTTPTransport(AsyncTransport, HTTPTransport): scheme = ['tornado+http', 'tornado+https'] - def __init__(self, parsed_url, *args, **kwargs): + def __init__(self, *args, **kwargs): if not has_tornado: raise ImportError('TornadoHTTPTransport requires tornado.') - super(TornadoHTTPTransport, self).__init__(parsed_url, *args, **kwargs) + super(TornadoHTTPTransport, self).__init__(*args, **kwargs) - def async_send(self, data, headers, success_cb, failure_cb): + def async_send(self, url, data, headers, success_cb, failure_cb): kwargs = dict(method='POST', headers=headers, body=data) kwargs["validate_cert"] = self.verify_ssl kwargs["connect_timeout"] = self.timeout @@ -41,12 +41,12 @@ class TornadoHTTPTransport(AsyncTransport, HTTPTransport): client = AsyncHTTPClient() kwargs['callback'] = None - future = client.fetch(self._url, **kwargs) + future = client.fetch(url, **kwargs) ioloop.IOLoop.current().add_future(future, partial(self.handler, success_cb, failure_cb)) else: client = HTTPClient() try: - client.fetch(self._url, **kwargs) + client.fetch(url, **kwargs) success_cb() except Exception as e: failure_cb(e) diff --git a/raven/transport/twisted.py b/raven/transport/twisted.py index c087718..2dae628 100644 --- a/raven/transport/twisted.py +++ b/raven/transport/twisted.py @@ -26,11 +26,11 @@ except: class TwistedHTTPTransport(AsyncTransport, HTTPTransport): scheme = ['twisted+http', 'twisted+https'] - def __init__(self, parsed_url, *args, **kwargs): + def __init__(self, *args, **kwargs): if not has_twisted: raise ImportError('TwistedHTTPTransport requires twisted.web.') - super(TwistedHTTPTransport, self).__init__(parsed_url, *args, **kwargs) + super(TwistedHTTPTransport, self).__init__(*args, **kwargs) # Import reactor as late as possible. from twisted.internet import reactor @@ -38,9 +38,9 @@ class TwistedHTTPTransport(AsyncTransport, HTTPTransport): # Use a persistent connection pool. self._agent = Agent(reactor, pool=HTTPConnectionPool(reactor)) - def async_send(self, data, headers, success_cb, failure_cb): + def async_send(self, url, data, headers, success_cb, failure_cb): d = self._agent.request( - b"POST", self._url, + b"POST", url, bodyProducer=FileBodyProducer(io.BytesIO(data)), headers=Headers(dict((k, [v]) for k, v in headers.items())) ) diff --git a/tests/base/tests.py b/tests/base/tests.py index cb988da..63ea8a0 100644 --- a/tests/base/tests.py +++ b/tests/base/tests.py @@ -163,13 +163,13 @@ class ClientTest(TestCase): # test recovery client.send_remote('http://example.com/api/1/store/', client.encode({})) - success_cb = async_send.call_args[0][2] + success_cb = async_send.call_args[0][3] success_cb() self.assertEquals(client.state.status, client.state.ONLINE) # test delayed raise of error client.send_remote('http://example.com/api/1/store/', client.encode({})) - failure_cb = async_send.call_args[0][3] + failure_cb = async_send.call_args[0][4] failure_cb(Exception()) self.assertEquals(client.state.status, client.state.ERROR) diff --git a/tests/transport/requests/test_threaded_requests.py b/tests/transport/requests/test_threaded_requests.py index 6428061..2147962 100644 --- a/tests/transport/requests/test_threaded_requests.py +++ b/tests/transport/requests/test_threaded_requests.py @@ -13,12 +13,12 @@ class DummyThreadedScheme(ThreadedRequestsHTTPTransport): self.events = [] self.send_delay = 0 - def send_sync(self, data, headers, success_cb, failure_cb): + def send_sync(self, url, data, headers, success_cb, failure_cb): # delay sending the message, to allow us to test that the shutdown # hook waits correctly time.sleep(self.send_delay) - self.events.append((data, headers, success_cb, failure_cb)) + self.events.append((url, data, headers, success_cb, failure_cb)) class ThreadedTransportTest(TestCase): @@ -38,11 +38,11 @@ class ThreadedTransportTest(TestCase): def test_shutdown_waits_for_send(self): url = urlparse(self.url) - transport = DummyThreadedScheme(url) + transport = DummyThreadedScheme() transport.send_delay = 0.5 data = self.client.build_msg('raven.events.Message', message='foo') - transport.async_send(data, None, None, None) + transport.async_send(url, data, None, None, None) time.sleep(0.1) diff --git a/tests/transport/tests.py b/tests/transport/tests.py index 2a69cf0..ecec09a 100644 --- a/tests/transport/tests.py +++ b/tests/transport/tests.py @@ -21,14 +21,14 @@ class DummyScheme(Transport): scheme = ['mock'] - def __init__(self, parsed_url, timeout=5): - self._parsed_url = parsed_url + def __init__(self, timeout=5): self.timeout = timeout - def send(self, data, headers): + def send(self, url, data, headers): """ Sends a request to a remote webserver """ + self._url = url self._data = data self._headers = headers @@ -56,6 +56,7 @@ class TransportTest(TestCase): c.send(**data) mock_cls = c._transport_cache['mock://some_username:some_password@localhost:8143/1'].get_transport() + print(mock_cls.__dict__) expected_message = zlib.decompress(c.encode(data)) actual_message = zlib.decompress(mock_cls._data) diff --git a/tests/transport/threaded/tests.py b/tests/transport/threaded/tests.py index f63dc71..e07e0b0 100644 --- a/tests/transport/threaded/tests.py +++ b/tests/transport/threaded/tests.py @@ -16,12 +16,12 @@ class DummyThreadedScheme(ThreadedHTTPTransport): self.events = [] self.send_delay = 0 - def send_sync(self, data, headers, success_cb, failure_cb): + def send_sync(self, url, data, headers, success_cb, failure_cb): # delay sending the message, to allow us to test that the shutdown # hook waits correctly time.sleep(self.send_delay) - self.events.append((data, headers, success_cb, failure_cb)) + self.events.append((url, data, headers, success_cb, failure_cb)) class LoggingThreadedScheme(ThreadedHTTPTransport): @@ -29,7 +29,7 @@ class LoggingThreadedScheme(ThreadedHTTPTransport): super(LoggingThreadedScheme, self).__init__(*args, **kwargs) self.filename = filename - def send_sync(self, data, headers, success_cb, failure_cb): + def send_sync(self, url, data, headers, success_cb, failure_cb): with open(self.filename, 'a') as log: log.write("{0} {1}\n".format(os.getpid(), data['message'])) @@ -51,11 +51,11 @@ class ThreadedTransportTest(TestCase): def test_shutdown_waits_for_send(self): url = urlparse(self.url) - transport = DummyThreadedScheme(url) + transport = DummyThreadedScheme() transport.send_delay = 0.5 data = self.client.build_msg('raven.events.Message', message='foo') - transport.async_send(data, None, None, None) + transport.async_send(url, data, None, None, None) time.sleep(0.1) @@ -66,7 +66,7 @@ class ThreadedTransportTest(TestCase): def test_fork_spawns_anew(self): url = urlparse(self.url) - transport = DummyThreadedScheme(url) + transport = DummyThreadedScheme() transport.send_delay = 0.5 data = self.client.build_msg('raven.events.Message', message='foo') @@ -75,7 +75,7 @@ class ThreadedTransportTest(TestCase): if pid == 0: time.sleep(0.1) - transport.async_send(data, None, None, None) + transport.async_send(url, data, None, None, None) # this should wait for the message to get sent transport.get_worker().main_thread_terminated() @@ -97,15 +97,15 @@ class ThreadedTransportTest(TestCase): fd, filename = mkstemp() try: os.close(fd) - transport = LoggingThreadedScheme(filename, url) + transport = LoggingThreadedScheme(filename) # Log from the parent process - starts the worker thread - transport.async_send(event1, None, None, None) + transport.async_send(url, event1, None, None, None) childpid = os.fork() if childpid == 0: # Log from the child process - transport.async_send(event2, None, None, None) + transport.async_send(url, event2, None, None, None) # Ensure threaded worker has finished transport.get_worker().stop() |