melody

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 30, 2024 License: BSD-2-Clause Imports: 7 Imported by: 0

README

Melody

This project is a fork of the latest version of olahol/melody that continues its development independently.

🎶 Minimalist websocket framework for Fasthttp.

Melody is websocket framework based on github.com/fasthttp/websocket that abstracts away the tedious parts of handling websockets. It gets out of your way so you can write real-time apps. Features include:

  • Clear and easy interface similar to net/http or Gin.
  • A simple way to broadcast to all or selected connected sessions.
  • Message buffers making concurrent writing safe.
  • Automatic handling of sending ping/pong heartbeats that timeout broken sessions.
  • Store data on sessions.

Install

go get github.com/maratrixx/melody
package main

import (
	"net/http"

	"github.com/maratrixx/melody"
)

func main() {
	m := melody.New()

	m.HandleMessage(func(s *melody.Session, msg []byte) {
		s.Write(msg)
	})

	handler := func(ctx *fasthttp.RequestCtx) {
		m.HandleRequest(ctx)
	}

	fasthttp.ListenAndServe(":5000", handler)
}

Tests

Here are the test results:

$ go test -timeout 100s github.com/maratrixx/melody -failfast -v -count=1 -cover

output:

=== RUN   TestEcho
--- PASS: TestEcho (0.82s)
=== RUN   TestEchoBinary
--- PASS: TestEchoBinary (0.81s)
=== RUN   TestWriteClosedServer
--- PASS: TestWriteClosedServer (0.54s)
=== RUN   TestWriteClosedClient
--- PASS: TestWriteClosedClient (0.54s)
=== RUN   TestUpgrader
--- PASS: TestUpgrader (0.52s)
=== RUN   TestBroadcast
--- PASS: TestBroadcast (4.03s)
=== RUN   TestClose
--- PASS: TestClose (0.58s)
=== RUN   TestLen
--- PASS: TestLen (0.66s)
=== RUN   TestSessions
--- PASS: TestSessions (0.71s)
=== RUN   TestPingPong
--- PASS: TestPingPong (0.53s)
=== RUN   TestHandleClose
--- PASS: TestHandleClose (0.53s)
=== RUN   TestHandleError
--- PASS: TestHandleError (0.53s)
=== RUN   TestErrClosed
--- PASS: TestErrClosed (0.53s)
=== RUN   TestErrSessionClosed
--- PASS: TestErrSessionClosed (0.52s)
=== RUN   TestErrMessageBufferFull
--- PASS: TestErrMessageBufferFull (0.53s)
=== RUN   TestSessionKeys
--- PASS: TestSessionKeys (0.83s)
=== RUN   TestSessionKeysConcurrent
--- PASS: TestSessionKeysConcurrent (0.52s)
=== RUN   TestMisc
--- PASS: TestMisc (0.52s)
=== RUN   TestHandleSentMessage
--- PASS: TestHandleSentMessage (1.05s)
=== RUN   TestConcurrentMessageHandling
=== RUN   TestConcurrentMessageHandling/text_should_error
=== RUN   TestConcurrentMessageHandling/text_should_not_error
=== RUN   TestConcurrentMessageHandling/binary_should_error
=== RUN   TestConcurrentMessageHandling/binary_should_not_error
--- PASS: TestConcurrentMessageHandling (2.94s)
    --- PASS: TestConcurrentMessageHandling/text_should_error (0.92s)
    --- PASS: TestConcurrentMessageHandling/text_should_not_error (0.56s)
    --- PASS: TestConcurrentMessageHandling/binary_should_error (0.93s)
    --- PASS: TestConcurrentMessageHandling/binary_should_not_error (0.53s)
PASS
coverage: 98.1% of statements
ok  	github.com/maratrixx/melody	18.486s	coverage: 98.1% of statements

Documentation

Index

Constants

View Source
const (
	CloseNormalClosure           = 1000
	CloseGoingAway               = 1001
	CloseProtocolError           = 1002
	CloseUnsupportedData         = 1003
	CloseNoStatusReceived        = 1005
	CloseAbnormalClosure         = 1006
	CloseInvalidFramePayloadData = 1007
	ClosePolicyViolation         = 1008
	CloseMessageTooBig           = 1009
	CloseMandatoryExtension      = 1010
	CloseInternalServerErr       = 1011
	CloseServiceRestart          = 1012
	CloseTryAgainLater           = 1013
	CloseTLSHandshake            = 1015
)

Close codes defined in RFC 6455, section 11.7. Duplicate of codes from gorilla/websocket for convenience.

Variables

View Source
var (
	ErrClosed            = errors.New("melody instance is closed")
	ErrSessionClosed     = errors.New("session is closed")
	ErrWriteClosed       = errors.New("tried to write to closed a session")
	ErrMessageBufferFull = errors.New("session message buffer is full")
)

Functions

func FormatCloseMessage

func FormatCloseMessage(closeCode int, text string) []byte

FormatCloseMessage formats closeCode and text as a WebSocket close message.

Types

type Config

type Config struct {
	WriteWait                 time.Duration // Duration until write times out.
	PongWait                  time.Duration // Timeout for waiting on pong.
	PingPeriod                time.Duration // Duration between pings.
	MaxMessageSize            int64         // Maximum size in bytes of a message.
	MessageBufferSize         int           // The max amount of messages that can be in a sessions buffer before it starts dropping them.
	ConcurrentMessageHandling bool          // Handle messages from sessions concurrently.
}

Config melody configuration struct.

type Melody

type Melody struct {
	Config   *Config
	Upgrader *websocket.FastHTTPUpgrader
	// contains filtered or unexported fields
}

Melody implements a websocket manager.

func New

func New() *Melody

New creates a new melody instance with default Upgrader and Config.

func (*Melody) Broadcast

func (m *Melody) Broadcast(msg []byte) error

Broadcast broadcasts a text message to all sessions.

func (*Melody) BroadcastBinary

func (m *Melody) BroadcastBinary(msg []byte) error

BroadcastBinary broadcasts a binary message to all sessions.

func (*Melody) BroadcastBinaryFilter

func (m *Melody) BroadcastBinaryFilter(msg []byte, fn func(*Session) bool) error

BroadcastBinaryFilter broadcasts a binary message to all sessions that fn returns true for.

func (*Melody) BroadcastBinaryOthers

func (m *Melody) BroadcastBinaryOthers(msg []byte, s *Session) error

BroadcastBinaryOthers broadcasts a binary message to all sessions except session s.

func (*Melody) BroadcastFilter

func (m *Melody) BroadcastFilter(msg []byte, fn func(*Session) bool) error

BroadcastFilter broadcasts a text message to all sessions that fn returns true for.

func (*Melody) BroadcastMultiple

func (m *Melody) BroadcastMultiple(msg []byte, sessions []*Session) error

BroadcastMultiple broadcasts a text message to multiple sessions given in the sessions slice.

func (*Melody) BroadcastOthers

func (m *Melody) BroadcastOthers(msg []byte, s *Session) error

BroadcastOthers broadcasts a text message to all sessions except session s.

func (*Melody) Close

func (m *Melody) Close() error

Close closes the melody instance and all connected sessions.

func (*Melody) CloseWithMsg

func (m *Melody) CloseWithMsg(msg []byte) error

CloseWithMsg closes the melody instance with the given close payload and all connected sessions. Use the FormatCloseMessage function to format a proper close message payload.

func (*Melody) HandleClose

func (m *Melody) HandleClose(fn func(*Session, int, string) error)

HandleClose sets the handler for close messages received from the session. The code argument to h is the received close code or CloseNoStatusReceived if the close message is empty. The default close handler sends a close frame back to the session.

The application must read the connection to process close messages as described in the section on Control Frames above.

The connection read methods return a CloseError when a close frame is received. Most applications should handle close messages as part of their normal error handling. Applications should only set a close handler when the application must perform some action before sending a close frame back to the session.

func (*Melody) HandleConnect

func (m *Melody) HandleConnect(fn func(*Session))

HandleConnect fires fn when a session connects.

func (*Melody) HandleDisconnect

func (m *Melody) HandleDisconnect(fn func(*Session))

HandleDisconnect fires fn when a session disconnects.

func (*Melody) HandleError

func (m *Melody) HandleError(fn func(*Session, error))

HandleError fires fn when a session has an error.

func (*Melody) HandleMessage

func (m *Melody) HandleMessage(fn func(*Session, []byte))

HandleMessage fires fn when a text message comes in. NOTE: by default melody handles messages sequentially for each session. This has the effect that a message handler exceeding the read deadline (Config.PongWait, by default 1 minute) will time out the session. Concurrent message handling can be turned on by setting Config.ConcurrentMessageHandling to true.

func (*Melody) HandleMessageBinary

func (m *Melody) HandleMessageBinary(fn func(*Session, []byte))

HandleMessageBinary fires fn when a binary message comes in.

func (*Melody) HandlePong

func (m *Melody) HandlePong(fn func(*Session))

HandlePong fires fn when a pong is received from a session.

func (*Melody) HandleRequest

func (m *Melody) HandleRequest(ctx *fasthttp.RequestCtx) error

HandleRequest upgrades http requests to websocket connections and dispatches them to be handled by the melody instance.

func (*Melody) HandleRequestWithKeys

func (m *Melody) HandleRequestWithKeys(ctx *fasthttp.RequestCtx, keys map[string]any) error

HandleRequestWithKeys does the same as HandleRequest but populates session.Keys with keys.

func (*Melody) HandleSentMessage

func (m *Melody) HandleSentMessage(fn func(*Session, []byte))

HandleSentMessage fires fn when a text message is successfully sent.

func (*Melody) HandleSentMessageBinary

func (m *Melody) HandleSentMessageBinary(fn func(*Session, []byte))

HandleSentMessageBinary fires fn when a binary message is successfully sent.

func (*Melody) IsClosed

func (m *Melody) IsClosed() bool

IsClosed returns the status of the melody instance.

func (*Melody) Len

func (m *Melody) Len() int

Len return the number of connected sessions.

func (*Melody) Sessions

func (m *Melody) Sessions() ([]*Session, error)

Sessions returns all sessions. An error is returned if the melody session is closed.

type Session

type Session struct {
	RequestCtx *fasthttp.RequestCtx
	Keys       map[string]any
	// contains filtered or unexported fields
}

Session wrapper around websocket connections.

func (*Session) Close

func (s *Session) Close() error

Close closes session.

func (*Session) CloseWithMsg

func (s *Session) CloseWithMsg(msg []byte) error

CloseWithMsg closes the session with the provided payload. Use the FormatCloseMessage function to format a proper close message payload.

func (*Session) Get

func (s *Session) Get(key string) (value any, exists bool)

Get returns the value for the given key, ie: (value, true). If the value does not exists it returns (nil, false)

func (*Session) IsClosed

func (s *Session) IsClosed() bool

IsClosed returns the status of the connection.

func (*Session) LocalAddr

func (s *Session) LocalAddr() net.Addr

LocalAddr returns the local addr of the connection.

func (*Session) MustGet

func (s *Session) MustGet(key string) any

MustGet returns the value for the given key if it exists, otherwise it panics.

func (*Session) RemoteAddr

func (s *Session) RemoteAddr() net.Addr

RemoteAddr returns the remote addr of the connection.

func (*Session) Set

func (s *Session) Set(key string, value any)

Set is used to store a new key/value pair exclusively for this session. It also lazy initializes s.Keys if it was not used previously.

func (*Session) UnSet

func (s *Session) UnSet(key string)

UnSet will delete the key and has no return value

func (*Session) WebsocketConnection

func (s *Session) WebsocketConnection() *websocket.Conn

WebsocketConnection returns the underlying websocket connection. This can be used to e.g. set/read additional websocket options or to write sychronous messages.

func (*Session) Write

func (s *Session) Write(msg []byte) error

Write writes message to session.

func (*Session) WriteBinary

func (s *Session) WriteBinary(msg []byte) error

WriteBinary writes a binary message to session.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL