engineio

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package engineio implements the Engine.IO v4 protocol layer: session management, HTTP long-polling and WebSocket transports, transport upgrades and the heartbeat.

A Server is an http.Handler serving Engine.IO sessions, and a Client dials a remote Engine.IO endpoint; both deliver raw message packets. The Socket.IO protocol (github.com/kingecg/gosocketio/socketio) is layered on top of this package.

Protocol reference: https://socket.io/docs/v4/engine-io-protocol/

Index

Examples

Constants

View Source
const (
	ErrCodeUnknownTransport = iota
	ErrCodeUnknownSID
	ErrCodeBadHandshakeMethod
	ErrCodeBadRequest
	ErrCodeForbidden
	ErrCodeUnsupportedProtocolVersion
)

Protocol error codes, mirroring the reference implementation.

View Source
const Protocol = 4

Protocol revision supported by this package.

Variables

View Source
var (
	// ErrUnsupportedProtocol is returned when the EIO protocol version is
	// not 4.
	ErrUnsupportedProtocol = errors.New("engineio: unsupported protocol version")

	// ErrUnknownTransport is returned when the transport is not enabled.
	ErrUnknownTransport = errors.New("engineio: unknown transport")

	// ErrBadHandshakeMethod is returned when a handshake request is not GET.
	ErrBadHandshakeMethod = errors.New("engineio: bad handshake method")

	// ErrBadRequest is returned for generic bad requests.
	ErrBadRequest = errors.New("engineio: bad request")

	// ErrForbidden is returned when AllowRequest rejects the handshake.
	ErrForbidden = errors.New("engineio: forbidden")

	// ErrUnknownSID is returned when the sid is not known.
	ErrUnknownSID = errors.New("engineio: session id unknown")

	// ErrInvalidPacket is returned when a transport packet cannot be
	// decoded. It wraps transport.ErrInvalidPacket, so errors.Is matches
	// both this sentinel and the transport-level one.
	ErrInvalidPacket = fmt.Errorf("%w: invalid packet", transport.ErrInvalidPacket)

	// ErrHeartbeatTimeout is returned when the peer fails to answer a ping
	// within the configured ping timeout.
	ErrHeartbeatTimeout = errors.New("engineio: heartbeat timeout")

	// ErrPayloadTooLarge is returned when a single packet in a polling
	// payload exceeds the configured maxPayload. It aliases
	// transport.ErrPayloadTooLarge so errors.Is matches both levels.
	ErrPayloadTooLarge = transport.ErrPayloadTooLarge
)

Sentinel errors.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is an Engine.IO client. It establishes a session with an Engine.IO server over HTTP long-polling and/or WebSocket, keeps the heartbeat alive and delivers message packets.

func Dial

func Dial(ctx context.Context, rawURL string, opts *Options) (*Client, error)

Dial connects to an Engine.IO server. It blocks until the handshake completes or ctx is cancelled.

Example

ExampleDial demonstrates a full Engine.IO round trip: dial a server, send a message and receive the echo. By default the client starts on HTTP long-polling and transparently upgrades to WebSocket.

package main

import (
	"context"
	"fmt"
	"log"
	"net/http/httptest"
	"time"

	"github.com/kingecg/gosocketio/engineio"
)

func main() {
	srv := engineio.NewServer(nil)
	srv.OnData(func(s *engineio.Socket, data []byte, binary bool) {
		s.SendMessage(data, binary)
	})
	httpSrv := httptest.NewServer(srv)
	defer httpSrv.Close()

	c, err := engineio.Dial(context.Background(), httpSrv.URL+"/socket.io/", nil)
	if err != nil {
		log.Fatal(err)
	}
	defer c.Close()

	echo := make(chan string, 1)
	c.OnData(func(_ *engineio.Client, data []byte, _ bool) {
		echo <- string(data)
	})
	if err := c.SendMessage([]byte("hello"), false); err != nil {
		log.Fatal(err)
	}
	select {
	case msg := <-echo:
		fmt.Println("echo:", msg)
	case <-time.After(5 * time.Second):
		log.Fatal("timed out waiting for echo")
	}
}
Output:
echo: hello

func (*Client) Close

func (c *Client) Close() error

Close closes the session.

func (*Client) OnClose

func (c *Client) OnClose(f func(*Client, error))

OnClose registers a handler invoked when the session is closed.

func (*Client) OnData

func (c *Client) OnData(f func(*Client, []byte, bool))

OnData registers a handler invoked for every received message packet.

func (*Client) OnOpen

func (c *Client) OnOpen(f func(*Client))

OnOpen registers a handler invoked once the handshake completes.

func (*Client) SID

func (c *Client) SID() string

SID returns the session identifier once the handshake has completed.

func (*Client) SendMessage

func (c *Client) SendMessage(data []byte, binary bool) error

SendMessage sends a message packet to the server.

func (*Client) SetLogger

func (c *Client) SetLogger(l Logger)

SetLogger sets the client logger.

type Context

type Context = context.Context

Context is a shorthand for context.Context to keep the public API terse.

type Logger

type Logger interface {
	Debugf(format string, args ...any)
	Infof(format string, args ...any)
	Warnf(format string, args ...any)
	Errorf(format string, args ...any)
}

Logger is the logging interface used across the package.

var NopLogger Logger = slogLogger{/* contains filtered or unexported fields */}

NopLogger discards all log output.

type Options

type Options struct {
	// PingInterval is how long to wait before sending a new ping packet.
	// Default: 25s.
	PingInterval time.Duration

	// PingTimeout is how long to wait for a pong packet before considering
	// the connection closed. Default: 20s.
	PingTimeout time.Duration

	// UpgradeTimeout is how long to wait for a client to complete a
	// transport upgrade before cancelling it. Default: 10s.
	UpgradeTimeout time.Duration

	// MaxHTTPBufferSize is the maximum size in bytes of a received payload
	// or POST body before closing the session. Default: 1 MiB.
	MaxHTTPBufferSize int64

	// Transports lists the enabled transports. Default: ["polling", "websocket"].
	Transports []string

	// AllowUpgrades enables or disables transport upgrades. Default: true.
	AllowUpgrades bool

	// AllowRequest is an optional authorization hook invoked on handshake
	// requests. Return an error to reject the request with HTTP 403.
	AllowRequest func(r *http.Request) error

	// GenerateID overrides the session id generator. Default: random base64.
	GenerateID func(r *http.Request) string
}

Options configures an Engine.IO server or client session.

type Server

type Server struct {
	Options Options

	// AcceptOptions customizes the WebSocket upgrade. Defaults to allowing
	// all origins (matching the reference implementation).
	AcceptOptions *websocket.AcceptOptions
	// contains filtered or unexported fields
}

Server is an Engine.IO server. It implements http.Handler and can be mounted on any URL path.

Example

ExampleServer demonstrates wiring the server-side handlers: OnConnect, OnData and OnClose. The server is an http.Handler, so it can be mounted on any path of an existing HTTP server.

package main

import (
	"context"
	"fmt"
	"log"
	"net/http/httptest"
	"time"

	"github.com/kingecg/gosocketio/engineio"
)

func main() {
	disconnected := make(chan struct{})
	srv := engineio.NewServer(nil)
	srv.OnConnect(func(s *engineio.Socket) {
		fmt.Println("client connected")
	})
	srv.OnData(func(s *engineio.Socket, data []byte, binary bool) {
		s.SendMessage(data, binary)
	})
	srv.OnClose(func(s *engineio.Socket, reason string, err error) {
		close(disconnected)
	})
	httpSrv := httptest.NewServer(srv)
	defer httpSrv.Close()

	c, err := engineio.Dial(context.Background(), httpSrv.URL+"/socket.io/", nil)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.Close(); err != nil {
		log.Fatal(err)
	}
	select {
	case <-disconnected:
		fmt.Println("client disconnected")
	case <-time.After(5 * time.Second):
		log.Fatal("server never observed the disconnect")
	}
}
Output:
client connected
client disconnected

func NewServer

func NewServer(opts *Options) *Server

NewServer creates an Engine.IO server.

func (*Server) ClientsCount

func (s *Server) ClientsCount() int

ClientsCount returns the number of active sessions.

func (*Server) Close

func (s *Server) Close()

Close closes all active sessions.

func (*Server) OnClose

func (s *Server) OnClose(f func(s *Socket, reason string, err error))

OnClose registers a handler invoked when a session is closed.

func (*Server) OnConnect

func (s *Server) OnConnect(f func(s *Socket))

OnConnect registers a handler invoked once a new session is established.

func (*Server) OnData

func (s *Server) OnData(f func(s *Socket, data []byte, binary bool))

OnData registers a handler invoked for every received `message` packet.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.

func (*Server) SetLogger

func (s *Server) SetLogger(l Logger)

SetLogger sets the server logger.

type Socket

type Socket struct {
	// contains filtered or unexported fields
}

Socket represents a single Engine.IO session on the server side.

func (*Socket) Close

func (s *Socket) Close()

Close closes the socket gracefully: pending packets are flushed and a `close` packet (or WebSocket close frame) is delivered to the client.

func (*Socket) ID

func (s *Socket) ID() string

ID returns the session identifier.

func (*Socket) MaybeUpgrade

func (s *Socket) MaybeUpgrade(newTransport transport.Transport)

MaybeUpgrade is called when the client attempts to upgrade the current transport to the given one (websocket).

func (*Socket) ReadyState

func (s *Socket) ReadyState() string

ReadyState returns a human readable session state.

func (*Socket) RemoteAddr

func (s *Socket) RemoteAddr() string

RemoteAddr returns the remote address of the client.

func (*Socket) SendMessage

func (s *Socket) SendMessage(data []byte, binary bool)

SendMessage sends a `message` packet to the client.

func (*Socket) Transport

func (s *Socket) Transport() transport.Transport

Transport returns the currently active transport.

Directories

Path Synopsis
Package transport implements the Engine.IO v4 protocol primitives (packet/payload encoding) and the underlying HTTP long-polling and WebSocket transports.
Package transport implements the Engine.IO v4 protocol primitives (packet/payload encoding) and the underlying HTTP long-polling and WebSocket transports.

Jump to

Keyboard shortcuts

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