jasonrbriggs / stomp.py

“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.
Apache License 2.0
492 stars 167 forks source link

[Help] How can I use stomp.py to subscribe and set a receiving listener to endpoint properly? #409

Open Paper-Folding opened 1 year ago

Paper-Folding commented 1 year ago

In JavaScript stomp client, I can use code below to set up a listener for each receiving endpoint:

import SockJS from "sockjs-client";
import Stomp from "stomp-websocket";

let sock = new SockJS('http://127.0.0.1:9090/stomp-api');
let stomp = Stomp.over(sock);
stomp.connect({}, function () {
    stomp.subscribe('/topic/news', function (msg) {
        console.log('Received news', msg.body);
    });

    stomp.subscribe('/topic/sports', function (msg) {
        console.log('Received sports news', msg.body);
    });
});

I wonder what is the equivalent code in stomp.py, thank you!

Paper-Folding commented 1 year ago

I did not even know if I was right, I use the python code like below:

import stomp

class MyListener(stomp.ConnectionListener):

    def __init__(self, conn):
        self.conn = conn

    def on_error(self, frame):
        print('received an error "%s"' % frame.body)

    def on_message(self, frame):
        print('received a message "%s"' % frame.body)

if __name__ == '__main__':
    connection = stomp.Connection([('127.0.0.1', 9090)], heartbeats=(4000, 4000))
    connection.set_listener('/stomp-api', MyListener(connection))
    connection.connect(wait=True)
    connection.subscribe(destination='/topic/news', id=412, ack='auto')

But received stomp.exception.ConnectFailedException always:

Traceback (most recent call last):
  File "test.py", line 19, in <module>
    connection.connect(wait=True)
  File "D:\env\python\lib\site-packages\stomp\connect.py", line 151, in connect
    Protocol11.connect(self, *args, **kwargs)
  File "D:\env\python\lib\site-packages\stomp\protocol.py", line 339, in connect
    self.transport.wait_for_connection()
  File "D:\env\python\lib\site-packages\stomp\transport.py", line 318, in wait_for_connection
    raise exception.ConnectFailedException()
stomp.exception.ConnectFailedException

And my stomp server is set up using spring-boot-starter-websocket, in other words, Java. Every time the python script is run, the Java stomp server can always receive an error:

java.lang.IllegalArgumentException: Invalid character found in method name [STOMP0x0aaccept-version:1.10x0a0x0a0x00...]. HTTP method names must be tokens
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:419) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:271) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.68.jar:9.0.68]

While this error not exists on connecting by JavaScript stomp client, I wonder how I can implement python stomp client properly like the one in JavaScript.

malaccan commented 4 months ago

just saw this issue. i have the same issue and am a bit stuck but thought i share where i'm at.

i'm using the exact same code template as a client to connect to spring boot. it is setup for encrypted wss so i passed in the necessary SSL context/cert paths accordingly. but i keep getting the same error in the spring boot server whenever i call conn.connect(wait=True):

Error parsing HTTP request header
java.lang.IllegalArgumentException: Invalid character found in 
method name [STOMP0x0aaccept-version:1.10x0a0x0a0x00...].
HTTP method names must be tokens


i wrote a separate java client using Spring Boot's WebSocketStompClient, and it works as expected. i am running spring boot v6.3.0. now, i wonder if spring boot is expecting a different message format than the ones coded up inside stomp.py?