def performance(duration=10, print_output=True): parser = RequestParser(ParserDelegate()) runs = 0 then = time.time() while time.time() - then < duration: parser.execute(NORMAL_REQUEST) runs += 1 if print_output: print('Ran {} times in {} seconds for {} runs per second.'.format( runs, duration, runs / float(duration)))
class ProxyConnection(object): """ A proxy connection manages the lifecycle of the sockets opened during a proxied client request against Pyrox. """ def __init__(self, us_filter_pipeline, ds_filter_pipeline, downstream, upstream, upstream_host): self.downstream = downstream self.upstream = upstream self.downstream_handler = DownstreamProxyHandler( ds_filter_pipeline, downstream, upstream, upstream_host) self.upstream_handler = UpstreamProxyHandler( us_filter_pipeline, downstream, upstream) self.downstream_parser = RequestParser(self.downstream_handler) self.upstream_parser = ResponseParser(self.upstream_handler) def on_upstream_connect(self): # Downstream callbacks self.downstream.set_close_callback(self._on_downstream_close) self.downstream.read_until_close( callback=self._on_downstream_read, streaming_callback=self._on_downstream_read) # Upstream callbacks self.upstream.set_close_callback(self._on_upstream_close) self.upstream.read_until_close( callback=self._on_upstream_read, streaming_callback=self._on_upstream_read) def _on_downstream_close(self): if not self.upstream.closed(): self.upstream.close() self.downstream_parser.destroy() def _on_upstream_close(self): if not self.downstream.closed(): self.downstream.close() self.upstream_parser.destroy() def _on_downstream_read(self, data): try: self.downstream_parser.execute(data) except iostream.StreamClosedError: pass except Exception as ex: _LOG.exception(ex) def _on_upstream_read(self, data): try: self.upstream_parser.execute(data) except iostream.StreamClosedError: pass except Exception as ex: _LOG.exception(ex)
def performance(duration=10, print_output=True): parser = RequestParser(ParserDelegate()) runs = 0 then = time.time() while time.time() - then < duration: parser.execute(NORMAL_REQUEST, len(NORMAL_REQUEST)) runs += 1 if print_output: print('Ran {} times in {} seconds for {} runs per second.'.format( runs, duration, runs / float(duration)))
def __init__(self, us_filter_pipeline, ds_filter_pipeline, downstream, upstream, upstream_host): self.downstream = downstream self.upstream = upstream self.downstream_handler = DownstreamProxyHandler( ds_filter_pipeline, downstream, upstream, upstream_host) self.upstream_handler = UpstreamProxyHandler( us_filter_pipeline, downstream, upstream) self.downstream_parser = RequestParser(self.downstream_handler) self.upstream_parser = ResponseParser(self.upstream_handler)
def __init__(self, us_filter_pl, ds_filter_pl, downstream, router): self._ds_filter_pl = ds_filter_pl self._us_filter_pl = us_filter_pl self._router = router self._upstream_parser = None self._upstream_tracker = ConnectionTracker( self._on_upstream_live, self._on_upstream_close, self._on_upstream_error) # Setup all of the wiring for downstream self._downstream = downstream self._downstream_handler = DownstreamHandler( self._downstream, self._ds_filter_pl, self._connect_upstream) self._downstream_parser = RequestParser(self._downstream_handler) self._downstream.on_close(self._on_downstream_close) self._downstream.read(self._on_downstream_read)
def _init_downstream(self): self.downstream_handler = DownstreamHandler( self.downstream, self.ds_filter_pl, self.connect_upstream) self.downstream_parser = RequestParser(self.downstream_handler) # Downstream callbacks self.downstream.set_close_callback(self._on_downstream_close) self.downstream.read_bytes( num_bytes=MAX_READ, callback=self._on_downstream_read, streaming_callback=self._on_downstream_read)
def __init__(self, us_filter_pl, ds_filter_pl, downstream, router): self._ds_filter_pl = ds_filter_pl self._us_filter_pl = us_filter_pl self._router = router self._upstream_parser = None self._upstream_tracker = ConnectionTracker(self._on_upstream_live, self._on_pipe_broken) # Setup all of the wiring for downstream self._downstream = downstream self._downstream_handler = DownstreamHandler(self._downstream, self._ds_filter_pl, self._connect_upstream) self._downstream_parser = RequestParser(self._downstream_handler) self._downstream.set_close_callback(self._on_downstream_close) self._downstream.read_until_close( callback=self._on_downstream_read, streaming_callback=self._on_downstream_read )
def test_reading_chunked_request(self): tracker = TrackingDelegate(ValidatingDelegate(self)) parser = RequestParser(tracker) chunk_message(CHUNKED_REQUEST, parser) tracker.validate_hits( { REQUEST_METHOD_SLOT: 1, REQUEST_URI_SLOT: 1, REQUEST_HTTP_VERSION_SLOT: 1, HEADER_FIELD_SLOT: 2, HEADER_VALUE_SLOT: 2, BODY_SLOT: 4, BODY_COMPLETE_SLOT: 1 }, self)
def test_reading_request_with_content_length(self): tracker = TrackingDelegate(NonChunkedValidatingDelegate(self)) parser = RequestParser(tracker) chunk_message(NORMAL_REQUEST, parser) tracker.validate_hits( { REQUEST_METHOD_SLOT: 1, REQUEST_URI_SLOT: 1, REQUEST_HTTP_VERSION_SLOT: 1, HEADER_FIELD_SLOT: 2, HEADER_VALUE_SLOT: 2, BODY_SLOT: 2, BODY_COMPLETE_SLOT: 1 }, self)
class ProxyConnection(object): """ A proxy connection manages the lifecycle of the sockets opened during a proxied client request against Pyrox. """ def __init__(self, us_filter_pl, ds_filter_pl, downstream, default_upstream_target): self.ds_filter_pl = ds_filter_pl self.us_filter_pl = us_filter_pl self.default_upstream_target = default_upstream_target self.hold_downstream = False self.downstream = downstream self.upstream = None self._init_downstream() def _init_downstream(self): self.downstream_handler = DownstreamHandler( self.downstream, self.ds_filter_pl, self.connect_upstream) self.downstream_parser = RequestParser(self.downstream_handler) # Downstream callbacks self.downstream.set_close_callback(self._on_downstream_close) self.downstream.read_bytes( num_bytes=MAX_READ, callback=self._on_downstream_read, streaming_callback=self._on_downstream_read) def connect_upstream(self, request, route=None): # Hold downstream reads self.hold_downstream = True # Request to proxy upstream self.request = request # Set up our upstream socket us_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) us_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) us_sock.setblocking(0) self.upstream = tornado.iostream.IOStream(us_sock) upstream_target = route if route else self.default_upstream_target self.upstream.connect(upstream_target, self.on_upstream_connect) def on_upstream_connect(self): # Upstream callbacks self.upstream_handler = UpstreamHandler(self.downstream, self.upstream, self.us_filter_pl) self.upstream_parser = ResponseParser(self.upstream_handler) self.upstream.set_close_callback(self._on_upstream_close) self.upstream.read_until_close( callback=self._on_upstream_read, streaming_callback=self._on_upstream_read) # Send the proxied request object self.upstream.write(self.request.to_bytes()) self.request = None # Allow downstream reads again self.hold_downstream = False if not self.downstream.reading(): self.downstream.read_bytes( num_bytes=MAX_READ, callback=self._on_downstream_read, streaming_callback=self._on_downstream_read) def _on_downstream_close(self): if self.upstream and not self.upstream.closed(): self.upstream.close() self.downstream_parser.destroy() def _on_upstream_close(self): if not self.downstream.closed(): self.downstream.close() self.upstream_parser.destroy() def _on_downstream_read(self, data): print('Read {} bytes from downstream'.format(len(data))) if len(data) > 0: try: self.downstream_parser.execute(data) except iostream.StreamClosedError: pass except Exception as ex: _LOG.exception(ex) elif not self.hold_downstream: self.downstream.read_bytes( num_bytes=MAX_READ, callback=self._on_downstream_read, streaming_callback=self._on_downstream_read) def _on_upstream_read(self, data): try: self.upstream_parser.execute(data) except iostream.StreamClosedError: pass except Exception as ex: _LOG.exception(ex)
class ProxyConnection(object): """ A proxy connection manages the lifecycle of the sockets opened during a proxied client request against Pyrox. """ def __init__(self, us_filter_pl, ds_filter_pl, downstream, router): self._ds_filter_pl = ds_filter_pl self._us_filter_pl = us_filter_pl self._router = router self._upstream_parser = None self._upstream_tracker = ConnectionTracker( self._on_upstream_live, self._on_pipe_broken) # Setup all of the wiring for downstream self._downstream = downstream self._downstream_handler = DownstreamHandler( self._downstream, self._ds_filter_pl, self._connect_upstream) self._downstream_parser = RequestParser(self._downstream_handler) self._downstream.set_close_callback(self._on_downstream_close) self._downstream.read_until_close( callback=self._on_downstream_read, streaming_callback=self._on_downstream_read) def _connect_upstream(self, request, route=None): if route: # This does some type checking for routes passed up via filter self._router.set_next(route) upstream_target = self._router.get_next() # Hold downstream reads self._hold_downstream = True # Update the request to proxy upstream and store it request.replace_header('host').values.append( '{}:{}'.format(upstream_target[0], upstream_target[1])) self._request = request self._upstream_tracker.connect(upstream_target) def _on_upstream_live(self, upstream): self._upstream_handler = UpstreamHandler( self._downstream, upstream, self._us_filter_pl) if self._upstream_parser: self._upstream_parser.destroy() self._upstream_parser = ResponseParser(self._upstream_handler) # Send the proxied request object upstream.write(self._request.to_bytes()) # Set the read callback if it's not already reading if not upstream.reading(): upstream.read_until_close( callback=self._on_upstream_read, streaming_callback=self._on_upstream_read) # Drop the ref to the proxied request head self._request = None # Set up our downstream handler self._downstream_handler._upstream = upstream if not self._downstream.reading(): self._downstream.read_until_close( callback=self._on_downstream_read, streaming_callback=self._on_downstream_read) def _on_downstream_close(self): self._upstream_tracker.destroy() self._downstream_parser.destroy() def _on_pipe_broken(self): if not self._downstream.closed() and not self._downstream.closed(): self._downstream.close() if self._upstream_parser: self._upstream_parser.destroy() def _on_downstream_read(self, data): try: self._downstream_parser.execute(data) except StreamClosedError: pass except Exception as ex: _LOG.exception(ex) def _on_upstream_read(self, data): try: self._upstream_parser.execute(data) except StreamClosedError: pass except Exception as ex: _LOG.exception(ex)
def test_exception_propagation(self): tracker = TrackingDelegate(ValidatingDelegate(self)) parser = RequestParser(tracker) with self.assertRaises(Exception): chunk_message(UNEXPECTED_HEADER_REQUEST, parser)
class ProxyConnection(object): """ A proxy connection manages the lifecycle of the sockets opened during a proxied client request against Pyrox. """ def __init__(self, us_filter_pl, ds_filter_pl, downstream, router): self._ds_filter_pl = ds_filter_pl self._us_filter_pl = us_filter_pl self._router = router self._upstream_parser = None self._upstream_tracker = ConnectionTracker( self._on_upstream_live, self._on_upstream_close, self._on_upstream_error) # Setup all of the wiring for downstream self._downstream = downstream self._downstream_handler = DownstreamHandler( self._downstream, self._ds_filter_pl, self._connect_upstream) self._downstream_parser = RequestParser(self._downstream_handler) self._downstream.on_close(self._on_downstream_close) self._downstream.read(self._on_downstream_read) def _connect_upstream(self, request, route=None): if route is not None: # This does some type checking for routes passed up via filter self._router.set_next(route) upstream_target = self._router.get_next() if upstream_target is None: self._downstream.write(_UPSTREAM_UNAVAILABLE.to_bytes(), self._downstream.handle.resume_reading) return # Hold downstream reads self._hold_downstream = True # Update the request to proxy upstream and store it request.replace_header('host').values.append( '{}:{}'.format(upstream_target[0], upstream_target[1])) self._request = request try: self._upstream_tracker.connect(upstream_target) except Exception as ex: _LOG.exception(ex) def _on_upstream_live(self, upstream): self._upstream_handler = UpstreamHandler( self._downstream, upstream, self._us_filter_pl) if self._upstream_parser: self._upstream_parser.destroy() self._upstream_parser = ResponseParser(self._upstream_handler) # Set the read callback upstream.read(self._on_upstream_read) # Send the proxied request object upstream.write(self._request.to_bytes()) # Drop the ref to the proxied request head self._request = None # Set up our downstream handler self._downstream_handler.on_upstream_connect(upstream) def _on_downstream_close(self): self._upstream_tracker.destroy() self._downstream_parser.destroy() self._downstream_parser = None def _on_downstream_error(self, error): _LOG.error('Downstream error: {}'.format(error)) if not self._downstream.closed(): self._downstream.close() def _on_upstream_error(self, error): if not self._downstream.closed(): self._downstream.write(_BAD_GATEWAY_RESP.to_bytes()) def _on_upstream_close(self): if not self._downstream.closed(): self._downstream.close() if self._upstream_parser is not None: self._upstream_parser.destroy() self._upstream_parser = None def _on_downstream_read(self, data): try: self._downstream_parser.execute(data) except StreamClosedError: pass except Exception as ex: _LOG.exception(ex) def _on_upstream_read(self, data): try: self._upstream_parser.execute(data) except StreamClosedError: pass except Exception as ex: _LOG.exception(ex)
class ProxyConnection(object): """ A proxy connection manages the lifecycle of the sockets opened during a proxied client request against Pyrox. """ def __init__(self, us_filter_pl, ds_filter_pl, downstream, router): self._ds_filter_pl = ds_filter_pl self._us_filter_pl = us_filter_pl self._router = router self._upstream_parser = None self._upstream_tracker = ConnectionTracker( self._on_upstream_live, self._on_upstream_close, self._on_upstream_error) # Setup all of the wiring for downstream self._downstream = downstream self._downstream_handler = DownstreamHandler( self._downstream, self._ds_filter_pl, self._connect_upstream) self._downstream_parser = RequestParser(self._downstream_handler) self._downstream.on_close(self._on_downstream_close) self._downstream.read(self._on_downstream_read) def _connect_upstream(self, request, route=None): if route is not None: # This does some type checking for routes passed up via filter self._router.set_next(route) upstream_target = self._router.get_next() if upstream_target is None: self._downstream.write(_UPSTREAM_UNAVAILABLE.to_bytes(), self._downstream.handle.resume_reading) return # Hold downstream reads self._hold_downstream = True # Update the request to proxy upstream and store it request.replace_header('host').values.append( '{}:{}'.format(upstream_target[0], upstream_target[1])) self._request = request try: self._upstream_tracker.connect(upstream_target) except Exception as ex: _LOG.exception(ex) def _on_upstream_live(self, upstream): self._upstream_handler = UpstreamHandler( self._downstream, upstream, self._us_filter_pl, self._request) if self._upstream_parser: self._upstream_parser.destroy() self._upstream_parser = ResponseParser(self._upstream_handler) # Set the read callback upstream.read(self._on_upstream_read) # Send the proxied request object upstream.write(self._request.to_bytes()) # Drop the ref to the proxied request head self._request = None # Set up our downstream handler self._downstream_handler.on_upstream_connect(upstream) def _on_downstream_close(self): self._upstream_tracker.destroy() self._downstream_parser.destroy() self._downstream_parser = None def _on_downstream_error(self, error): _LOG.error('Downstream error: {}'.format(error)) if not self._downstream.closed(): self._downstream.close() def _on_upstream_error(self, error): _LOG.error('Upstream error: {}'.format(error)) if not self._downstream.closed(): self._downstream.write(_BAD_GATEWAY_RESP.to_bytes()) def _on_upstream_close(self): if not self._downstream.closed(): self._downstream.close() if self._upstream_parser is not None: self._upstream_parser.destroy() self._upstream_parser = None def _on_downstream_read(self, data): try: self._downstream_parser.execute(data) except StreamClosedError: pass except Exception as ex: _LOG.exception(ex) def _on_upstream_read(self, data): try: self._upstream_parser.execute(data) except StreamClosedError: pass except Exception as ex: _LOG.exception(ex)