Skip to content
/ rocco Public

Type-safe HTTP framework for Go with automatic OpenAPI generation

License

Notifications You must be signed in to change notification settings

zoobzio/rocco

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rocco

CI Status codecov Go Report Card CodeQL Go Reference License Go Version Release

Type-safe HTTP framework for Go with automatic OpenAPI generation.

Define your request and response types, wire up handlers, and get a fully-documented API with validation baked in.

Types Become Endpoints

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"`
}

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
    },
).WithErrors(rocco.ErrBadRequest, rocco.ErrConflict)

Your types define the contract. Rocco handles validation, serialization, error responses, and OpenAPI schema generation — all derived from the same source of truth.

Install

go get github.com/zoobzio/rocco

Requires Go 1.24+.

Quick Start

package main

import (
    "fmt"

    "github.com/zoobzio/openapi"
    "github.com/zoobzio/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()

    // Configure OpenAPI metadata
    engine.WithOpenAPIInfo(openapi.Info{
        Title:   "User API",
        Version: "1.0.0",
    })

    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
        },
    ).
        WithSummary("Create a new user").
        WithTags("users").
        WithSuccessStatus(201).
        WithErrors(rocco.ErrBadRequest, rocco.ErrUnprocessableEntity)

    engine.WithHandlers(handler)

    // OpenAPI spec at /openapi, interactive docs at /docs
    fmt.Println("Server listening on :8080")
    engine.Start(rocco.HostAll, 8080)
}

Capabilities

Feature Description Docs
Type-Safe Handlers Generic handlers with compile-time type checking Handlers
Server-Sent Events Built-in SSE support for real-time streaming Streaming
Automatic OpenAPI Generate OpenAPI 3.1.0 specs from your types OpenAPI
Request Validation Struct tag validation with detailed error responses Concepts
Sentinel Errors Typed HTTP errors with OpenAPI schema generation Errors
Lifecycle Events Observable signals for logging, metrics, tracing Events

Why rocco?

  • Type-safe — Generic handlers catch errors at compile time, not runtime
  • Self-documenting — OpenAPI specs generated from the same types that validate requests
  • Explicit — No magic, no hidden behaviors, no struct tag DSLs for routing
  • Chi-powered — Built on the battle-tested Chi router with full middleware compatibility
  • Observable — Lifecycle events via capitan for metrics and tracing
  • Streaming-native — First-class SSE support with typed event streams

Contract-First by Default

Rocco enables a pattern: define types once, derive everything else.

Your request and response structs become the single source of truth. From them, rocco derives validation rules, OpenAPI schemas, error contracts, and documentation.

Define a type:

type CreateOrderInput struct {
    CustomerID string  `json:"customer_id" validate:"required,uuid4" description:"Customer UUID"`
    Items      []Item  `json:"items" validate:"required,min=1" description:"Order line items"`
    Total      float64 `json:"total" validate:"required,gt=0" description:"Order total in USD"`
}

Get an OpenAPI schema:

CreateOrderInput:
  type: object
  required: [customer_id, items, total]
  properties:
    customer_id:
      type: string
      format: uuid
      description: Customer UUID
    items:
      type: array
      minItems: 1
      description: Order line items
      items:
        $ref: '#/components/schemas/Item'
    total:
      type: number
      exclusiveMinimum: 0
      description: Order total in USD

Get consistent validation errors:

{
  "code": "VALIDATION_FAILED",
  "message": "validation failed",
  "details": {
    "fields": [
      {"field": "customer_id", "message": "must be a valid UUID"},
      {"field": "total", "message": "must be greater than 0"}
    ]
  }
}

No separate schema files. No manual sync between code and docs. The types ARE the contract.

Documentation

  • Overview — Design philosophy and architecture

Learn

Guides

Cookbook

Reference

  • API — Complete function documentation
  • Errors — All sentinel errors and detail types
  • Events — Lifecycle signals and field keys

Contributing

See CONTRIBUTING.md for guidelines.

License

MIT License — see LICENSE for details.

About

Type-safe HTTP framework for Go with automatic OpenAPI generation

Resources

License

Contributing

Security policy

Stars

Watchers

Forks