Skip to content

GoREST is a library that helps you easily create production-grade REST APIs, either from any relational database or from scratch.

License

Notifications You must be signed in to change notification settings

nicolasbonnici/gorest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

GoREST

Test Go Report Card License

πŸš€ GoREST is a Go library for building type-safe REST APIs in Go from your existing database schema or from scratch.

✨ Features

  • πŸ›  Codegen REST endpoints, resource DTOs and models for each table
  • πŸ”Ž Auto-discovery of tables, relations, columns & types
  • ⚑ Type-safe generic CRUD operations with hooks system
  • πŸ” Full DTO support with field-level control (dto tags)
  • πŸ”‘ JWT authentication with context-aware plugins
  • 🎭 Hook layer to add your business logic and override any API layer
  • 🧩 Modular plugin system that can add features, override some or all existing endpoints or even CLI commands
  • βœ… Security best practices, rate limiting, CORS and many more configurable core middleware
  • 🌐 JSON-LD support with semantic web context (@context, @type, @id)
  • πŸ”— Advanced resource deserialization with IRI and optional on demand relations
  • πŸ” Advanced serialization, filtering & ordering
  • πŸ“„ Page based pagination with Hydra collections
  • πŸ‘¨πŸ»β€πŸ’» DAL, migrations and fixtures with PostgreSQL, MySQL and SQLite engines support
  • πŸ›‘οΈ Production grade errors and processes management
  • 🐳 Docker and Kubernetes support
  • πŸ§ͺ Full test coverage with automated testing
  • πŸ’š Status check endpoint (/status)
  • πŸ“œ OpenAPI 3 spec generation in html or any format

πŸš€ Quick Start

1. Create Your Project

mkdir my-api && cd my-api
go mod init github.com/yourusername/my-api
go get github.com/nicolasbonnici/gorest@latest

2. Configure Your API

Create gorest.yaml in your project root:

server:
  scheme: "${SERVER_SCHEME:-http}"
  host: "${SERVER_HOST:-localhost}"
  port: "${SERVER_PORT:-8000}"
  environment: "${ENV:-development}"

database:
  url: "${DATABASE_URL}"

pagination:
  default_limit: "${PAGINATION_DEFAULT_LIMIT:-10}"
  max_limit: "${PAGINATION_MAX_LIMIT:-1000}"

plugins:
  - name: auth
    enabled: true
    config:
      jwt_secret: "${JWT_SECRET}"
      jwt_ttl: 900

codegen:
  output:
    models: "generated/models"
    resources: "generated/resources"
    dtos: "generated/dtos"
    openapi: "generated/openapi"
    config: "generated/config"

  enums:
    enabled: true

  auth:
    enabled: true
    defaults:
      GET: true
      POST: true
      PUT: true
      DELETE: true
    endpoints:
      - name: posts
        GET: false

Set required environment variables:

# Required (no defaults)
export DATABASE_URL="postgres://user:pass@localhost:5432/mydb?sslmode=require"
export JWT_SECRET=$(openssl rand -base64 32)

# Optional (defaults shown in gorest.yaml above)
export ENV="production"              # default: development
export SERVER_SCHEME="https"         # default: http
export SERVER_HOST="api.example.com" # default: localhost
export SERVER_PORT="8080"            # default: 8000
export PAGINATION_DEFAULT_LIMIT="20" # default: 10
export PAGINATION_MAX_LIMIT="5000"   # default: 1000

Or use a .env file (dotenv support):

# Required
DATABASE_URL=postgres://user:pass@localhost:5432/mydb?sslmode=require
JWT_SECRET=your-secret-key-here

# Optional (override defaults)
ENV=production
SERVER_SCHEME=https
SERVER_HOST=api.example.com
SERVER_PORT=8080
PAGINATION_DEFAULT_LIMIT=20
PAGINATION_MAX_LIMIT=5000

πŸ“š Full configuration documentation β†’

Environment Variable Interpolation

GoREST supports bash-style environment variable interpolation with default fallback values:

Syntax:

  • ${VAR} - Use environment variable VAR (leaves ${VAR} unchanged if not set)
  • ${VAR:-default} - Use environment variable VAR, or "default" if not set

Examples:

server:
  # Will use environment variable or fallback to default
  port: "${SERVER_PORT:-8000}"
  host: "${SERVER_HOST:-localhost}"

  # Required variable (no default)
  environment: "${ENV}"

database:
  # Complex defaults work too
  url: "${DATABASE_URL:-postgres://user:pass@localhost:5432/dev?sslmode=disable}"

pagination:
  # Numeric defaults
  default_limit: "${PAGINATION_DEFAULT_LIMIT:-10}"
  max_limit: "${PAGINATION_MAX_LIMIT:-1000}"

plugins:
  - name: auth
    config:
      # Empty default
      jwt_secret: "${JWT_SECRET:-}"

Behavior:

  • If the environment variable is set (even to an empty string), its value is used
  • If the environment variable is not set and a default is provided, the default is used
  • If the environment variable is not set and no default is provided, the original ${VAR} string remains

Note: Environment variable interpolation only works for string fields in the configuration. Integer fields like port, default_limit, and max_limit must be specified as numeric values directly in the YAML file.

3. Generate Code from Your Database

go run github.com/nicolasbonnici/gorest/cmd/codegen@latest all

4. Create Your Main Application

package main

import (
    "github.com/yourusername/my-api/generated/resources"
    "github.com/nicolasbonnici/gorest"
)

func main() {
    cfg := gorest.Config{
        ConfigPath:     ".",
        RegisterRoutes: resources.RegisterGeneratedRoutes,
    }
    gorest.Start(cfg)
}

5. Run Your API

go run main.go

Your API is now running at: ${SERVER_SCHEME}://${SERVER_HOST}:${SERVER_PORT}/

  • πŸ“š API specs: ${SERVER_SCHEME}://${SERVER_HOST}:${SERVER_PORT}/openapi
  • πŸ’š Status: ${SERVER_SCHEME}://${SERVER_HOST}:${SERVER_PORT}/status

(With default values: http://localhost:8000/)


πŸ“¦ Using GoREST as a Library

Import GoREST packages directly in your Go projects:

go get github.com/nicolasbonnici/gorest@latest

Available Packages

Package Description
crud Type-safe CRUD operations with hooks
database Multi-database abstraction
expand Relation expansion (IRI to object)
filter Query filtering & ordering
serializer JSON-LD response serialization
hooks Lifecycle hooks for business logic
plugin Plugin interfaces
pluginloader Plugin factory & loading
pagination Hydra-compliant pagination
response HTTP response helpers
migrations Database migration system
fixtures Test fixture management

Example

import (
    "github.com/gofiber/fiber/v2"
    "github.com/nicolasbonnici/gorest/database"
    "github.com/nicolasbonnici/gorest/crud"
    auth "github.com/nicolasbonnici/gorest-auth"
)

type User struct {
    ID    string `json:"id" db:"id"`
    Email string `json:"email" db:"email"`
}

func (User) TableName() string { return "users" }

func main() {
    db, _ := database.Open("postgres", "postgres://...")
    defer db.Close()

    userCRUD := crud.New[User](db)
    app := fiber.New()

    app.Get("/users", auth.RequireAuth("secret", func(c *fiber.Ctx) error {
        ctx := auth.Context(c)
        result, _ := userCRUD.GetAllPaginated(ctx, crud.PaginationOptions{Limit: 10})
        return c.JSON(result.Items)
    }))

    app.Listen(":8000")
}

πŸ“š Full API documentation on pkg.go.dev


πŸ“š Core Documentation

Configuration & Setup

Data Management

Business Logic


πŸ” Quick Examples

Filtering & Ordering

# Filter by status
GET /todos?status=active

# Multiple filters with comparison
GET /todos?status=active&priority[gte]=5

# Order results
GET /todos?order[created_at]=desc

# Combine all
GET /todos?status=active&priority[gte]=5&order[created_at]=desc&limit=10

πŸ“š Full filtering documentation β†’

Expand Relations

# IRI reference (default)
GET /todos/123
# Returns: { "user": "/users/456", ... }

# Expand to full object
GET /todos/123?expand[]=user
# Returns: { "user": { "id": "456", "name": "Alice", ... }, ... }

πŸ“š Full expansion documentation β†’

JSON-LD Support

# Regular JSON
curl -H "Accept: application/json" http://localhost:8000/todos/123

# JSON-LD with semantic context
curl -H "Accept: application/ld+json" http://localhost:8000/todos/123

πŸ“š Full JSON-LD documentation β†’


πŸ“‚ Project Structure

Generated Project

my-api/
β”œβ”€β”€ gorest.yaml              # Configuration
β”œβ”€β”€ main.go                  # Your application
└── generated/
    β”œβ”€β”€ models/              # DB models
    β”œβ”€β”€ resources/           # REST handlers
    β”œβ”€β”€ dtos/                # Data transfer objects
    └── openapi/             # OpenAPI schema

GoREST Library

gorest/
β”œβ”€β”€ crud/                    # Generic CRUD
β”œβ”€β”€ database/                # Multi-DB abstraction
β”‚   β”œβ”€β”€ postgres/
β”‚   β”œβ”€β”€ mysql/
β”‚   └── sqlite/
β”œβ”€β”€ migrations/              # Migration system
β”œβ”€β”€ fixtures/                # Fixture management
β”œβ”€β”€ expand/                  # Relation expansion
β”œβ”€β”€ filter/                  # Query filtering
β”œβ”€β”€ serializer/              # JSON-LD serialization
β”œβ”€β”€ codegen/                 # Code generation
β”œβ”€β”€ hooks/                   # Lifecycle hooks
β”œβ”€β”€ plugin/                  # Plugin interfaces
β”œβ”€β”€ pluginloader/            # Plugin loading
β”œβ”€β”€ middleware/              # Core middleware
β”œβ”€β”€ pagination/              # Hydra pagination
β”œβ”€β”€ response/                # HTTP helpers
└── cmd/codegen/             # CLI tool

πŸ›  Development Commands

# Code Generation
make codegen          # Run all code generation
make codegen-models   # Generate models only
make codegen-resources # Generate resources & DTOs only
make codegen-openapi  # Generate OpenAPI schema only

# Testing
make test-up          # Start test databases
make test-schema      # Load test schema
make test             # Run all tests
make test-coverage    # Run tests with coverage

# Benchmarking
make benchmark        # Run API performance benchmarks

πŸš€ Production Deployment

Docker

services:
  api:
    build: .
    ports: ["8000:8000"]
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - JWT_SECRET=${JWT_SECRET}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/status"]
      interval: 30s

Nginx Reverse Proxy

upstream gorest {
    server localhost:8000;
}

server {
    listen 443 ssl;
    server_name api.example.com;

    location / {
        proxy_pass http://gorest;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Kubernetes Health Checks

livenessProbe:
  httpGet:
    path: /status
    port: 8000
  initialDelaySeconds: 10
  periodSeconds: 30

πŸ”’ Security

  • Passwords: bcrypt hashing with automatic salts
  • JWT: 32+ character secrets required
  • CORS: Configurable origins
  • Rate Limiting: Configurable per-IP limits
  • SQL Injection: Parameterized queries
  • Input Validation: go-playground/validator support
  • Security Headers: X-Frame-Options, CSP, HSTS, etc.

🀝 Contributing

See CONTRIBUTING.md for guidelines.

Quick start:

git clone https://github.com/YOUR_USERNAME/gorest.git
cd gorest
make test-up && make test-schema && make test

πŸ“‹ Changelog

See CHANGELOG.md for release history.


πŸ“œ License

MIT – free to use in your projects πŸš€

About

GoREST is a library that helps you easily create production-grade REST APIs, either from any relational database or from scratch.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published