Coder Social home page Coder Social logo

jasonrbriggs / stomp.py Goto Github PK

View Code? Open in Web Editor NEW
490.0 37.0 164.0 3.95 MB

“stomp.py” is a Python client library for accessing messaging servers (such as ActiveMQ or RabbitMQ) using the STOMP protocol (versions 1.0, 1.1 and 1.2). It can also be run as a standalone, command-line client for testing.

License: Apache License 2.0

Makefile 2.11% Python 96.82% Dockerfile 1.03% Shell 0.03%

stomp.py's Introduction

stomp.py

PyPI version

"stomp.py" is a Python client library for accessing messaging servers (such as ActiveMQ, Artemis or RabbitMQ) using the STOMP protocol (STOMP v1.0, STOMP v1.1 and STOMP v1.2). It can also be run as a standalone, command-line client for testing. NOTE: Stomp.py has officially ended support for Python2.x. See python3statement.org for more information.

You can connect to a message broker running on the local machine, and send a message using the following example.

import stomp

conn = stomp.Connection()
conn.connect('admin', 'password', wait=True)
conn.send(body=' '.join(sys.argv[1:]), destination='/queue/test')
conn.disconnect()

The current version of stomp.py supports:

  • Python 3.x (Python2 support ended as of Jan 2020)
  • STOMP version 1.0, 1.1 and 1.2

There is also legacy 3.1.7 version using the old 3-series code (see 3.1.7 on PyPi and 3.1.7 on GitHub). This is no longer supported, but (at least as of 2018) there were still a couple of reports of this version still being used in the wild.

Note: stomp.py now follows semantic versioning:

  • MAJOR version for incompatible API changes,
  • MINOR version for functionality added in a backwards compatible manner, and
  • PATCH version for backwards compatible bug fixes.

stomp.py has been perfunctorily tested on:

For testing locally, you'll need to install docker (or podman). Once installed:

  1. Install dependencies:
    poetry install
  2. Create the docker (or podman) image:
    make docker-image (or make podman-image)
  3. Run the container:
    make run-docker (or make run-podman)
  4. Run stomp.py unit tests:
    make test
  5. Cleanup the container afterwards if you don't need it any more:
    make remove-docker (or make remove-podman)
If you want to connect to the test services locally (other than from the included tests), you'll want to add test domain names to your hosts file like so:
172.17.0.2 my.example.com
172.17.0.2 my.example.org
172.17.0.2 my.example.net

If you're using podman and you want to access services via their private IP addresses, you'll want to run your commands with:

podman unshare --rootless-netns <command>

so that <command> has access to the private container network. Service ports are also exposed to the host and can be accessed directly.

stomp.py's People

Contributors

aarondmarasco avatar anthchirp avatar aragaer avatar bradleynull avatar cg2v avatar christopherjameshoward avatar cygnusb avatar geckon avatar giz avatar grundleborg avatar hwiese1980 avatar jasonrbriggs avatar jvantuyl avatar mfmarche avatar mikael-vandmo-wcar avatar mikebonnet avatar nigelsim avatar ozeebee avatar percentcer avatar permanentstudy avatar rafaduran avatar raghavtan avatar rnixx avatar scop avatar snyk-bot avatar spitfire1900 avatar tirkarthi avatar vlcinsky avatar willianantunes avatar wordlesstruth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stomp.py's Issues

error happens when receive 'bytes' type data

I am using stomp.py to communicate with rabbitMQ.
When I serialize my data with JSON before send it, stomp.py works well.
But when I want to send bytes type data, there is something wrong.

SEND code:

# bytes in range(-128,128)
data = b'\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f'
...
c.send('/topic/test',data)

send() works fine. Through the RabbitMQ web management plugin, I can see the data in the queue which binds to topic 'test' . When I use nc tool and subcribe the topic manually, I can get the data too.
But with stomp.py, an exception happens.

RECEIVE code is as below:

class ProcessListener(stomp.ConnectionListener):
    def on_error(self,headers,message):
        print('received an error "%s"' % message)
    def on_message(self,headers,message):
        print(message)
...
c.set_listener('',ProcessListener())
...
c.subscribe(topic,id=1,headers=Headers)

Exception infomation is as below:

Exception in thread StompReceiverThread-1:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/stomp/transport.py", line 310, in __receiver_loop
    f.body = decode(f.body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/stomp/backward3.py", line 25, in decode
    return byte_data.decode()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte

It seems it's about codec but I know little about it. Could you please help me to figure it out?

race condition during shutdown

While executing the example provided in the front page (https://github.com/kwoli/stomp.py/wiki/Simple-Example), sometimes the process ends-up throwing following exception:

Exception in thread Thread-1 (most likely raised during interpreter shutdown)

Looking at the code, it seems like a race condition during shutdown. The last thing the main thread does is stop the transport, that is, wait for the receiver thread to exit:

264 def stop(self):
265 """
266 Stop the connection. Performs a clean shutdown by waiting for the
267 receiver thread to exit.
268 """
269 self.__receiver_thread_exit_condition.acquire()
270 while not self.__receiver_thread_exited:
271 self.__receiver_thread_exit_condition.wait()
272 self.__receiver_thread_exit_condition.release()

Problem is the receiver thread after setting the exit condition, still tries to log some info:

509 finally:
510 self.__receiver_thread_exit_condition.acquire()
511 self.__receiver_thread_exited = True
512 self.__receiver_thread_exit_condition.notifyAll()
513 self.__receiver_thread_exit_condition.release()
514 log.info("Receiver loop ended")

Thus, if the main thread is fast enough, it finish before the receiver thread (which is set as daemon thread), and the intepreter raise an exception during shutdown.

Problem with install stomp.py version 3.1.5 in ubuntu 16.04

I need install the stomp.py (version 3.1.5).
I'm using ubuntu, version 16.04.

sudo pip install stomp.py==3.1.5
The directory '/home/tacnoman/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/home/tacnoman/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Collecting stomp.py==3.1.5
Downloading stomp.py-3.1.5.tar.gz (94kB)
100% |████████████████████████████████| 102kB 989kB/s
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "/tmp/pip-build-FGqOzb/stomp.py/setup.py", line 12, in
import stomp
File "stomp/init.py", line 16, in
import connect, listener, exception
File "stomp/connect.py", line 19, in
DEFAULT_SSL_VERSION = ssl.PROTOCOL_SSLv3
AttributeError: 'module' object has no attribute 'PROTOCOL_SSLv3'

----------------------------------------

Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-FGqOzb/stomp.py/

How can I do to solve this?
Thanks for this.

4.x speaks STOMP 1.2 with 1.1 selected

Hi,

Installed stomp.py via pip and now all of my previously working programs are broken... I've adapted one of them to the new API, but I can't even do an ACK (ActiveMQ 5.9), I get the following error:
"ACK received without a message-id to acknowledge!"
Indeed, this version sends the message-id as id, which is not valid in STOMP 1.[01].

Overriding the default version (1.1) to 1.2, I get the following:
"Unexpected ACK received for message-id [null]"
while stomp.py sent the following ACK:
INFO:stomp.py:Sending frame ['ACK', '\n', 'id:ID\cmq00d-57544-1385032044164-5\c486\c-1\c1\c3\n', '\n', '\x00']

Also, <1.2 needs the subscription header, while there is no way to specify that with the current version if I'm right (passing a headers structure to ack and other calls is not possible).

Could you please test and fix these issues?

Thanks,

ubuntu: ImportError: No module named adapter.multicast

this is when i try to run the command line interface. if i all MulticastConnection entries, i works fine

stomp -H x.x.x.x -P x -U x-W x

Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
"main", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/usr/local/lib/python2.7/dist-packages/stomp/main.py", line 14, in
from adapter.multicast import MulticastConnection
ImportError: No module named adapter.multicast

Bug in setting keepalive settings on socket

In transport.py in method __enable_keepalive, If keepalive settings are passed they are not applied to the actual socket.

    ka = self.__keepalive

    if not ka: 
        return

    if ka: 
        ka_sig = 'auto'
        ka_args = ()
    else:
        try:
            ka_sig = ka[0]
            ka_args = ka[1:]
        except Exception:
            log.error("keepalive: bad specification %r", ka) 
            return                            

The code in else block never gets executed as ka will always be defined when it reaches the if condition.
It used to work in stomp.py v3.1.1 because of this code:

    ka = self.__keepalive

    if not ka: 
        return

    # The if condition fails as ka is a tuple and we are able to override socket settings
    if ka == True:
        ka_sig = 'auto'
        ka_args = ()
    else:
        try:
            ka_sig = ka[0]
            ka_args = ka[1:]
        except Exception:
            log.error('keepalive: bad specification %r' % (ka,))
            return

Please take a look and patch it as early as possible?

Logging suggestion

Below code in transport.py module gives out warning for every failed connection attempt in the given host:port list.

except socket.error:
      self.socket = None
      connect_count += 1
      log.warning("Could not connect to host %s, port %s", host_and_port[0], host_and_port[1], exc_info=1)

My suggestion is to make the log statement in the above code to be logged at INFO level and give out a warning only if we fail to connect to any of the host:port pairs provided in the list.

The reason I am suggesting this is that default log level in python WARN and if the client is able to connect to one of the host:port pair in the list, It should be considered a success without any abnormalities and more often than not the warning produced by this code has caused confusions to the people not much familiar with the API.
Now, I know there are ways to suppress this log statement in the client code but they are cumbersome and making the log statement at INFO level seems like reasonable logging improvement and we can anyway log a WARNING or ERROR if we fail to connect any of host:port pair in this list.

Cheers,
Abhishek

receiving all event

Is there any way to receive all the event sending on all destination. I am using activeMQ as message broker which support wildcard for destination. For example, I am set listener l1 and l2 for destination 'a' and '*', when someone sending event on destination 'a' both listener l1 and l2 should be called. In my case either l1 or l2 is called. Any Idea?

Gracefully exiting a listener with manual ACK

My listener daemon runs an "endless" loop like this:

            service = self.make_service()  # returns a Connection with registered listener
            self.print_banner(service)
            try:
                while True:
                    time.sleep(1000)
                    if not service.is_connected():
                        break
            except KeyboardInterrupt:
                service.stop()

The point is that a) on disconnect the main daemon thread terminates (not only the listener thread) and also a CTRL-C on the daemon will gracefully(!) terminate the listener.
Now the problem appears to be that stop() first disconnects the connection and then waits for the thread to finish. But the last thing that the listener does (after doing it's long running task) is sending the ACK. By the time that the listener reaches that statement, the connection is gone (and cannot even be reconnected).
In effect the handler does all it's work but can not ACK the message, which means that it will handle it again on restart.

Am I doing something wrong?

header escaping

stomp 1.1 and 1.2 require that colon (:), backslash, and newline be backslash escaped in header values (stomp 1.2 also adds carriage return). stomp.py doesn't implement this, which leads to strange looking error headers from activemq:

User XXX is not authorized to read from\c queue\c//yyy

it may also prevent some servers from accepting passwords containing colons (thankfully, activemq is lenient about this)

delete/purge destination/queue

Hi,

I need a precondition before start application to clear all prev messages from Activemq

I managed to do this via hack

def purge(self):
    cmd = [
        "/usr/bin/activemq-admin",
        "purge",
        "--jmxurl", "service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi" % (self._activemq_host, self._activemq_port_jmx),
        self._activemq_destination
    ]
    self._log.info("cmd = %s", cmd)

    try:
        call(cmd)
    except Exception, e:
        self._log.exception(e)
    else:
        self._log.info("successful purging")

I wish to have a method like

_stomp.purge(destination=self._activemq_destination)

Is it implemented already or how to implement this ?

Heartbeat listener does not exit when connection is closed

Hi,

when closing a StompConnection11 via the disconnect() method, the heartbeat listener keeps on running and periodically calls on_heartbeat_timeout().

I was wondering if the expected behavior should be the heartbeat listener closing as well when the connections gets terminated via disconnect().

Adding this to the heartbeat listener class solves this:

def on_disconnected(self):
    self.running = False

Am I missing something? I also noticed that the attribute self.running is currently never set to False by anyone...

Best regards,
Patrick

heartbeat_thread of HeartbeatListener, need to handle network error

Code:

try:
self.transport.transmit(utils.Frame(None, {}, None))
except exception.NotConnectedException:

logger.Log.instance().debug("Lost connection, unable to send heartbeat")

need to fix as:


try:
self.transport.transmit(utils.Frame(None, {}, None))
except exception.NotConnectedException:
logger.Log.instance().debug("Lost connection, unable to send heartbeat")
excep Exception:

logger.Log.instance().debug("Error sending heartbeat frame")

Error handling?

How is error handling supposed to be done with stomp.py? I am having trouble authenticating to an activemq server, and it's not clear how I am supposed to detect it and recover.

conn = stomp.Connection([(ipaddress, 61612)], use_ssl=True, timeout=30)
listener = MyListener()
conn.set_listener('', listener)
conn.start()
conn.connect(wait=True, username=user, passcode=password)
conn.subscribe(destination='/temp-queue/ActiveMQ.Queues', ack='auto', transformation="jms-map-json", id="zenoss")

if I connect with wait=True, the application hangs forever (the listener's on_error does fire, but it seems that callbacks are run in threads, so there's no point throwing an exception from it)
if I use wait=False, then I get a strange python error (TypeError: send() got multiple values for keyword argument 'destination')

(windows only?) message sent right before interpreter exit is never received

Hi,

With an ActiveMQ broker running on a machine called broker (not sure if it matters what kind of broker is running) and the following listener (test_listener.py) running:

import stomp
import time
stompClient = stomp.Connection([("broker", 61613)])
class MyListener(stomp.ConnectionListener):
   def on_error(self, headers, message):
       print('received an error "%s"' % message)
   def on_message(self, headers, message):
       print('received a message "%s"' % message)
stompClient.set_listener('', MyListener())
stompClient.start()
stompClient.connect()
stompClient.subscribe(destination='/topic/test_autoexit', id=1, ack='auto')

while True:
    time.sleep(0.2)

When the following script (test_sender.py), is run on Windows (server 2008 R2 Enterprise SP1 with ActiveState python 2.7.1) the message it sends is never received by the listener. It works fine on linux (Ubuntu 14.04.3 LTS, python 2.7.6). Both machines are running stomp.py 4.1.8.

import stomp
import time

stompClient = stomp.Connection([("broker", 61613)])
stompClient.start()
stompClient.connect()

stompClient.send(body="foo", destination="/topic/test_autoexit")
#print("about to sleep")
#time.sleep(1)

If I uncomment the last two lines (thereby sleeping for one second after sending) and run it again, the message is received by the listener. The results are consistent.
So it has something to do (as far as I can tell) with exiting the interpreter right after calling send().
Sleeping for 0.1 seconds seems to be enough to ensure the message is sent, but sleeping for 0.01 seconds is not long enough.

Thanks.

Providing connect headers

Hey,

Why doesn't connect support custom headers?

I needed to provide the client-id header when connecting, I modified the connect function in https://github.com/jasonrbriggs/stomp.py/blob/master/stomp/protocol.py#L154 so now it looks like

def connect(self, username=None, passcode=None, wait=False, connectHeaders={}):
        cmd = CMD_CONNECT
        headers = {
            HDR_ACCEPT_VERSION : self.version
        }

        headers.update(connectHeaders)

        if self.transport.vhost:
            headers[HDR_HOST] = self.transport.vhost

        if username is not None:
            headers[HDR_LOGIN] = username

        if passcode is not None:
            headers[HDR_PASSCODE] = passcode

        self.__send_frame(cmd, headers)

        if wait:
            self.transport.wait_for_connection()
            if self.connection_error:
                raise ConnectFailedException()

And it all works as expected

Now, am I being stupid, is there something I missed as to why this wasn't implemented in the first place? I can add it to the other protocol versions and send a PR but I didn't want to do that if there was a reason it wasn't there.

Thanks,
-Sam

Can't pip install

$ python --version
Python 2.7.8
$ pip --version
pip 1.5.6 from /home/acorcoles/.virtualenvs/scratch/local/lib/python2.7/site-packages (python 2.7)
$ pip install -i https://pypi.python.org/simple stomp.py
Downloading/unpacking stomp.py
Using download cache from /home/acorcoles/.cache/pip/https%3A%2F%2Fpypi.python.org%2Fpackages%2Fsource%2Fs%2Fstomp.py%2Fstomp.py-4.0.15.tar.gz
Running setup.py (path:/tmp/pip-build-pEcKl1/stomp.py/setup.py) egg_info for package stomp.py
Traceback (most recent call last):
File "", line 17, in
File "/tmp/pip-build-pEcKl1/stomp.py/setup.py", line 12, in
import stomp
File "stomp/init.py", line 12, in
import stomp.connect as connect, stomp.listener as listener
File "stomp/connect.py", line 1, in
from stomp.transport import *
File "stomp/transport.py", line 25, in
DEFAULT_SSL_VERSION = ssl.PROTOCOL_SSLv3
AttributeError: 'module' object has no attribute 'PROTOCOL_SSLv3'
Complete output from command python setup.py egg_info:
Traceback (most recent call last):

File "", line 17, in

File "/tmp/pip-build-pEcKl1/stomp.py/setup.py", line 12, in

import stomp

File "stomp/init.py", line 12, in

import stomp.connect as connect, stomp.listener as listener

File "stomp/connect.py", line 1, in

from stomp.transport import *

File "stomp/transport.py", line 25, in

DEFAULT_SSL_VERSION = ssl.PROTOCOL_SSLv3

AttributeError: 'module' object has no attribute 'PROTOCOL_SSLv3'


Cleaning up...
Command python setup.py egg_info failed with error code 1 in /tmp/pip-build-pEcKl1/stomp.py
Storing debug log for failure in /home/acorcoles/.pip/pip.log

Question about reconnection

Dear all,
Could you be so kind help me to understand library behavior on the event of unexpected disconnection ? Will library try to connect again (and also resubscribe if needed), when the application lost the connection? How many reconnection attempts will happen? Can it be configured?

With regards,
RedDec

Stomp messes with sys.path and breaks stuff

I have a package utils in my project, probably not a very unique name I'm sure.

If I import stomp and then later try and import any code from my utils package, I get a mystical ImportError: No module named time.

After considerable effort I finally backtracked this error to stomp.

Stomp breaks my code because it modifies sys.path (which is bad enough as it is, for a library), by prepending (even worse) it's own path to it. This causes my previously ok code to break.

This works:

from utils.time import my_util_func

This does not:

import stomp
from utils.time import my_util_func

After importing stomp the utils actually resolves to utils.py inside stomp. I assume this same error will occur if anyone will try and use the names: adapter, backward2, backward3, backward, colors, connect, constants, exception, listener, protocol, or transport.

Most of those names don't seem that unique.

Worse yet, since the path change is done globally, it can break any seemingly unrelated code that is just executed after the import.

The issue is caused by these lines:
https://github.com/jasonrbriggs/stomp.py/blob/master/stomp/__init__.py#L12-L14

I can fix this myself by moving all of my code under another package, "myproject", and then use from myproject.utils.time import ..., but I wouldn't have to worry about this if stomp wasn't changing the path.

Suggestion - Support MapMessage format in on_message

I have situation where I'm subscribed to a topic that has messages both in 'text' and 'map' message format. For the text messages, I am able to retrieve them fine in on_message - the map messages are triggered in on_message but the 'message' parameter is zero length.

I don't know how hard this would be but it seemed at least consistent that for on_message to pass in a dictionary type (like 'headers') when the received message was in mapmessage format. The consumer can then use standard python type checking to distinguish between receipt of a text or map message.

I have seen examples where I could request activemq to transform the map messages (to json or xml) as part of the subscription process but that requires the activemq server to have optional jar files (that may not be installed) and does not support the case where both text and map messages are present on the topic (I believe).

Random out-of-range exceptions

I am getting the following exception when running my stomp.py based client for a while. There are no other warning signs. I am trying to consume the UK's Network Rail datafeeds which use ActiveMQ as the backend.

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)
  File "/home/filip/RailDelay/server/lib/python3.4/site-packages/stomp/transport.py", line 299, in __receiver_loop
    f = utils.parse_frame(frame)
  File "/home/filip/RailDelay/server/lib/python3.4/site-packages/stomp/utils.py", line 131, in parse_frame
    f.cmd = preamble_lines[first_line]
IndexError: list index out of range

I am using the latest version of the package as published to pypi.

on_before_message

Decided to remove this message:
DEBUG:stomp.py:listener <main.stompworkerListener object at 0x7f42cba13650> has no method on_before_message

so I implemented a simple logging function and it exposes this:

    INFO:stomp.py:Receiver loop ended

Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(_self.__args, *_self.__kwargs)
File "/usr/local/lib/python2.7/dist-packages/stomp/transport.py", line 312, in __receiver_loop
self.process_frame(f, frame)
File "/usr/local/lib/python2.7/dist-packages/stomp/transport.py", line 166, in process_frame
(f.headers, f.body) = self.notify('before_message', f.headers, f.body)
TypeError: 'NoneType' object is not iterable

'sys' is not defined in listener.py

Using latest library version, on line 231 there is a call to sys.exc_info(), but sys has not been imported.

Traceback (most recent call last):                                             
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner       
    self.run()                                                                 
  File "/usr/lib/python2.7/threading.py", line 763, in run                     
    self.__target(*self.__args, **self.__kwargs)                               
  File "/usr/local/lib/python2.7/dist-packages/stomp/listener.py", line 231, in
 __heartbeat_loop                                                              
    _, e, _ = sys.exc_info()                                                   
NameError: global name 'sys' is not defined

Solution: add import sys at the top?

Documentation ?

Hello,

I'm new to stomp, and stomp.py, I tried the demo, and received a message I previously posted using curl and the rest endpoint, great. Now I'm searching for some documentation, typically about the subscribe method, I found the "API Documentation" listing classes methods and parameters name, but I can't find a documentation about "what does what", typically the ack parameter, where do I find what are the different possible values for it ?

If this kind of documentation exists, I think it may be cool to link to it from the README,
Bests.

Unable to make reconnecting work

I have this method as part of my listener class, which I believe ought to trigger a reconnect in the event of a heartbeat timeout.

It doesn't seem to work, and stomp.py seems to end up sending data to an unconnected socket (which it handles gracefully).

    def on_heartbeat_timeout(self):
        # Oh damn - the heartbeats have timed out....
        connected = False
        Log.debug("Heartbeat timed out - attempting a reconnect")
        for n in range(1, 31):
            try:
                Log.debug("Reconnecting: Attempt %d" % n)
                self._stomp.start()
                self._stomp.connect(wait = True)
                connected = True
            except stomp.ConnectFailedException:
                # Oh, still can't reconnect
                Log.debug("Reconnect attempt failed")
                time.sleep(2)

The debug log from this is as follows:

DEBUG:stomp.py:Heartbeat timeout: diff_receive=23.0276641846, diff_heartbeat=13.0276241302, time=1388048391.94, lastrec=1388048378.92
DEBUG:pbls.sinks:Heartbeat timed out - attempting a reconnect
DEBUG:pbls.sinks:Reconnecting: Attempt 1
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 2
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 3
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 4
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 5
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 6
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 7
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 8
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:stomp.py:Starting receiver loop
DEBUG:pbls.sinks:Reconnecting: Attempt 9
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:stomp.py:Starting receiver loop
DEBUG:pbls.sinks:Reconnecting: Attempt 10
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 11
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 12
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 13
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 14
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 15
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 16
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 17
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 18
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 19
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 20
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 21
DEBUG:stomp.py:Starting receiver loop
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 22
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 23
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 24
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:stomp.py:Starting receiver loop
DEBUG:pbls.sinks:Reconnecting: Attempt 25
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:stomp.py:Starting receiver loop
DEBUG:pbls.sinks:Reconnecting: Attempt 26
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:stomp.py:Starting receiver loop
DEBUG:pbls.sinks:Reconnecting: Attempt 27
DEBUG:stomp.py:Starting receiver loop
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:pbls.sinks:Reconnecting: Attempt 28
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:stomp.py:Starting receiver loop
DEBUG:pbls.sinks:Reconnecting: Attempt 29
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:stomp.py:Starting receiver loop
DEBUG:pbls.sinks:Reconnecting: Attempt 30
INFO:stomp.py:Sending frame ['STOMP', '\n', 'accept-version:1.1\n', 'heart-beat:10000,10000\n', '\n', '\x00']
DEBUG:stomp.py:Starting receiver loop
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended
DEBUG:stomp.py:Receiver loop ended

Are you able to explain what is going wrong here?

disconnect issues

I have a short-lived client that pulls things off a queue and disconnects. I had noticed that under 4.0.11, it was printing a blank line shortly before quitting. This turns out to be a print of an exception in the receiver loop. I noticed that post 4.0.11, this print was turned into a debug log, but the error was not from process_frame or my listener, it was a ConnectionClosedException.
The ConnectionClosedException is not propagating up, so the 'except exception.ConnectionClosedException' block, firing the disconnected event, is never run.

implicit disconnect receipts are broken for 1.0 and 1.1, since the Connection wrapper classes default the receipt to None, masking the default receipt defined in the Protocol classes. The Connection12 class is for some reason different and does not take the standard parameters in its disconnect wrapper.

If i use Connection12 and the receipt is used (verified by looking at debug logging), for some reason self.running does not become False, and the ConnectionClosedException still happens. I will probably look more into this after the other issues are dealt with.

For the first issue, I would recommend pushing the catchall exception handler down into notify, and removing some of the nested try blocks in the receiver loop. If that is acceptable to you, I can work on a pull request. I think the second could be solved by moving the default receipt from the ProtocolXX classes to StompConnectionXX

[stomp.py] Receiver loop ended (and gevent)

On linux, not sure if there is a problem with stomp.py v4.0.12 and gevent 0.13.7. When the remote ActiveMQ server was down or restarted. Server logs recorded "Receiver loop ended". However, the listener registered with the connection doesn't get on_disconnected() triggered. When stomp.py decided to disconnect, on_disconnected() will be called but doing

  for n in range(1,3):
        try:
            self.conn.set_listener()
            self.conn.set_listener("JMSListener", self)
            self.conn.stop()
            self.conn.start()
            self.conn.connect(wait=False)
            print "Connected?"
            break
        except Exception:
            print "Reconnect attempt failed:"
            time.sleep(1)

does not resume connection. The conn.send calls after that will get NotConnectedException

Currently, I work around the issue by try/except on conn.send() and do the connection code above inside except to restore connection but I probably lost 1 or more send before connection is restored.

So issue 1) Receiver loop ended does not trigger listener method. Issue 2) can't get reconnection code inside listener to really connect.

Finally, understand that app level reconnect had different approaches but can the stomp.py provide a default implementation or recipe to do it the basic/working way?

Thank you!

Lost messages due to heartbeat handling

I have run into an issue where infrequently messages are delivered by ActiveMQ, but never seen in the consumer/listener. I eventually tracked this down to __read() in transport.py and the way heartbeats are detected/handled. I've been running version 4.1.2, however, the code in question isn't any different in 4.1.9.

Here is an example, the only important detail is the end. Each line represents one chunk from self.receive() in the __read() function:

Headers...
Body...
\n
\x00\n

The \n on line 3 (part of the message body) comes in as a single byte and matches the condition elif c == b'\x0a': triggering an immediate return, dumping everything in fastbuf and effectively losing the message.

My current solution is the following, inside of elif c == b'\x0a'::

fastbuf_tell = fastbuf.tell()
if fastbuf_tell == 0 or (fastbuf_tell == 1 and fastbuf.getvalue() == b'\x0a'):
    # heartbeat (special case)
    return [c, ]

I don't know if it is a valid solution in all cases, only that it worked under my configuration.

If you take a hypothetical queue service that only writes one byte at a time to the connection, this problem would happen consistently, just in reading the headers. In real-world conditions this was happening about once every 4 hours on a 30 message/second connection.

One additional detail, this connection was configured with no heart beats: heart-beat:0,0. Ideally the heartbeat handling code would not be active when heart beats are turned off. This was the last place I looked because I figured, we don't have heart beats on, so I won't be hitting the heart beat special case.

How can I specify a protocol?

How can I specify a protocol? I need "ssl+stomp" or just "ssl" or "https" or "amqp+ssl".

This doesn't work:

conn = stomp.Connection(host_and_ports=[("stomp+ssl://something.com", 61613)], use_ssl=True)

and even this doesn't:

conn = stomp.Connection(host_and_ports=[("ssl://something.com", 61613)], use_ssl=True)

whereas this does but it costed me a few hours to discover it because in the documentation isn't described:

conn = stomp.Connection(host_and_ports=[("something.com", 61613)], use_ssl=True)

Unable to reconnect after disconnect handled

Using stomp.py 4.1.11 with STOMP 1.2 and ActiveMQ.

I have a listener:

class MyListener(stomp.ConnectionListener):
  def __init__(self, conn):
    self.conn = conn

  def on_disconnected(self):
    self.conn.start()
    self.conn.connect(None, None, wait=True)
    self.conn.subscribe("/queue/test", "foo-1", "client-individual")

conn = stomp.Connection12([('localhost', 61613)], reconnect_sleep_initial=2, reconnect_attempts_max=15)
conn.set_listener('', MyListener(conn))
self.conn.start()
self.conn.connect(None, None, wait=True)
self.conn.subscribe("/queue/test", "foo-1", "client-individual")

while True:
  time.sleep(1)

It starts up, connects and subscribes to "/queue/test". I then stop ActiveMQ, and start it again. A bunch of connection attempts are logged and then I see the messages:

Attempting connection...
Established connection...
Starting receiver loop....
Sending frame cmd='STOMP'....
Received frame: 'CONNECTED'....
Sending frame cmd='SUBSCRIBE'....
Receiver loop ended

I'm unsure as to why the receiver loop ends. At that point the subscriber no longer receives messages.

ssl example

Hi,
Can you please post an example on how to create sender with SSL certificate.
Here is how I send message:

`import time
import sys
import stomp
conn = stomp.Connection()
conn.start()
conn.connect()

conn.send(body='Hello world', destination='/queue/test')
conn.disconnect()`
How do I add my cer and key to the message?
Thanks

timeout not working on Transport.start

Hi,

I recently noticed that the timeout, set at the time of initializing stomp.Connection(), wouldn't work properly on start method.
For e.g. If I enter the rabbitmq host address to an unreachable address, it takes about a minute to get the exception of type stomp.exception.ConnectFailedException even though I set the timeout to 10.

I just checked the source code and following change seems to solve the issue:
Line 696 of file stomp/transport.py, the code "self.socket.settimeout(self.__timeout)" is probably inside "if need_ssl: " block by mistake and just taking the code out of "if need_ssl" block would solve the issue.

Regards

improve documentation

API docs are confusingly organized and the "simple example" is laughably _over_simplified.

Destination regex errors on 4.0.11 version

Hello, Jason,

we are dealing with some bug introduced in new version of stomp.py, 4.0.11.

We are using 4.0.10 normally, but after some update to 4.0.11 version, Apache Apollo returns the following exception headline:

Internal Server Error: org.apache.activemq.apollo.util.path.PathParser$PathException: Invalid destination: 'companyname\cservice\cMODULE\cSUBMODULE\cPROCESSING\cREQUEST', it does not match regex: [ a-zA-Z0-9_-%~:()]+ | 1442223a9c3

Validating this queue name with regex, it's normal.

Checking it out on recent stomp.py changes, we found that it changed on last week.

Now, I can't open stomp.py code to fix this issue. May you indicate a path to start a fix on this issue?

Best regards,

Andre Pastore

using stomp.send_frame fails after a couple of times

After 12 xmits using stomp.send_frame(), I get a stomp.connection.NotConnectedException. If I send using "stomp.send()", it runs forever. It could be I'm using stomp wrong, but it does seem pretty straightforward.
I'm using stomp.py 4.1.8, ActiveMQ 5.12.1 and python python 2.7.5 on a RHEL 7 platform.

#!/usr/bin/python
import random
import stomp
import socket
from time import sleep

if __name__ == '__main__':

   hdrs = {'expires': '0', 'timestamp': '1452527028845', 'destination': '/topic/FOO', 'persistent': 'true', 'priority': '4', 'message-id': 'ID:520969-foobar-52253-1451938805275-0:0:2:392022:1', 'subscription': '3'}


   nbody = """
<?xml version="1.0" encoding="UTF-8"?>
<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd" https="false">
    <meta>
        <author>Brian Cantoni</author>
        <description>Generate random Lorem Ipsum text from lipsum.com. Parameters: amount=number of things to fetch; what: paras, words, bytes, or lists; start: set to "no" to not start all strings with Lorem Ipsum.</description>
        <documentationURL>http://www.lipsum.com/</documentationURL>
        <sampleQuery>select * from {table} where amount='5' and what='paras';</sampleQuery>
    </meta>
    <bindings>
        <select itemPath="" produces="XML">
            <urls>
                <url></url>
            </urls>
            <inputs>
                <key id="%f" type="xs:string" paramType="query" />
                <key id="%f" type="xs:string" paramType="query" />
                <key id="%f" type="xs:string" paramType="query" default="yes" />
            </inputs>
            <execute>
                <![CDATA[
                var q = y.query('select * from html where url="http://www.lipsum.com/feed/http?amount=' + amount + '&what=' + what + '&start=' + start + '" and xpath=\'//div[@id="lipsum"]//p\'');
                if (q.results) {
                    response.object = q.results;
                }
                ]]>
            </execute>
        </select>
    </bindings>
</table>
"""

   a = 0.72
   b = -0.95
   c = 0.01
   count = 0
   addr = ('localhost',61613)
   conx = stomp.Connection([addr])
   conx.start()
   conx.connect(wait=True)

   while True:
      try:
         # this fails after 12 reps:
         conx.send_frame(cmd="SEND",body=nbody % (a,b,c), headers=hdrs)

         # This runs for a long time
         # conx.send(body=nbody % (a,b,c), destination='/topic/FOO')
      except socket.error, e:
         print 'socket error: %s' % e.strerror
         sleep(0.5)
         conx.stop()
         conx.disconnect()
         sleep(0.5)
         conx = stomp.Connection([addr])
         conx.start()
         conx.connect(wait=True)
         continue
      except stomp.exception.NotConnectedException, e:
         print 'stomp error: % s' % e
         sleep(1)
         conx = stomp.Connection([addr])
         conx.start()
         conx.connect(wait=True)
         continue
      # conx.disconnect()
      print 'sent %d' % count
      count += 1
      sleep(1)

stomp.py 4.1.1 cannot be pip installed

$ mkvirtualenv scratch
New python executable in scratch/bin/python
Installing setuptools, pip...done.
(scratch)$ pip install stomp.py
You are using pip version 6.1.1, however version 7.1.0 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting stomp.py
This repository located at xxxxxx is not a trusted host, if this repository is available via HTTPS it is recommend to use HTTPS instead, otherwise you may silence this warning with '--trusted-host xxxxx'.
DEPRECATION: Implicitly allowing locations which are not hosted at a secure origin is deprecated and will require the use of --trusted-host in the future.
Downloading stomp.py-4.1.1.tar.gz (134kB)
100% |████████████████████████████████| 135kB 220kB/s
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 20, in
File "/tmp/pip-build-IV32I_/stomp.py/setup.py", line 4, in
import coverage
ImportError: No module named coverage

----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-IV32I_/stomp.py

asyncio support

Hi

How easy would it be to use stomp.py in an asyncio framework?

As I understand it, currently stomp.py handles async-ness using a connection listener in a separate thread, one needs to do some synchronisation between the different threads.
coroutines work simply because they avoid the need for synchronisation, and I'm unsure how an on_message() would be able to insert something into the event-loop in a safe way.

Any ideas? It might be useful to look at something like aoizmq? Am I approaching this wrong?

Regards

TypeError in Transport

Hi, I've spotted a small bug:
In transport.py line 174 len(f.body) is called, but f.body can be None which leads to an exception:

Traceback (most recent call last):
  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)
  File "venv/lib/python3.4/site-packages/stomp/transport.py", line 300, in __receiver_loop
    self.process_frame(f, frame)
  File "venv/lib/python3.4/site-packages/stomp/transport.py", line 174, in process_frame
    log.info("Received frame: %r, headers=%r, len(body)=%r", f.cmd, f.headers, len(f.body))
TypeError: object of type 'NoneType' has no len()

best regards,
Patrick

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.