Here's an English version of the promotional blog post for EasyWS:
Say Goodbye to Complexity! EasyWS: Building WebSocket Servers in Go Just Got Easier! ๐
Are you tired of grappling with the complexities of connection management, message broadcasting, and concurrency when building WebSocket applications in Go? Good news! Today, I'm thrilled to introduce EasyWSโa lightweight, highly extensible Go library designed to help you effortlessly build high-performance, scalable WebSocket servers.
โจ Why Choose EasyWS?
EasyWS is engineered with "simplicity and efficiency" at its core. It abstracts away the low-level intricacies of WebSocket handling, allowing you to focus your energy on implementing your core business logic. Whether you're developing real-time chat applications, dynamic dashboards, or multiplayer online games, EasyWS provides the solid foundation you need.
Here are the highlights of EasyWS:
- Ultimate Simplicity: Get a fully functional WebSocket server up and running with just a few lines of code.
- High Flexibility: Easily plug in custom logic to handle connections, disconnections, messages, and even user authentication.
-
Concurrency-Safe: Built with Go's native concurrency primitives (like
sync.RWMutex
and channels) to ensure all operations are thread-safe. - Excellent Scalability: Designed for efficient management of numerous client connections and message broadcasting.
- Comprehensive Customization: From client ID generation to cross-origin checks, and even integration with existing HTTP routersโeverything is under your control.
๐ฆ Installation, Effortlessly Done!
Getting started with EasyWS is incredibly straightforward; just one command:
go get github.com/whoamixl/easyws
EasyWS relies on github.com/gorilla/websocket
, which will be automatically fetched when you run go mod tidy
.
๐ Quick Start & Demo
Let's demonstrate the power of EasyWS with a simple "echo server" example. This server not only echoes messages but also handles client authentication and broadcasts messages from all authenticated clients to others!
package main
import (
"fmt"
"log"
"net/http"
"time"
"github.com/whoamixl/easyws" // Import the EasyWS library
)
func main() {
// Create a new WebSocket server instance
server := easyws.NewWebSocketServer()
// Configure Hub callbacks โ this is where your application logic goes!
server.Hub.OnConnect = func(client *easyws.Client) error {
log.Printf("New client connected: %s", client.ID)
// Send a welcome message to the newly connected client
client.SendText("Welcome to the EasyWS echo server! Please send 'AUTH <your_secret_key>' to authenticate.")
return nil // Return nil if connection should proceed
}
server.Hub.OnDisconnect = func(client *easyws.Client, err error) {
if err != nil {
log.Printf("Client %s disconnected with error: %v", client.ID, err)
} else {
log.Printf("Client %s disconnected cleanly.", client.ID)
}
// You can notify other clients here that someone disconnected
}
server.Hub.OnMessage = func(client *easyws.Client, messageType int, data []byte) error {
msg := string(data)
log.Printf("Received message from %s: %s (Type: %d)", client.ID, msg, messageType)
// Echo the message back to the sender
client.SendText("You said: " + msg)
// Broadcast the message to all other *authenticated* clients
// Note: The authentication check happens *before* OnMessage if OnAuth is set.
// We still check here for clarity of what's being broadcast.
if client.GetAuth() {
server.Hub.BroadcastText(fmt.Sprintf("Client %s (authenticated) says: %s", client.ID, msg))
} else {
client.SendText("Please authenticate first to participate in broadcast!")
}
return nil // Return nil if message was processed successfully
}
// Implement a simple authentication mechanism
server.Hub.OnAuth = func(client *easyws.Client, messageType int, data []byte) (bool, error) {
authMsg := string(data)
log.Printf("Client %s attempting to authenticate with: %s", client.ID, authMsg)
// Simple secret key authentication
if authMsg == "AUTH mysecretkey123" {
client.SendText("Authentication successful!")
log.Printf("Client %s authenticated successfully.", client.ID)
return true, nil // Return true for successful authentication
}
client.SendText("Authentication failed! Please send 'AUTH <your_secret_key>'")
log.Printf("Client %s authentication failed.", client.ID)
return false, nil // Return false if authentication fails
}
// --- Advanced Customization (Optional) ---
// Customize client ID generation (e.g., from a URL query parameter)
server.SetGenerateClientID(func(r *http.Request) string {
if id := r.URL.Query().Get("user_id"); id != "" {
return "user_" + id
}
// Fallback to a timestamp-based ID if no user_id is provided
return fmt.Sprintf("guest_%d", time.Now().UnixNano())
})
// Set custom CORS check (e.g., allow specific origins for security)
server.SetCheckOrigin(func(r *http.Request) bool {
origin := r.Header.Get("Origin")
// Allow requests from specific origins
return origin == "http://localhost:3000" || origin == "https://your-frontend-domain.com"
// For local development, `return true` is often used, but be cautious in production.
})
// Start the server with default options (:8080/ws)
log.Println("Starting EasyWS server on :8080/ws")
if err := server.StartWithDefaults(); err != nil {
log.Fatalf("Server failed to start: %v", err)
}
}
To run this demo:
Save the code as
main.go
in your project.Make sure you have your
go.mod
file correctly set up.Run
go mod tidy
to ensure all dependencies are fetched.Execute
go run main.go
from your terminal.-
Open your browser's developer console and connect using JavaScript, or use a WebSocket client tool:
const ws = new WebSocket("ws://localhost:8080/ws?user_id=johndoe"); ws.onopen = () => { console.log("Connected to WebSocket server!"); ws.send("Hello there!"); // This won't be processed by OnMessage until authenticated setTimeout(() => { ws.send("AUTH mysecretkey123"); // Authenticate after a short delay }, 1000); }; ws.onmessage = (event) => { console.log("Received message:", event.data); }; ws.onclose = () => { console.log("Disconnected from WebSocket server."); }; ws.onerror = (error) => { console.error("WebSocket error:", error); };
๐ ๏ธ Core Components of EasyWS
EasyWS is built around a few key abstractions that make managing WebSockets intuitive:
Hub
: Your WebSocket Central Hub
The Hub
is the central orchestrator of your WebSocket application. It's responsible for managing all connected clients, handling their registration and unregistration, and facilitating message broadcasting. You'll primarily interact with the Hub
by setting its powerful event-driven callback functions.
-
OnConnect(client *Client) error
: Invoked after a new client successfully establishes a WebSocket connection. -
OnDisconnect(client *Client, err error)
: Called when a client's connection is closed. -
OnMessage(client *Client, messageType int, data []byte) error
: Executed when a client sends a message to the server. For unauthenticated clients, this is only called afterOnAuth
(if configured) has successfully authenticated them. -
OnAuth(client *Client, messageType int, data []byte) (bool, error)
: (Optional) If set, this callback is the first to process any incoming message from an unauthenticated client. -
BroadcastText(text string)
: Sends a string message to all currently connected clients.
Client
: The Individual Connection Representative
Each Client
object represents an individual, active WebSocket connection. It encapsulates the underlying *websocket.Conn
and provides convenient methods for interacting with that specific client.
-
ID string
: A unique identifier assigned to the client. -
IsAuth bool
: A flag indicating whether the client has been authenticated. -
UserData map[string]interface{}
: A flexible, thread-safe map where you can store any custom data pertinent to this client's session. -
SendText(text string) error
: Queues a string message to be sent to this client. -
SetAuth(isAuth bool)
/GetAuth() bool
: Safely update and retrieve the client's authentication status.
WebSocketServer
: Launch Your WebSocket Service
The WebSocketServer
is your entry point for setting up and running the WebSocket listener within your HTTP server. It handles the initial HTTP upgrade request to a WebSocket connection.
-
NewWebSocketServer()
: Creates a newWebSocketServer
instance, including a defaultHub
. -
SetCheckOrigin(checkOrigin func(r *http.Request) bool)
: Allows you to override the defaultCheckOrigin
function used bygorilla/websocket
. This is crucial for controlling Cross-Origin Resource Sharing (CORS) in production environments. -
SetGenerateClientID(generateClientID func(r *http.Request) string)
: Provides a powerful hook to define your own logic for how client IDs are generated. -
StartWithDefaults() error
: A convenient helper to start the server on the default address":8080"
and WebSocket path prefix"/ws"
.
๐ค Contribution & Collaboration
EasyWS is still evolving, and we enthusiastically welcome contributions of all forms! Whether you have ideas for new features, bug fixes, or improvements, please feel free to visit our GitHub repository: https://github.com/whoamixl/easyws to open an issue or submit a pull request.
๐ License
EasyWS is open-source software licensed under the MIT License. See the LICENSE file for more details.
What are you waiting for? Experience EasyWS now and make your Go WebSocket development simpler and more enjoyable than ever before! We believe EasyWS will become an invaluable tool for building powerful real-time applications.
What other features would you like to see in EasyWS, or what improvements do you envision for future versions? Feel free to share your thoughts in the comments!
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.