https://github.com/xraph/steel
Not just yet another Go Lang Router
https://github.com/xraph/steel
go
Last synced: 3 months ago
JSON representation
Not just yet another Go Lang Router
- Host: GitHub
- URL: https://github.com/xraph/steel
- Owner: xraph
- Created: 2025-07-08T01:05:21.000Z (12 months ago)
- Default Branch: main
- Last Pushed: 2025-07-10T21:03:16.000Z (12 months ago)
- Last Synced: 2025-07-11T10:53:48.105Z (12 months ago)
- Topics: go
- Language: Go
- Homepage: https://steel.xraph.com
- Size: 1.5 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
Awesome Lists containing this project
README
# Steel Router ๐
A high-performance HTTP router for Go with automatic OpenAPI documentation, WebSocket/SSE support, and comprehensive testing utilities.
[](https://golang.org)
[](LICENSE)
[](https://goreportcard.com/report/github.com/xraph/steel)
## โจ Features
- **๐ High Performance**: Fast radix tree-based routing with zero allocations for parameter extraction
- **๐ Automatic OpenAPI**: Generate complete OpenAPI 3.0 documentation from your handlers
- **๐ Real-time**: Built-in WebSocket and Server-Sent Events (SSE) support with AsyncAPI docs
- **๐ฏ Type-Safe**: Opinionated handlers with automatic parameter binding and validation
- **๐งช Testing**: Comprehensive testing utilities with request builders and assertions
- **โก Middleware**: Flexible middleware system with built-in recovery, logging, and timeout
- **๐จ Multiple Docs**: Support for Swagger UI, ReDoc, Scalar, and Stoplight Elements
- **๐ง Developer-Friendly**: Rich debugging tools and development utilities
## ๐ฆ Installation
```bash
go get github.com/xraph/steel
```
## ๐ Quick Start
```go
package main
import (
"log"
"net/http"
"github.com/xraph/steel"
)
type User struct {
ID int `json:"id" path:"id" description:"User ID"`
Name string `json:"name" query:"name" description:"User name"`
}
type UserResponse struct {
ID int `json:"id" description:"User ID"`
Name string `json:"name" description:"User name"`
Created bool `json:"created" description:"Whether user was created"`
}
func main() {
r := steel.NewRouter()
// Add middleware
r.Use(steel.Logger, steel.Recoverer)
// Opinionated handler with automatic OpenAPI generation
r.OpinionatedGET("/users/:id", func(ctx *steel.Context, req User) (*UserResponse, error) {
return &UserResponse{
ID: req.ID,
Name: req.Name,
Created: false,
}, nil
}, steel.WithSummary("Get User"), steel.WithTags("users"))
// Enable automatic OpenAPI documentation
r.EnableOpenAPI()
log.Println("Server starting on :8080")
log.Println("API docs available at http://localhost:8080/openapi/docs")
log.Fatal(http.ListenAndServe(":8080", r))
}
```
Visit `http://localhost:8080/openapi/docs` to see your automatically generated API documentation!
## ๐ฏ Key Features
### Opinionated Handlers
Steel's opinionated handlers provide automatic parameter binding, validation, and OpenAPI generation:
```go
type CreateUserRequest struct {
Name string `json:"name" body:"body" description:"User name"`
Email string `json:"email" body:"body" description:"User email"`
Age int `query:"age" description:"User age"`
}
r.OpinionatedPOST("/users", func(ctx *router.Context, req CreateUserRequest) (*UserResponse, error) {
// Request automatically bound from JSON body and query parameters
if req.Age < 18 {
return nil, router.BadRequest("User must be 18 or older")
}
// Your business logic here
return &UserResponse{ID: 123, Name: req.Name}, nil
}, router.WithSummary("Create User"))
```
### Real-time Communication
Built-in WebSocket and SSE support with AsyncAPI documentation:
```go
// WebSocket handler
r.WebSocket("/ws/chat", func(conn *router.WSConnection, message ChatMessage) (*ChatResponse, error) {
return &ChatResponse{Reply: "Echo: " + message.Text}, nil
}, router.WithAsyncSummary("Chat WebSocket"))
// Server-Sent Events
r.SSE("/events/:userId", func(conn *router.SSEConnection, params EventParams) error {
return conn.SendMessage(router.SSEMessage{
Event: "notification",
Data: map[string]interface{}{"userId": params.UserID},
})
}, router.WithAsyncSummary("User Events"))
// Enable AsyncAPI documentation
r.EnableAsyncAPI()
```
### Comprehensive Error Handling
Rich error types with automatic OpenAPI documentation:
```go
r.OpinionatedGET("/users/:id", func(ctx *router.Context, req GetUserRequest) (*User, error) {
user, exists := database.GetUser(req.ID)
if !exists {
return nil, router.NotFound("User")
}
if !user.Active {
return nil, router.Forbidden("User account is deactivated")
}
return user, nil
})
```
### Testing Made Easy
Built-in testing utilities for comprehensive API testing:
```go
func TestUserAPI(t *testing.T) {
router := setupTestRouter()
// Test user creation
response := router.NewRequest("POST", "/users").
WithJSON(map[string]interface{}{
"name": "John Doe",
"email": "john@example.com",
}).
Execute(router)
router.AssertResponse(t, response).
Status(http.StatusCreated).
IsJSON().
JSON("name", "John Doe")
}
```
## ๐ Documentation
### Basic Routing
```go
r := router.NewRouter()
// HTTP methods
r.GET("/", handler)
r.POST("/users", handler)
r.PUT("/users/:id", handler)
r.DELETE("/users/:id", handler)
// Path parameters
r.GET("/users/:id/posts/:postId", handler)
// Wildcards
r.GET("/static/*", handler)
// Route groups
r.Route("/api/v1", func(r router.Router) {
r.GET("/users", getUsersHandler)
r.POST("/users", createUserHandler)
})
```
### Middleware
```go
// Built-in middleware
r.Use(router.Logger)
r.Use(router.Recoverer)
r.Use(router.Timeout(30 * time.Second))
// Custom middleware
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// Your middleware logic
next.ServeHTTP(w, req)
})
})
```
### Parameter Binding Tags
| Tag | Description | Example |
|-----|-------------|---------|
| `path` | URL path parameter | `ID int \`path:"id"\`` |
| `query` | Query parameter | `Limit int \`query:"limit"\`` |
| `header` | HTTP header | `Auth string \`header:"Authorization"\`` |
| `body` | JSON body field | `Data string \`body:"body"\`` |
| `json` | JSON field name | `Name string \`json:"name"\`` |
| `description` | OpenAPI description | `ID int \`description:"User ID"\`` |
## ๐ง Advanced Features
### Custom Response Types
```go
r.OpinionatedPOST("/users", func(ctx *router.Context, req CreateUserRequest) (*router.APIResponse, error) {
user := createUser(req)
return router.Created(user).
WithHeader("Location", fmt.Sprintf("/users/%d", user.ID)), nil
})
```
### Validation Errors
```go
func validateUser(req CreateUserRequest) error {
fields := []router.FieldError{}
if req.Email == "" {
fields = append(fields, router.NewFieldError("email", "Email is required", req.Email, "REQUIRED"))
}
if len(fields) > 0 {
return router.UnprocessableEntity("Validation failed", fields...)
}
return nil
}
```
### Connection Management
```go
// Get connection manager for WebSocket/SSE connections
cm := router.ConnectionManager()
// Broadcast to all WebSocket connections
cm.BroadcastWS(router.WSMessage{
Type: "notification",
Payload: "Hello everyone!",
})
// Broadcast to all SSE connections
cm.BroadcastSSE(router.SSEMessage{
Event: "update",
Data: "System maintenance in 5 minutes",
})
```
## ๐ Documentation Viewers
Steel supports multiple documentation viewers out of the box:
- **Swagger UI**: Interactive API documentation
- **ReDoc**: Beautiful, responsive documentation
- **Scalar**: Modern documentation with excellent UX
- **Stoplight Elements**: Comprehensive documentation platform
Access them at:
- `/openapi/docs` - Documentation hub
- `/openapi/swagger` - Swagger UI
- `/openapi/redoc` - ReDoc
- `/openapi/scalar` - Scalar
- `/openapi/spotlight` - Stoplight Elements
- `/asyncapi/docs` - AsyncAPI documentation
## ๐งช Testing
### Load Testing
```go
config := router.LoadTestConfig{
Concurrency: 10,
Requests: 1000,
Timeout: 30 * time.Second,
Paths: []string{"/api/users", "/api/posts"},
}
result := router.RunLoadTest(router, config)
fmt.Printf("RPS: %.2f, Success: %d%%\n",
result.RequestsPerSecond,
(result.SuccessRequests*100)/result.TotalRequests)
```
### Benchmark Testing
```go
func BenchmarkUserAPI(b *testing.B) {
setup := router.NewBenchmarkSetup().
AddStaticRoutes(100).
AddParameterRoutes(50)
router := setup.Setup()
b.ResetTimer()
for i := 0; i < b.N; i++ {
// Your benchmark code
}
}
```
## ๐ Integration Examples
### With Database (GORM)
```go
type UserService struct {
db *gorm.DB
}
func (s *UserService) GetUser(ctx *router.Context, req GetUserRequest) (*User, error) {
var user User
if err := s.db.First(&user, req.ID).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, router.NotFound("User")
}
return nil, router.InternalServerError("Database error")
}
return &user, nil
}
// Register handler
r.OpinionatedGET("/users/:id", userService.GetUser)
```
### With Validation (go-playground/validator)
```go
type CreateUserRequest struct {
Name string `json:"name" validate:"required,min=2" description:"User name"`
Email string `json:"email" validate:"required,email" description:"User email"`
Age int `json:"age" validate:"min=18" description:"User age"`
}
func createUserWithValidation(ctx *router.Context, req CreateUserRequest) (*User, error) {
if err := validator.New().Struct(req); err != nil {
var fields []router.FieldError
for _, err := range err.(validator.ValidationErrors) {
fields = append(fields, router.NewFieldError(
err.Field(),
err.Error(),
err.Value(),
err.Tag(),
))
}
return nil, router.UnprocessableEntity("Validation failed", fields...)
}
// Create user...
return &User{}, nil
}
```
## ๐๏ธ Architecture
Steel is built with performance and developer experience in mind:
- **Radix Tree Routing**: Efficient O(log n) route matching
- **Zero Allocations**: Parameter extraction without memory allocations
- **Reflection-Based Binding**: Automatic request binding using Go reflection
- **OpenAPI Generation**: Real-time schema generation from Go types
- **Connection Pooling**: Efficient parameter object pooling
- **Middleware Chain**: Flexible middleware composition
- **Error Handling**: Structured error responses with automatic documentation
## ๐ค Contributing
We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## ๐ License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## ๐ Acknowledgments
- Inspired by [Chi](https://github.com/go-chi/chi) and [Gin](https://github.com/gin-gonic/gin)
- OpenAPI 3.0 specification
- AsyncAPI 2.6 specification
- Go community for amazing ecosystem
## ๐ Support
- ๐ [Documentation](https://steel.xraph.com)
- ๐ [Report Bug](https://github.com/xraph/steel/issues)
- ๐ก [Request Feature](https://github.com/xraph/steel/issues)
- ๐ฌ [Discussions](https://github.com/xraph/steel/discussions)
---
**Made with โค๏ธ by the XRaph team**