Пример #1
0
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)
Пример #2
0
    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)
Пример #3
0
 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)
Пример #4
0
    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)
Пример #5
0
    def test_reading_chunked_request(self):
        tracker = TrackingDelegate(ValidatingDelegate(self))
        parser = ResponseParser(tracker)

        chunk_message(CHUNKED_RESPONSE, parser)

        tracker.validate_hits({
            RESPONSE_HTTP_VERSION_SLOT: 1,
            RESPONSE_CODE_SLOT: 1,
            HEADER_FIELD_SLOT: 1,
            HEADER_VALUE_SLOT: 1,
            BODY_SLOT: 4,
            BODY_COMPLETE_SLOT: 1}, self)
Пример #6
0
    def test_reading_request_with_content_length(self):
        tracker = TrackingDelegate(ValidatingDelegate(self))
        parser = ResponseParser(tracker)

        chunk_message(NORMAL_RESPONSE, parser)

        tracker.validate_hits({
            RESPONSE_HTTP_VERSION_SLOT: 1,
            RESPONSE_CODE_SLOT: 1,
            HEADER_FIELD_SLOT: 1,
            HEADER_VALUE_SLOT: 1,
            BODY_SLOT: 3,
            BODY_COMPLETE_SLOT: 1}, self)
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
0
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)
Пример #10
0
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)
Пример #11
0
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)
Пример #12
0
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)