KSMUX is a fast and lightweight HTTP router and web framework for Go, featuring built-in WebSocket support. It is designed to be simple yet powerful, providing a range of features to build modern web applications.
- Fast HTTP Routing: Supports URL parameters and wildcards for flexible routing.
- WebSocket Support: Built-in support for WebSocket connections with optional compression.
- Middleware Support: Easily add middleware for request handling.
- Static File Serving: Serve static files from local or embedded sources.
- Template Rendering: Render HTML templates with custom functions.
- GZIP Compression: Automatic GZIP compression for responses.
- Basic Authentication: Simple basic authentication middleware.
- CORS Support: Cross-Origin Resource Sharing (CORS) middleware.
- Request Logging: Log incoming requests with customizable logging.
- Rate Limiting: Limit the rate of incoming requests.
- Proxy Support: Reverse proxy capabilities.
- Load Balancer: powerful load balancer that support middlewares as code for each backend
- Server-Sent Events (SSE): Support for server-sent events.
- Built-in Tracing: Distributed tracing with OpenTelemetry-compatible backends.
To install KSMUX, use the following command:
go get github.com/kamalshkeir/ksmux@latest
KSMUX includes built-in distributed tracing capabilities that can export to OpenTelemetry-compatible backends:
// Enable tracing with default Jaeger endpoint
ksmux.ConfigureExport("", ksmux.ExportTypeJaeger)
// Or use Tempo
ksmux.ConfigureExport(ksmux.DefaultTempoEndpoint, ksmux.ExportTypeTempo)
// Enable tracing with optional custom handler
ksmux.EnableTracing(&CustomTraceHandler{})
// Add tracing middleware to capture all requests
app.Use(ksmux.TracingMiddleware)
// Manual span creation
app.Get("/api", func(c *ksmux.Context) {
// Create a span
span, ctx := ksmux.StartSpan(c.Request.Context(), "operation-name")
defer span.End()
// Add tags
span.SetTag("key", "value")
// Set error if needed
span.SetError(err)
// Set status code
span.SetStatusCode(200)
// Use context for propagation
doWork(ctx)
})
type CustomTraceHandler struct{}
func (h *CustomTraceHandler) HandleTrace(span *ksmux.Span) {
// Access span information
fmt.Printf("Trace: %s, Span: %s, Operation: %s\n",
span.TraceID(), span.SpanID(), span.Name())
}
The tracer can export to any OpenTelemetry-compatible backend. Pre-configured support for:
- Jaeger (default)
- Grafana Tempo
Default endpoints:
// Add paths to ignore in tracing
ksmux.IgnoreTracingEndpoints("/health", "/metrics")
By default, the tracer keeps the last 1000 traces in memory. You can adjust this limit:
// Set maximum number of traces to keep in memory
ksmux.SetMaxTraces(500) // Keep only the last 500 traces
When the limit is reached, the oldest trace will be removed when a new one is added.
Here's a simple example to get started with KSMUX:
package main
import "github.com/kamalshkeir/ksmux"
func main() {
// Create a new router
router := ksmux.New()
// Define a route
router.Get("/", func(c *ksmux.Context) {
c.Text("Hello World!")
})
// Start the server
router.Run(":8080")
}
KSMUX supports various routing patterns:
// Basic routes
router.Get("/users", handleUsers)
router.Post("/users", createUser)
router.Put("/users/:id", updateUser)
router.Delete("/users/:id", deleteUser)
// URL parameters
router.Get("/users/:id", func(c *ksmux.Context) {
id := c.Param("id")
c.Json(map[string]string{"id": id})
})
// Wildcards
router.Get("/files/*filepath", serveFiles)
The Context
object provides many useful methods for handling requests and responses:
// Response methods
c.Text("Hello") // Send plain text
c.Json(data) // Send JSON
c.JsonIndent(data) // Send indented JSON
c.Html("template.html", data) // Render HTML template
c.Stream("message") // Server-sent events
c.Download(bytes, "file.txt") // Force download
c.Redirect("/new-path") // HTTP redirect
// Request data
c.Param("id") // URL parameter
c.QueryParam("q") // Query parameter
c.BodyJson() // Parse JSON body
c.BodyStruct(&data) // Parse body into struct
c.GetCookie("session") // Get cookie value
c.SetCookie("session", "value") // Set cookie
// Headers
c.SetHeader("X-Custom", "value")
c.AddHeader("X-Custom", "value")
c.SetStatus(200)
// Files
c.SaveFile(fileHeader, "path") // Save uploaded file
c.ServeFile("image/png", "path") // Serve local file
Add middleware globally or to specific routes:
// Global middleware
router.Use(ksmux.Logs())
router.Use(ksmux.Gzip())
router.Use(ksmux.Cors())
// Route-specific middleware
router.Get("/admin", adminOnly(handleAdmin))
func adminOnly(next ksmux.Handler) ksmux.Handler {
return func(c *ksmux.Context) {
if !isAdmin(c) {
c.Status(403).Text("Forbidden")
return
}
next(c)
}
}
KSMUX provides built-in support for WebSocket connections:
router.Get("/ws", func(c *ksmux.Context) {
// Upgrade HTTP connection to WebSocket
conn, err := c.UpgradeConnection()
if err != nil {
return
}
// Handle WebSocket messages
for {
messageType, p, err := conn.ReadMessage()
if err != nil {
return
}
// Echo the message back
err = conn.WriteMessage(messageType, p)
if err != nil {
return
}
}
})
Render HTML templates with custom functions:
// Load templates
router.LocalTemplates("templates/")
// or
router.EmbededTemplates(embededFS, "templates/")
// Add custom template functions
router.NewTemplateFunc("upper", strings.ToUpper)
// Render template
router.Get("/", func(c *ksmux.Context) {
c.Html("index.html", map[string]any{
"title": "Home",
"user": user,
})
})
Serve static files from local or embedded sources:
// Serve local directory
router.LocalStatics("static/", "/static")
// Serve embedded files
router.EmbededStatics(embededFS, "static/", "/static")
func main() {
app := ksmux.New()
err := app.LocalStatics("assets", "/static")
lg.CheckError(err)
err = app.LocalTemplates("temps")
lg.CheckError(err)
// Setup load balancer for /api path, distributing requests between two backend servers
err = app.LoadBalancer("/",
ksmux.BackendOpt{
Url: "localhost:8081",
Middlewares: []ksmux.Handler{
func(c *ksmux.Context) {
fmt.Println("from middleware 8081")
},
},
},
ksmux.BackendOpt{
Url: "localhost:8082",
},
)
lg.CheckError(err)
app.Run(":9313")
}
Configure server settings and cookies:
// Server timeouts
ksmux.READ_TIMEOUT = 10 * time.Second
ksmux.WRITE_TIMEOUT = 10 * time.Second
ksmux.IDLE_TIMEOUT = 30 * time.Second
// Cookie settings
ksmux.COOKIES_HttpOnly = true
ksmux.COOKIES_SECURE = true
ksmux.COOKIES_SameSite = http.SameSiteStrictMode
ksmux.COOKIES_Expires = 24 * time.Hour
BSD 3-Clause License. See LICENSE for details.
Contributions are welcome! Please feel free to submit a Pull Request.
Kamal SHKEIR
If you find this project helpful, please give it a ⭐️