Proto Packages & Runtime

Proto Packages & Runtime

Sphere extends Protobuf with specialized packages and provides a runtime layer that makes building HTTP APIs clean and efficient.

Proto Packages Overview

Sphere includes focused Protobuf packages that keep HTTP binding, errors, and custom options declarative. These annotations power Sphere’s generators and help maintain consistent, type-safe APIs.

sphere/binding

Purpose:

  • Declare where each field binds from (URI, query, body, header, form)
  • Set message/oneof defaults and auto-tags for generated structs
  • Work seamlessly with Sphere’s request binding helpers

Use when:

  • You want explicit, generator-driven request parsing rules
  • You prefer consistent struct tags without hand editing

Example:

message GetUserRequest {
  int64 user_id = 1 [(sphere.binding.location) = BINDING_LOCATION_URI];
  repeated string fields = 2 [(sphere.binding.location) = BINDING_LOCATION_QUERY];
  string auth_token = 3 [(sphere.binding.location) = BINDING_LOCATION_HEADER];
}

See API Definitions Guide for detailed examples.

sphere/errors

Purpose:

  • Define typed error enums with HTTP status, reason, and message
  • Generate helpers to wrap causes and produce uniform JSON errors
  • Map error codes to HTTP status codes automatically

Use when:

  • You need consistent error shapes across services and clients
  • You want programmatic access to status/code/reason/message

Example:

enum UserError {
  option (sphere.errors.default_status) = 500;
  
  USER_ERROR_NOT_FOUND = 1001 [(sphere.errors.options) = {
    status: 404
    reason: "USER_NOT_FOUND"
    message: "User not found"
  }];
}

See Error Handling Guide for implementation details.

sphere/options

Purpose:

  • Attach simple key/value metadata to RPC methods
  • Let generators consume options for advanced routing or transports

Use when:

  • You build adapters beyond HTTP
  • You need custom routing hints or generator options

Runtime Layer

Sphere’s HTTP runtime layer builds on Gin with small, focused helpers that keep handlers concise and error responses consistent.

Core Components

Response Wrappers:

  • WithJson[T]: Wraps a handler returning (T, error) and serializes responses to DataResponse[T]
  • AbortWithJsonError: Normalizes errors to ErrorResponse with proper HTTP status codes

Request Binding:

  • ShouldBindJSON/Uri/Query: Thin wrappers to bind request payloads with validation
  • Integrates with sphere/binding annotations for declarative binding

Server Features:

  • Docs Server: Auxiliary HTTP server for Swagger UI
  • Debug Server: Diagnostics and health check endpoints
  • Middleware Support: Request logging, CORS, authentication

Typical Request Flow

  1. Protobuf + protoc-gen-sphere generate handler plumbing
  2. Request arrives at generated HTTP handler
  3. Handler binds request data to generated structs (using sphere/binding)
  4. Service method executes business logic, returns data or typed error
  5. Runtime wrapper transforms result to stable JSON envelope
  6. Response serialized with proper headers and HTTP status

Example Handler

// Generated by protoc-gen-sphere
func (s *UserHandler) GetUser(ctx *gin.Context) {
    req := &GetUserRequest{}
    if err := ctx.ShouldBindUri(req); err != nil {
        s.AbortWithJsonError(ctx, err)
        return
    }
    
    data, err := s.service.GetUser(ctx, req)
    if err != nil {
        s.AbortWithJsonError(ctx, err)
        return
    }
    
    ctx.JSON(http.StatusOK, &DataResponse{Data: data})
}

Extensibility

  • Custom Router Types: Swap Gin for Fiber, Echo, or Hertz via protoc-gen-sphere flags
  • Context Customization: Use custom context types instead of *gin.Context
  • Response Envelope: Define your own data/error response structures
  • Error Parser: Provide custom error handling to merge validation or domain-specific errors

This flexibility allows Sphere to work with your existing infrastructure while providing sensible defaults for new projects.

Last updated on