https://github.com/nofeaturesonlybugs/stomp
Go STOMP peer and broker
https://github.com/nofeaturesonlybugs/stomp
Last synced: 3 months ago
JSON representation
Go STOMP peer and broker
- Host: GitHub
- URL: https://github.com/nofeaturesonlybugs/stomp
- Owner: nofeaturesonlybugs
- License: mit
- Created: 2022-06-14T18:31:11.000Z (almost 3 years ago)
- Default Branch: master
- Last Pushed: 2022-06-14T18:36:04.000Z (almost 3 years ago)
- Last Synced: 2025-01-11T07:49:56.304Z (4 months ago)
- Language: Go
- Size: 41 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://pkg.go.dev/github.com/nofeaturesonlybugs/stomp)
[](https://goreportcard.com/report/github.com/nofeaturesonlybugs/stomp)
[](https://app.travis-ci.com/nofeaturesonlybugs/stomp)
[](https://codecov.io/gh/nofeaturesonlybugs/stomp)
[](https://opensource.org/licenses/MIT)`stomp` is a partial implementation of a STOMP client and broker.
It is unlikely this project will ever be fully completed.
## Client
There is no actual `Client` struct in this package; code exists but it is incomplete and commented out. The following sections describe how a stomp.Peer can be used as a low-level client, meaning it has no inbuilt features for acknowledgement, heartbeats, protocol negotiation, etc. Despite the lack of features the stomp.Peer is fairly well tested and seemingly reliable.
**Connecting**
```go
func Connect() (stomp.Peer, error) {
var peer stomp.Peer
//
conn, err := tls.Dial("tcp", Address, TLSConf) // Address, TLSConf are just placeholders
if err != nil {
return peer, error
}
//
peer.R, peer.W = conn, conn
peer.Start(nil) // TODO Can pass a waitgroup here.
//
peer.Send <- frames.Connect("user123", "s3cr3t")
select {
case f := <-peer.Receive:
if f.Command != stomp.CommandConnected {
peer.Shutdown()
return peer, fmt.Errorf("main: stomp-conf-connect: expected %v but got %v", stomp.CommandConnected, f.Command)
}
return peer, nil
case err = <-peer.Error:
peer.Shutdown()
return peer, err
}
}
```**Subscribing**
```go
var peer stomp.Peer
topics := []string{
"/topic/foo",
"/topic/bar",
}
for _, t := range topics {
peer.Send <- frames.Subscribe(t, "auto", "") // Auto for ack: auto
}
```**Send Messages**
```go
f := frames.Send("/topic/foo", []byte("Hello"))
f.Headers[stomp.HeaderReplyTo] = "/temp-queue/"
peer.Send <- ff := frames.SendString("/topic/foo", "Goodbye")
f.Headers[stomp.HeaderReplyTo] = "/temp-queue/"
peer.Send <- f
```**Receive Messages**
```go
// This message loop ends on the first error or when a channel is closed.
var peer stomp.Peer
MessageLoop:
for {
select {
case f, open := <-peer.Receive:
if !open {
break MessageLoop
}
fmt.Printf("frame: %v", f)
case err, open := <-peer.Error:
if !open {
break MessageLoop
}
fmt.Printf("error: %v", err)
}
}
```Alternate message loop:
```go
// This message loop stays open until both channels are closed. This may
// be ideal if the error comes through while messages are still pending
// on the Receive channel.
var peer stomp.Peer
receiveC, errorC := peer.Receive, peer.Error
for receiveC != nil || errorC != nil {
select {
case f, open := <-receiveC:
if !open {
receiveC = nil
continue
}
fmt.Printf("frame: %v", f)
case err, open := <-errorC:
if !open {
errorC = nil
continue
}
fmt.Printf("error: %v", err)
}
}
```## Server
The `server` package has a partially complete broker implementation.
**Starting a broker**
```go
srv := server.Server{
// Bind address.
Addr: "0.0.0.0:61613",// Optional event channel. If set then it must be consumed.
// Events: make(chan<- interface{}),// Optional TLS configuration. If set then a TLS listener is created.
// TLSConfig: &tls.Config{},// Optional logger.
// Logger: nil,// Optional session ID generator.
// NewSessionID: func() string { ... },
}
err := srv.ListenAndServe() // ListenAndServe is non-blocking
if err != nil {
fmt.Println(err)
return
}
defer srv.Shutdown()// TODO Wait on SigC or other quit mechanism
```The server does not fully implement the STOMP protocol.
What works:
- ✓ Server start and stop with ordered shutdown
- ✓ Subscribe and unsubscribeAll destinations are treated as pubsub.
Missing STOMP features:
- Version negotiation
- Heartbeats
- DISCONNECT
- ACK, NACK
- BEGIN, COMMIT, ABORT
- RECEIPTSome message headers are not fully implemented. For example SUBSCRIBE can include an `id` header (supported) which should be sent as `subscription` header in MESSAGE frame (not supported).
Additionally high level broker features are missing:
- Authentication and/or RBAC
- Message expiration
- Client reconnect and resume
- Round-robin destinations (i.e. QUEUES in ActiveMQ)