Пример #1
0
class Stomp(object):
    """STOMP Client.

    :param hostname: Hostname of the STOMP server to connect to.
    :param port: The port to use. (default ``61613``)

    """
    ConnectionError = ConnectionError
    ConnectionTimeoutError = ConnectionTimeoutError
    NotConnectedError = NotConnectedError

    def __init__(self, hostname, port=61613):
        self.host = hostname
        self.port = port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._subscribed_to = {}
        self._subscribed = None
        self._callback = None
        self.connected = None
        self.frame = Frame()

    def connect(self, username=None, password=None, clientid=None):
        """Connect to STOMP server.

        :keyword username: Username for connection
        :keyword password: Password for connection
        :keyword clientid: Client identification for persistent connections
        """
        try:
            self.sock.connect((self.host, self.port))
            self.frame.connect(self.sock, username=username, password=password, clientid=clientid)
        except socket.timeout, exc:
            raise self.ConnectionTimeoutError(*exc.args)
        except socket.error, exc:
            raise self.ConnectionError(*exc.args)
Пример #2
0
    def should_send_frame_and_return_frame(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        headers = {'destination': '/queue/nose_test',
                   'persistent': 'true'}
        body = {'body': 'Testing'}
        my_frame._getline.return_value = \
                'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        my_frame.connect(self.sockobj.connect('localhost', 99999))
        this_frame = my_frame.build_frame({'command': 'SEND',
                                           'headers': headers,
                                           'body': body},
                                           want_receipt=True)
        my_frame._getline.return_value = \
                'RECEIPT\nreceipt-id:ID:nose-receipt123\n\n\x00\n'
        send_frame = my_frame.send_frame(this_frame.as_string())

        assert isinstance(my_frame, Frame)
Пример #3
0
    def should_send_frame_and_return_frame(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        headers = {'destination': '/queue/nose_test', 'persistent': 'true'}
        body = {'body': 'Testing'}
        my_frame._getline.return_value = \
                'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        my_frame.connect(self.sockobj.connect('localhost', 99999))
        this_frame = my_frame.build_frame(
            {
                'command': 'SEND',
                'headers': headers,
                'body': body
            },
            want_receipt=True)
        my_frame._getline.return_value = \
                'RECEIPT\nreceipt-id:ID:nose-receipt123\n\n\x00\n'
        send_frame = my_frame.send_frame(this_frame.as_string())

        assert isinstance(my_frame, Frame)
Пример #4
0
class WhenSendingFrames(DingusTestCase(Frame)):
    def setup(self):
        super(WhenSendingFrames, self).setup()
        self.frame = Frame()
        self.sockobj = frame.socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def should_send_frame_and_return_none(self):
        self.frame._getline = Dingus()
        self.frame._getline.return_value = \
                'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        self.frame.connect(self.sockobj.connect('localhost', 99999))
        this_frame = self.frame.build_frame({
            'command': 'CONNECT',
            'headers': {}
        })
        send_frame = self.frame.send_frame(this_frame.as_string())

        assert send_frame is None

    def should_send_frame_and_return_frame(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        headers = {'destination': '/queue/nose_test', 'persistent': 'true'}
        body = {'body': 'Testing'}
        my_frame._getline.return_value = \
                'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        my_frame.connect(self.sockobj.connect('localhost', 99999))
        this_frame = my_frame.build_frame(
            {
                'command': 'SEND',
                'headers': headers,
                'body': body
            },
            want_receipt=True)
        my_frame._getline.return_value = \
                'RECEIPT\nreceipt-id:ID:nose-receipt123\n\n\x00\n'
        send_frame = my_frame.send_frame(this_frame.as_string())

        assert isinstance(my_frame, Frame)
Пример #5
0
class Stomp(object):
    """STOMP Client.

    :param hostname: Hostname of the STOMP server to connect to.
    :param port: The port to use. (default ``61613``)

    """
    ConnectionError = ConnectionError
    ConnectionTimeoutError = ConnectionTimeoutError
    NotConnectedError = NotConnectedError

    def __init__(self, hostname, port=61613):
        self.host = hostname
        self.port = port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._subscribed_to = {}
        self._subscribed = None
        self._callback = None
        self.connected = None
        self.frame = Frame()

    def connect(self, username=None, password=None, clientid=None):
        """Connect to STOMP server.

        :keyword username: Username for connection
        :keyword password: Password for connection
        :keyword clientid: Client identification for persistent connections
        """
        try:
            self.sock.connect((self.host, self.port))
            self.frame.connect(self.sock,
                               username=username,
                               password=password,
                               clientid=clientid)
        except socket.timeout, exc:
            raise self.ConnectionTimeoutError(*exc.args)
        except socket.error, exc:
            raise self.ConnectionError(*exc.args)
Пример #6
0
class WhenSendingFrames(DingusTestCase(Frame)):

    def setup(self):
        super(WhenSendingFrames, self).setup()
        self.frame = Frame()
        self.sockobj = frame.socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def should_send_frame_and_return_none(self):
        self.frame._getline = Dingus()
        self.frame._getline.return_value = \
                'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        self.frame.connect(self.sockobj.connect('localhost', 99999))
        this_frame = self.frame.build_frame({'command': 'CONNECT',
                                             'headers': {}})
        send_frame = self.frame.send_frame(this_frame.as_string())

        assert send_frame is None

    def should_send_frame_and_return_frame(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        headers = {'destination': '/queue/nose_test',
                   'persistent': 'true'}
        body = {'body': 'Testing'}
        my_frame._getline.return_value = \
                'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        my_frame.connect(self.sockobj.connect('localhost', 99999))
        this_frame = my_frame.build_frame({'command': 'SEND',
                                           'headers': headers,
                                           'body': body},
                                           want_receipt=True)
        my_frame._getline.return_value = \
                'RECEIPT\nreceipt-id:ID:nose-receipt123\n\n\x00\n'
        send_frame = my_frame.send_frame(this_frame.as_string())

        assert isinstance(my_frame, Frame)
Пример #7
0
class WhenSettingUp(DingusTestCase(Frame)):

    def setup(self):
        super(WhenSettingUp, self).setup()
        self.frame = Frame()
        self.sockobj = frame.socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def should_set_name(self):
        assert frame.socket.calls('gethostbyname', frame.socket.gethostname())

    def should_connect(self):
        self.frame._getline = Dingus()
        self.frame._getline.return_value = \
            'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        self.frame.connect(self.sockobj.connect('localhost', 99999))
        sendall = self.frame.sock.calls('sendall', DontCare).one().args[0]

        assert self.frame.session is not None
        assert 'CONNECT' in sendall

    def should_connect_with_authentication(self):
        self.frame._getline = Dingus()
        self.frame._getline.return_value = \
            'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        self.frame.connect(self.sockobj.connect('localhost', 99999),
                                                username="******",
                                                password="******")
        sendall = self.frame.sock.calls('sendall', DontCare).one().args[0]

        assert self.frame.session is not None
        assert 'login:test' in sendall

    def should_set_client_id(self):
        self.frame._getline = Dingus()
        self.frame._getline.return_value = \
            'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        self.frame.connect(self.sockobj.connect('localhost', 99999),
                                                clientid="test")
        sendall = self.frame.sock.calls('sendall', DontCare).one().args[0]

        assert self.frame.session is not None
        assert 'client-id:test' in sendall
Пример #8
0
class WhenSettingUp(DingusTestCase(Frame)):
    def setup(self):
        super(WhenSettingUp, self).setup()
        self.frame = Frame()
        self.sockobj = frame.socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def should_set_name(self):
        assert frame.socket.calls('gethostbyname', frame.socket.gethostname())

    def should_connect(self):
        self.frame._getline = Dingus()
        self.frame._getline.return_value = \
            'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        self.frame.connect(self.sockobj.connect('localhost', 99999))
        sendall = self.frame.sock.calls('sendall', DontCare).one().args[0]

        assert self.frame.session is not None
        assert 'CONNECT' in sendall

    def should_connect_with_authentication(self):
        self.frame._getline = Dingus()
        self.frame._getline.return_value = \
            'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        self.frame.connect(self.sockobj.connect('localhost', 99999),
                           username="******",
                           password="******")
        sendall = self.frame.sock.calls('sendall', DontCare).one().args[0]

        assert self.frame.session is not None
        assert 'login:test' in sendall

    def should_set_client_id(self):
        self.frame._getline = Dingus()
        self.frame._getline.return_value = \
            'CONNECTED\nsession:ID:nose-session123\n\n\x00\n'
        self.frame.connect(self.sockobj.connect('localhost', 99999),
                           clientid="test")
        sendall = self.frame.sock.calls('sendall', DontCare).one().args[0]

        assert self.frame.session is not None
        assert 'client-id:test' in sendall
Пример #9
0
class WhenParsingFrames(DingusTestCase(Frame,
        exclude=["UnknownBrokerResponseError", "BrokerErrorResponse"])):

    def setup(self):
        super(WhenParsingFrames, self).setup()
        self.frame = Frame()
        self.sockobj = frame.socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def should_parse_headers(self):
        header = 'destination:/queue/nose_test'
        parsed = self.frame.parse_headers(header)

        assert isinstance(parsed, type({}))

    def should_parse_command(self):
        command_str = 'CONNECT\nsession:ID:nose-session123'
        command = self.frame.parse_command(command_str)

        assert isinstance(command, type(''))

    def should_set_bytes_message(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        body = 'Test 1'
        my_frame._getline.return_value = (
                'MESSAGE\nsession:ID:nose-session123'
                '\ncontent-length:%d\n\n%s\x00\n' % (len(body), body))
        this_frame = my_frame.parse_frame()

        assert 'bytes_message' in this_frame.headers

    def should_get_line(self):
        command = 'CONNECTED'
        headers = {'session': 'ID:nose-session123'}
        body = '\x00'
        my_frame = Frame()
        self.frame.parse_frame = Dingus()
        this_frame = my_frame.build_frame({'command': command,
                                           'headers': headers,
                                           'body': body})
        self.frame.parse_frame.return_value = this_frame
        self.frame.connect(self.sockobj.connect(('localhost', 99999)))
        header = "session:%(session)s\n" % headers
        ret = '\n'.join([command, header, body])
        self.frame.sock.recv.return_value = ret
        self.frame._getline()

        assert self.frame.sock.calls('recv', 1)

    def should_not_get_line(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        my_frame._getline.return_value = None
        ret_value = my_frame.parse_frame()
        assert ret_value is None

    def should_fail_to_get_headers(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        my_frame._getline.return_value = \
                'RECEIPTreceipt-id:ID:nose-receipt123'

        nose_tools.assert_raises(UnknownBrokerResponseError,
            my_frame.parse_frame)

    def should_get_error_from_broker(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        command = 'ERROR'
        header = 'message:Illegal command'
        body = 'Error Message'
        my_frame._getline.return_value = \
            '%s\n%s\ncontent-length:%d\n\n%s\n\x00' % (command,
                                                       header,
                                                       len(body),
                                                       body)

        nose_tools.assert_raises(BrokerErrorResponse, my_frame.parse_frame)

    def should_return_frame_repr(self):
        my_frame = Frame()
        assert isinstance(repr(my_frame), type(''))
Пример #10
0
class WhenParsingFrames(
        DingusTestCase(
            Frame,
            exclude=["UnknownBrokerResponseError", "BrokerErrorResponse"])):
    def setup(self):
        super(WhenParsingFrames, self).setup()
        self.frame = Frame()
        self.sockobj = frame.socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def should_parse_headers(self):
        header = 'destination:/queue/nose_test'
        parsed = self.frame.parse_headers(header)

        assert isinstance(parsed, type({}))

    def should_parse_command(self):
        command_str = 'CONNECT\nsession:ID:nose-session123'
        command = self.frame.parse_command(command_str)

        assert isinstance(command, type(''))

    def should_set_bytes_message(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        body = 'Test 1'
        my_frame._getline.return_value = ('MESSAGE\nsession:ID:nose-session123'
                                          '\ncontent-length:%d\n\n%s\x00\n' %
                                          (len(body), body))
        this_frame = my_frame.parse_frame()

        assert 'bytes_message' in this_frame.headers

    def should_get_line(self):
        command = 'CONNECTED'
        headers = {'session': 'ID:nose-session123'}
        body = '\x00'
        my_frame = Frame()
        self.frame.parse_frame = Dingus()
        this_frame = my_frame.build_frame({
            'command': command,
            'headers': headers,
            'body': body
        })
        self.frame.parse_frame.return_value = this_frame
        self.frame.connect(self.sockobj.connect(('localhost', 99999)))
        header = "session:%(session)s\n" % headers
        ret = '\n'.join([command, header, body])
        self.frame.sock.recv.return_value = ret
        self.frame._getline()

        assert self.frame.sock.calls('recv', 1)

    def should_not_get_line(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        my_frame._getline.return_value = None
        ret_value = my_frame.parse_frame()
        assert ret_value is None

    def should_fail_to_get_headers(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        my_frame._getline.return_value = \
                'RECEIPTreceipt-id:ID:nose-receipt123'

        nose_tools.assert_raises(UnknownBrokerResponseError,
                                 my_frame.parse_frame)

    def should_get_error_from_broker(self):
        my_frame = Frame()
        my_frame._getline = Dingus()
        command = 'ERROR'
        header = 'message:Illegal command'
        body = 'Error Message'
        my_frame._getline.return_value = \
            '%s\n%s\ncontent-length:%d\n\n%s\n\x00' % (command,
                                                       header,
                                                       len(body),
                                                       body)

        nose_tools.assert_raises(BrokerErrorResponse, my_frame.parse_frame)

    def should_return_frame_repr(self):
        my_frame = Frame()
        assert isinstance(repr(my_frame), type(''))
Пример #11
0
class Stomp(object):
    """STOMP Client.

    :param hostname: Hostname of the STOMP server to connect to.
    :param port: The port to use. (default ``61613``)

    """
    ConnectionError = ConnectionError
    ConnectionTimeoutError = ConnectionTimeoutError
    NotConnectedError = NotConnectedError

    def __init__(self, hostname, port=61613):
        self.host = hostname
        self.port = port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._subscribed_to = {}
        self._subscribed = None
        self._callback = None
        self.connected = None
        self.frame = Frame()

    def connect(self, username=None, password=None, clientid=None):
        """Connect to STOMP server.

        :keyword username: Username for connection
        :keyword password: Password for connection
        :keyword clientid: Client identification for persistent connections
        """
        try:
            self.sock.connect((self.host, self.port))
            self.frame.connect(self.sock, username=username, password=password, clientid=clientid)
        except socket.timeout as exc:
            raise self.ConnectionTimeoutError(*exc.args)
        except socket.error as exc:
            raise self.ConnectionError(*exc.args)
        self.connected = True

    def disconnect(self, conf=None):
        """Disconnect from the server."""
        try:
            for destination in self._subscribed_to.keys():
                self.unsubscribe({"destination": destination})
            self._send_command("DISCONNECT", conf)
        except self.NotConnectedError:
            pass
        try:
            self.sock.shutdown(0)
            self.sock.close()
        except socket.error as exc:
            # likely wasn't connected
            pass
        self.connected = False

    def send(self, conf=None, receipt=True):
        """Send message to STOMP server

        You'll need to pass the body and any other headers your
        STOMP server likes.

        destination is **required**

        In the case of ActiveMQ with persistence, you could do this:

            >>> for i in xrange(1,1000):
            ...     stomp.send({'destination': '/queue/foo',
            ...                 'body': 'Testing',
            ...                 'persistent': 'true'})

        """
        headers = dict(conf)
        body = headers.pop("body", "")
        return self._send_command("SEND", headers, extra={"body": body},
                                  want_receipt=receipt)

    def _build_frame(self, *args, **kwargs):
        self._connected_or_raise()
        return self.frame.build_frame(*args, **kwargs)

    def subscribe(self, conf=None):
        """Subscribe to a given destination

        You will need to pass any headers your STOMP server likes.

        destination is *required*

        In the case of ActiveMQ, you could do this:

            >>> stomp.subscribe({'destination':'/queue/foo',
            ...                  'ack':'client'})
        """
        destination = conf["destination"]
        self._send_command("SUBSCRIBE", conf)
        self._subscribed_to[destination] = True

    def begin(self, conf=None):
        """Begin transaction.

        You will need to pass any headers your STOMP server likes.

        destination is *required*

        In the case of ActiveMQ, you could do this:

            >>> stomp.begin({'transaction':'<randomish_hash_like_thing>'})
        """
        self._send_command("BEGIN", conf)

    def commit(self, conf=None):
        """Commit transaction.

        You will need to pass any headers your STOMP server likes.

        destination is **required**

        In the case of ActiveMQ, you could do this:

            >>> stomp.commit({'transaction':'<randomish_hash_like_thing>'})

        """
        self._send_command("COMMIT", conf)

    def abort(self, conf=None):
        """Abort transaction.

        In the case of ActiveMQ, you could do this:

            >>> stomp.abort({'transaction':'<randomish_hash_like_thing>'})

        """
        self._send_command("ABORT", conf)

    def unsubscribe(self, conf=None):
        """Unsubscribe from a given destination

        You will need to pass any headers your STOMP server likes.

        destination is *required*

        >>> stomp.unsubscribe({'destination':'/queue/foo'})
        """
        destination = conf["destination"]
        self._send_command("UNSUBSCRIBE", conf)
        self._subscribed_to.pop(destination, None)

    def ack(self, frame):
        """Acknowledge receipt of a message

        :param: A :class:`stompy.frame.Frame` instance.

        Example

            >>> while True:
            ...     frame = stomp.receive_frame()
            ...     stomp.ack(frame)

        """
        message_id = frame.headers.get('message-id')
        self._send_command("ACK", {"message-id": message_id})

    def receive_frame(self, callback=None, nonblocking=False):
        """Get a frame from the STOMP server

        :keyword nonblocking: By default this function waits forever
            until there is a message to be received, however, in non-blocking
            mode it returns ``None`` if there is currently no message
            available.

        :keyword callback: Optional function to execute when message recieved.

        Note that you must be subscribed to one or more destinations.
        Use :meth:`subscribe` to subscribe to a topic/queue.

        Example: Blocking

            >>> while True:
            ...     frame = stomp.receive_frame()
            ...     print(frame.headers['message-id'])
            ...     stomp.ack(frame)

        Example: Non-blocking

            >>> frame = stomp.recieve_frame(nonblocking=True)
            >>> if frame:
            ...     process_message(frame)
            ... else:
            ...     # no messages yet.

        """
        self._connected_or_raise()
        self._callback = callback
        message = None
        if self._callback:
            message = self.frame.get_message(nb=nonblocking)
            self._callback(message)
            return
        else:
            return self.frame.get_message(nb=nonblocking)

    def poll(self, callback=None):
        """Alias to :meth:`receive_frame` with ``nonblocking=True``."""
        return self.receive_frame(nonblocking=True, callback=callback)

    def send_frame(self, frame):
        """Send a custom frame to the STOMP server

        :param frame: A :class:`stompy.frame.Frame` instance.

        Example

            >>> from stompy import Frame
            >>> frame = Frame().build_frame({
            ...    "command": "DISCONNECT",
            ...    "headers": {},
            ... })
            >>> stomp.send_frame(frame)

        """
        self._connected_or_raise()
        frame = self.frame.send_frame(frame.as_string())
        return frame

    def _send_command(self, command, conf=None, extra=None, **kwargs):
        conf = conf or {}
        extra = extra or {}
        frame_conf = {"command": command, "headers": conf}
        frame_conf.update(extra)
        frame = self._build_frame(frame_conf, **kwargs)
        reply = self.send_frame(frame)
        if kwargs.get("want_receipt", False):
            return reply
        return frame

    def _connected_or_raise(self):
        if not self.connected:
            raise self.NotConnectedError("Not connected to STOMP broker.")

    @property
    def subscribed(self):
        """**DEPRECATED** The queue or topic currently subscribed to."""
        as_list = self._subscribed_to.keys()
        if not as_list:
            return
        return as_list[0]