fluxo

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 9, 2026 License: MIT Imports: 9 Imported by: 0

README

Fluxo Logo

A fast, type-safe Go REST API framework inspired by FastAPI (Python)

Go Version License Built on Gin


📖 Table of Contents

Fluxo focuses on developer productivity: type‑safe generic handlers, automatic binding (JSON, query, path, form, multipart), built‑in validation, and automatic Swagger/OpenAPI—without boilerplate. Built on top of gin for maximum performance and ecosystem compatibility. Inspired by FastAPI (Python) for fast development, type‑first design, and automatic interactive docs.

Key Features

  • Type‑safe generic handlers: Handle (automatic content-type detection)
  • Automatic binding from multiple sources: json, query, path, form, multipart
  • Built‑in validation via go-playground/validator
  • Automatic Swagger/OpenAPI generation with WithSwagger(title, version)
  • Full gin integration - native gin.Context and middleware support
  • Route groups with shared middleware
  • Zero configuration, no code generation
  • Production-ready with gin's battle-tested HTTP engine

Install

go get github.com/leviantech/fluxo

Quick Start

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/leviantech/fluxo"
)

type CreateUserReq struct {
    Email string `json:"email" validate:"required,email"`
    Name  string `json:"name"  validate:"required,min=2"`
    Age   int    `json:"age"   validate:"min=18,max=120"`
}

type CreateUserRes struct {
    ID    string `json:"id"`
    Email string `json:"email"`
    Name  string `json:"name"`
    Age   int    `json:"age"`
}

func CreateUser(ctx *gin.Context, req CreateUserReq) (CreateUserRes, error) {
    return CreateUserRes{ID: "user_123", Email: req.Email, Name: req.Name, Age: req.Age}, nil
}

func main() {
    app := fluxo.New().WithSwagger("User API", "1.0.0")
    app.POST("/users", fluxo.Handle(CreateUser))
    app.Start(":8080")
}

Binding Sources

  • JSON body: json:"..."
  • Query string: form:"..." (gin convention)
  • Path params: uri:"..." (gin native)
  • Form & Multipart: form:"..."

Example with query + path:

type SearchRequest struct {
    Query string `form:"q" validate:"required"`     // Query parameter
    Limit int    `form:"limit" validate:"max=100"`  // Query parameter  
    ID    string `uri:"id" validate:"required"`     // Path parameter
}

Content‑Type Automatic Detection

The unified Handle function automatically detects content-type and binds accordingly:

// JSON (application/json) - default
app.POST("/users", fluxo.Handle(CreateUser))

// Form (application/x-www-form-urlencoded) - auto-detected
type LoginReq struct {
    Username string `form:"username" validate:"required"`
    Password string `form:"password" validate:"required"`
}
type LoginRes struct { Token string `json:"token"` }
app.POST("/login", fluxo.Handle(func(ctx *gin.Context, req LoginReq) (LoginRes, error) {
    return LoginRes{Token: "ok"}, nil
}))

// Multipart (multipart/form-data) with file upload - auto-detected
// Single file: *multipart.FileHeader; Multiple files: []*multipart.FileHeader
type UploadReq struct {
    Title string                   `form:"title" validate:"required"`
    File  *multipart.FileHeader    `form:"file"`
    Files []*multipart.FileHeader  `form:"files"`
}
type UploadRes struct { URL string `json:"url"` }
app.POST("/upload", fluxo.Handle(func(ctx *gin.Context, req UploadReq) (UploadRes, error) {
    return UploadRes{URL: "https://example.com/file"}, nil
}))

Validation

  • Use validate:"..." tags (e.g. required, email, min, max, len).
  • Validation errors return HTTP 400 with formatted messages.

Gin Integration & Middleware

Fluxo is built on top of gin, giving you access to gin's powerful ecosystem:

app := fluxo.New()

// Add gin middleware
app.Use(gin.Logger())
app.Use(gin.Recovery())

// Route groups with middleware
admin := app.Group("/admin", gin.BasicAuth(gin.Accounts{
    "admin": "password",
}))
admin.GET("/dashboard", fluxo.Handle(adminHandler))

// Access gin.Context directly in handlers
func MyHandler(ctx *gin.Context, req MyRequest) (MyResponse, error) {
    // Use any gin.Context method
    clientIP := ctx.ClientIP()
    userAgent := ctx.GetHeader("User-Agent")
    
    return MyResponse{Message: "Hello from gin!"}, nil
}

Automatic Swagger/OpenAPI

  • Enable with app.WithSwagger("Title", "Version")
  • UI: http://localhost:8080/docs
  • Spec: http://localhost:8080/openapi.json
  • Smart Content-Type Detection: Automatically detects JSON, Form, and Multipart content types
  • Proper Parameter Documentation: GET requests show query/path parameters, POST requests show request bodies
  • Full Validation Rules: All validate:"..." tags are documented in the schema
  • Complete OpenAPI 3.0 Specification: Generated automatically from your Go structs

Swagger Parameter Examples

GET with Query Parameters:

type SearchRequest struct {
    Query string `form:"q" validate:"required"`     // Shows as query param
    Limit int    `form:"limit" validate:"max=100"` // Shows as optional query param
    Page  int    `form:"page"`                     // Shows as optional query param
}

GET with Path Parameters:

type GetUserRequest struct {
    ID string `uri:"id" validate:"required"` // Shows as required path parameter
}

POST with Form Data:

type LoginRequest struct {
    Username string `form:"username" validate:"required"` // Documented in requestBody
    Password string `form:"password" validate:"required"` // Documented in requestBody
}

Performance & Ecosystem

Built on gin - one of the fastest Go web frameworks:

  • High performance HTTP router
  • Battle-tested in production environments
  • Rich middleware ecosystem - CORS, rate limiting, authentication, etc.
  • JSON serialization with optimized libraries
  • Memory efficient with sync.Pool

Why Fluxo?

  • Type-safe handlers with Go generics
  • Zero boilerplate - automatic binding and validation
  • One handler style across all content-types (JSON, Form, Multipart) with automatic detection
  • Always-in-sync API documentation
  • Gin-powered for maximum performance and ecosystem compatibility
  • Production-ready with built-in error handling and logging

License

MIT — see LICENSE.

Documentation

Overview

Copyright 2025 M Reyhan Fahlevi Licensed under the MIT License. See LICENSE for details.

Copyright 2025 M Reyhan Fahlevi Licensed under the MIT License. See LICENSE for details.

Copyright 2025 M Reyhan Fahlevi Licensed under the MIT License. See LICENSE for details.

Copyright 2025 M Reyhan Fahlevi Licensed under the MIT License. See LICENSE for details.

Copyright 2025 M Reyhan Fahlevi Licensed under the MIT License. See LICENSE for details.

Copyright 2025 M Reyhan Fahlevi Licensed under the MIT License. See LICENSE for details.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Created

func Created(w http.ResponseWriter, data interface{}) error

func Handle

func Handle[Req any, Res any](fn HandlerFunc[Req, Res]) gin.HandlerFunc

Handle creates a type-safe handler using gin's native functionality with automatic content-type detection

func JSON

func JSON(w http.ResponseWriter, status int, data interface{}) error

func Middleware added in v0.2.0

func Middleware[Req any](fn MiddlewareFunc[Req]) gin.HandlerFunc

Middleware creates a type-safe middleware using gin's native functionality with automatic content-type detection

func NoContent

func NoContent(w http.ResponseWriter) error

func RegisterTranslation added in v0.2.0

func RegisterTranslation(lang, tag, message string)

RegisterTranslation registers a translated message for a validation tag. Example: fluxo.RegisterTranslation("jp", "required", "%s は必須です")

func Success

func Success(w http.ResponseWriter, data interface{}) error

Types

type App

type App struct {
	// contains filtered or unexported fields
}

func New

func New() *App

func (*App) DELETE

func (a *App) DELETE(path string, handlers ...gin.HandlerFunc)

DELETE registers a DELETE handler

func (*App) EnableSwaggerUI

func (a *App) EnableSwaggerUI(path string)

EnableSwaggerUI serves the Swagger UI at the specified path

func (*App) GET

func (a *App) GET(path string, handlers ...gin.HandlerFunc)

func (*App) Group

func (a *App) Group(path string, middleware ...gin.HandlerFunc) *gin.RouterGroup

Group creates a route group with optional middleware

func (*App) PATCH

func (a *App) PATCH(path string, handlers ...gin.HandlerFunc)

PATCH registers a PATCH handler

func (*App) POST

func (a *App) POST(path string, handlers ...gin.HandlerFunc)

POST registers a POST handler

func (*App) PUT

func (a *App) PUT(path string, handlers ...gin.HandlerFunc)

PUT registers a PUT handler

func (*App) ServeHTTP

func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*App) Start

func (a *App) Start(addr string) error

func (*App) Use

func (a *App) Use(middleware ...gin.HandlerFunc)

Use adds middleware to the gin router

func (*App) WithSwagger

func (a *App) WithSwagger(title, version string, opts ...SwaggerOption) *App

WithSwagger enables swagger documentation generation and serves it at /docs

type Components

type Components struct {
	Schemas map[string]Schema `json:"schemas,omitempty"`
}

type Context added in v0.2.0

type Context struct {
	*gin.Context
}

func (*Context) GetAuthenticatedUser added in v0.2.0

func (c *Context) GetAuthenticatedUser(target any) error

func (*Context) Lang added in v0.2.0

func (c *Context) Lang() string

func (*Context) SetAuthenticatedUser added in v0.2.0

func (c *Context) SetAuthenticatedUser(user any)

type HTTPError

type HTTPError struct {
	Status  int    `json:"status"`
	Message string `json:"message"`
}

func BadRequest

func BadRequest(message string) HTTPError

func Forbidden

func Forbidden(message string) HTTPError

func InternalServerError

func InternalServerError(message string) HTTPError

func NewHTTPError

func NewHTTPError(status int, message string) HTTPError

func NotFound

func NotFound(message string) HTTPError

func Unauthorized

func Unauthorized(message string) HTTPError

func (HTTPError) Error

func (e HTTPError) Error() string

type HandlerFunc

type HandlerFunc[Req any, Res any] func(ctx *Context, req Req) (Res, error)

type MediaType

type MediaType struct {
	Schema Schema `json:"schema"`
}

type MiddlewareFunc added in v0.2.0

type MiddlewareFunc[Req any] func(ctx *Context, req Req) error

type OpenAPIInfo

type OpenAPIInfo struct {
	Title       string `json:"title"`
	Version     string `json:"version"`
	Description string `json:"description,omitempty"`
}

type OpenAPISpec

type OpenAPISpec struct {
	OpenAPI    string              `json:"openapi"`
	Info       OpenAPIInfo         `json:"info"`
	Paths      map[string]PathItem `json:"paths"`
	Components Components          `json:"components"`
}

type Operation

type Operation struct {
	Summary     string              `json:"summary,omitempty"`
	Description string              `json:"description,omitempty"`
	Parameters  []Parameter         `json:"parameters,omitempty"`
	RequestBody *RequestBody        `json:"requestBody,omitempty"`
	Responses   map[string]Response `json:"responses"`
}

type Parameter

type Parameter struct {
	Name        string `json:"name"`
	In          string `json:"in"`
	Description string `json:"description,omitempty"`
	Required    bool   `json:"required"`
	Schema      Schema `json:"schema"`
}

type PathItem

type PathItem struct {
	POST   *Operation `json:"post,omitempty"`
	GET    *Operation `json:"get,omitempty"`
	PUT    *Operation `json:"put,omitempty"`
	DELETE *Operation `json:"delete,omitempty"`
	PATCH  *Operation `json:"patch,omitempty"`
}

type RequestBody

type RequestBody struct {
	Description string               `json:"description,omitempty"`
	Content     map[string]MediaType `json:"content"`
	Required    bool                 `json:"required,omitempty"`
}

type Response

type Response struct {
	Description string               `json:"description"`
	Content     map[string]MediaType `json:"content,omitempty"`
}

type Schema

type Schema struct {
	Type        string            `json:"type,omitempty"`
	Properties  map[string]Schema `json:"properties,omitempty"`
	Required    []string          `json:"required,omitempty"`
	Items       *Schema           `json:"items,omitempty"`
	Format      string            `json:"format,omitempty"`
	Description string            `json:"description,omitempty"`
	Example     interface{}       `json:"example,omitempty"`
}

type SwaggerGenerator

type SwaggerGenerator struct {
	// contains filtered or unexported fields
}

func NewSwaggerGenerator

func NewSwaggerGenerator(title, version string, opts ...SwaggerOption) *SwaggerGenerator

func (*SwaggerGenerator) AddEndpoint

func (sg *SwaggerGenerator) AddEndpoint(method, path string, requestTypes []reflect.Type, responseType reflect.Type, contentType string)

func (*SwaggerGenerator) Generate

func (sg *SwaggerGenerator) Generate(handlers map[string]handlerInfo) map[string]interface{}

Generate returns the OpenAPI spec as a map (for JSON serialization)

func (*SwaggerGenerator) GetJSON

func (sg *SwaggerGenerator) GetJSON() ([]byte, error)

func (*SwaggerGenerator) GetSpec

func (sg *SwaggerGenerator) GetSpec() OpenAPISpec

func (*SwaggerGenerator) UIHandler

func (sg *SwaggerGenerator) UIHandler() gin.HandlerFunc

serveSwaggerUI serves the Swagger UI using gin

type SwaggerOption

type SwaggerOption func(*SwaggerGenerator)

func WithSwaggerDescription

func WithSwaggerDescription(desc string) SwaggerOption

func WithSwaggerPageTitle

func WithSwaggerPageTitle(title string) SwaggerOption

Directories

Path Synopsis
examples
auth_header command
basic command
db_gorm command
middleware command
todo_api command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL