Rocco
Type-safe HTTP framework for Go with automatic OpenAPI generation.
Rocco provides a declarative, type-safe approach to building HTTP APIs. Define your handlers with generic types, and rocco handles request parsing, error responses, and OpenAPI documentation automatically.
Why Rocco?
Building HTTP APIs in Go typically involves repetitive boilerplate: parsing request bodies, validating inputs, mapping errors to status codes, and keeping documentation in sync. Rocco eliminates this friction through a type-driven design.
┌─────────────────────────────────────────────────────────────┐
│ Your Code │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ type Input struct { Name string `validate:"req"` }│ │
│ │ type Output struct { ID string } │ │
│ │ func Handle(req) (Output, error) { ... } │ │
│ └─────────────────────────────────────────────────────┘ │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Rocco │
│ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │
│ │ Parse │→ │ Validate │→ │ Execute Handler │ │
│ │ JSON │ │ Input │ │ + Marshal Output │ │
│ └────────────┘ └────────────┘ └────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ OpenAPI Spec Generation │ │
│ │ (schemas, params, errors from your types) │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Design Principles
Type Safety First
Every handler declares its input and output types. The compiler catches mismatches, and the framework uses these types to generate accurate OpenAPI schemas.
// Compile-time type safety
handler := rocco.NewHandler[CreateUserInput, UserOutput](...)
// req.Body is CreateUserInput, not any or interface{}
func(req *rocco.Request[CreateUserInput]) (UserOutput, error) {
return UserOutput{Name: req.Body.Name}, nil
}
Explicit Over Magic
No hidden configuration files, no reflection-based routing, no implicit middleware. Every behavior is declared in code.
handler.
WithPathParams("id"). // Explicit path params
WithQueryParams("page", "limit"). // Explicit query params
WithErrors(ErrNotFound). // Explicit error declarations
WithScopes("users:read") // Explicit authorization
Documentation as Code
OpenAPI schemas are generated from your types. When you change a struct field, the documentation updates automatically. No manual syncing required.
Errors as Values
Error handling uses sentinel errors with structured responses. Declare which errors a handler may return, and rocco enforces this at runtime while generating accurate error schemas.
Core Capabilities
Typed Handlers
Generic handlers with compile-time type checking for request bodies and responses.
Type-Based Validation
Types that implement the Validatable interface are automatically validated. Use any validation library (like go-playground/validator) or write custom logic. The validate struct tag is parsed for OpenAPI schema generation.
OpenAPI Generation
Full OpenAPI 3.1.0 specs generated from your code, including request/response schemas, parameters, and error responses.
Identity & Authorization
Built-in support for identity extraction, scope-based authorization, role-based access control, and usage limits.
Structured Errors
Typed error responses with codes, messages, and optional details. Custom errors with typed detail schemas for comprehensive API contracts.
Observability
Event emission via capitan for request lifecycle, handler execution, and error tracking.
Stdlib Router
Built on Go 1.22+ stdlib http.ServeMux with native path parameter support. Zero external router dependencies.
Quick Example
package main
import "github.com/zoobz-io/rocco"
type CreateUserInput struct {
Name string `json:"name" validate:"required,min=2"`
Email string `json:"email" validate:"required,email"`
}
type UserOutput struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func main() {
engine := rocco.NewEngine()
handler := rocco.NewHandler[CreateUserInput, UserOutput](
"create-user",
"POST",
"/users",
func(req *rocco.Request[CreateUserInput]) (UserOutput, error) {
return UserOutput{
ID: "usr_123",
Name: req.Body.Name,
Email: req.Body.Email,
}, nil
},
).WithSuccessStatus(201)
engine.WithHandlers(handler)
engine.Start(rocco.HostAll, 8080)
}
Next Steps
- Quickstart - Get running in 5 minutes
- Core Concepts - Understand the building blocks
- Architecture - How rocco works internally
See Also
- Handler Guide - Deep dive into handler configuration
- Error Handling - Error patterns and custom errors
- API Reference - Complete API documentation