Skip to content

Labbs/fiber-oapi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fiber OpenAPI

A Go library that extends Fiber to add automatic OpenAPI documentation generation with built-in validation, authentication, and role-based access control.

Features

  • Complete HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD) with automatic validation
  • Group support with OpenAPI methods available on both app and groups
  • Unified API with interface-based approach for seamless app/group usage
  • Powerful validation via github.com/go-playground/validator/v10
  • Multiple authentication schemes: Bearer, Basic Auth, API Key, AWS SigV4
  • Declarative role-based access control with OR/AND semantics
  • Custom error handlers for validation and authentication errors
  • Per-route security overrides and public routes
  • Type safety with Go generics
  • OpenAPI 3.0 documentation in JSON and YAML formats
  • Redoc documentation UI for modern, responsive API documentation
  • OpenAPI extensions (x-required-roles, x-required-roles-mode)
  • Conditional auth middleware for flexible authentication strategies

Installation

go get github.com/labbs/fiber-oapi/v3

Upgrading from v1.x? v3 tracks Fiber v3 and requires Go 1.26+. Breaking changes:

  • Handlers now take fiber.Ctx (struct value) instead of *fiber.Ctx.
  • The path-parameter struct tag is now uri: instead of path: (Fiber v3 binder convention). Query and header tags are unchanged.
  • The default validation/parse error response uses a new ErrorEnvelope shape (one entry per failing field, response_context.response_id mirrored from X-Request-Id) and validation errors are returned as 422 Unprocessable Entity instead of 400. See Error responses.

Quick Start

package main

import (
    "github.com/gofiber/fiber/v3"
    fiberoapi "github.com/labbs/fiber-oapi/v3"
)

func main() {
    app := fiber.New()
    oapi := fiberoapi.New(app)

    fiberoapi.Get(oapi, "/hello/:name",
        func(c fiber.Ctx, input struct {
            Name string `uri:"name" validate:"required,min=2"`
        }) (fiber.Map, *fiberoapi.ErrorResponse) {
            return fiber.Map{"message": "Hello " + input.Name}, nil
        },
        fiberoapi.OpenAPIOptions{
            Summary: "Say hello",
            Tags:    []string{"greeting"},
        })

    // Docs at /docs, spec at /openapi.json and /openapi.yaml
    app.Listen(":3000")
}

Configuration

type Config struct {
    EnableValidation       bool                      // Enable input validation (default: true)
    EnableOpenAPIDocs      bool                      // Enable automatic docs setup (default: true)
    EnableAuthorization    bool                      // Enable auth validation (default: false)
    OpenAPIDocsPath        string                    // Path for docs UI (default: "/docs")
    OpenAPIJSONPath        string                    // Path for JSON spec (default: "/openapi.json")
    OpenAPIYamlPath        string                    // Path for YAML spec (default: "/openapi.yaml")
    OpenAPITitle           string                    // Spec title (default: "Fiber OpenAPI")
    OpenAPIDescription     string                    // Spec description (default: "API documentation generated by fiber-oapi")
    OpenAPIVersion         string                    // Spec version (default: "1.0.0")
    AuthService            AuthorizationService      // Service for handling auth
    SecuritySchemes        map[string]SecurityScheme // OpenAPI security schemes
    DefaultSecurity        []map[string][]string     // Default security requirements
    ValidationErrorHandler ValidationErrorHandler    // Custom handler for validation errors
    AuthErrorHandler       AuthErrorHandler          // Custom handler for auth errors (401/403/5xx)
}

Default config when none is provided:

  • Validation: enabled
  • Documentation: enabled
  • Authorization: disabled
  • Docs path: /docs
  • JSON spec path: /openapi.json
  • YAML spec path: /openapi.yaml
  • Spec title: Fiber OpenAPI
  • Spec description: API documentation generated by fiber-oapi
  • Spec version: 1.0.0

Override the info block of the generated spec via Config:

fiberoapi.New(app, fiberoapi.Config{
    OpenAPITitle:       "My Service",
    OpenAPIDescription: "Public REST API for the My Service platform",
    OpenAPIVersion:     "2024.10.1",
})

HTTP Methods

All methods work with both the main app and groups:

fiberoapi.Get(router, path, handler, options)
fiberoapi.Post(router, path, handler, options)
fiberoapi.Put(router, path, handler, options)
fiberoapi.Patch(router, path, handler, options)
fiberoapi.Delete(router, path, handler, options)
fiberoapi.Head(router, path, handler, options)
fiberoapi.Method(method, router, path, handler, options) // Custom HTTP method

Parameter Types

type MyInput struct {
    ID     string `uri:"id" validate:"required"`           // Path parameter
    Filter string `query:"filter" validate:"omitempty"`      // Query parameter
    Auth   string `header:"Authorization"`                   // Header parameter
    Title  string `json:"title" validate:"required,min=1"`   // JSON body field
}

Special tags:

  • openapi:"-" — Exclude a field from the OpenAPI schema (the field still works in the handler)
  • description:"text" — Add a description to the field in the spec
  • resource:"document" — Mark field as a resource identifier for dynamic authorization
  • action:"write" — Specify the action for resource access checks

Groups

app := fiber.New()
oapi := fiberoapi.New(app)

v1 := fiberoapi.Group(oapi, "/api/v1")
users := fiberoapi.Group(v1, "/users")

// OpenAPI methods on groups
fiberoapi.Get(users, "/:id", getUser, options)   // Registers as GET /api/v1/users/{id}
fiberoapi.Post(users, "/", createUser, options)

// Standard Fiber middleware still works
v1.Use(authMiddleware)

Validation

Uses validator/v10. Common tags:

type Input struct {
    Name   string `json:"name" validate:"required,min=3,max=50"`
    Email  string `json:"email" validate:"required,email"`
    Age    int    `json:"age" validate:"min=13,max=120"`
    Role   string `json:"role" validate:"oneof=admin user guest"`
    Tags   []string `json:"tags" validate:"dive,min=1"`
}

Error responses

When the default validation / parse handler runs (i.e. no custom ValidationErrorHandler is configured), errors are returned as a structured envelope with one entry per failing field:

{
  "errors": [
    {
      "type": "validation_error",
      "code": 422,
      "loc": ["body", "workspaceId"],
      "field": "workspaceId",
      "msg": "field 'workspaceId' must be at least 11",
      "constraint": "min=11"
    },
    {
      "type": "validation_error",
      "code": 422,
      "loc": ["body", "nested", "slug"],
      "field": "slug",
      "msg": "field 'slug' must be at least 2",
      "constraint": "min=2"
    }
  ],
  "response_context": {
    "response_id": "bf0e9029-576b-42e8-84f9-ad0622972f50"
  }
}

Status codes used by the default handler:

Code Category Entry type
422 Failed validation rules validation_error
400 JSON parse / type mismatch type_error, parse_error
401 / 403 Authentication / authorization authentication_error, authorization_error

response_context.response_id mirrors the X-Request-Id request header when present (no UUID is generated by the lib — pair with a requestid middleware if you want one). The loc array starts with the request source (body, path, query, header) followed by the field path using JSON / URI / header tag names.

By default the offending value is omitted to avoid leaking secrets (e.g. a password failing min=8 validation). Opt in via Config.IncludeInvalidValueInErrors: true if you want each entry to carry a value field.

The OpenAPI spec exposes ErrorEnvelope / ValidationErrorEntry / ResponseContext under components.schemas and adds a 422 response with a realistic example to every operation, plus a 400 example for body-carrying methods. Routes that declare a non-empty TError and no per-status OpenAPIOptions.Errors keep their domain shape under the catch-all 4XX response — as soon as the route declares explicit Errors entries the catch-all is suppressed and only the enumerated status codes appear in the spec.

Hiding a route from the spec entirely

Some routes — internal admin endpoints, debug handlers, in-progress features — serve traffic but shouldn't appear in the published spec. Set OpenAPIOptions.Hidden = true:

fiberoapi.Get(oapi, "/admin/debug/:id",
    controller.Debug,
    fiberoapi.OpenAPIOptions{
        OperationID: "internalDebug",
        Hidden:      true, // ← serves traffic, absent from /openapi.json
    },
)

The path entry is omitted and any type only referenced by hidden routes is skipped from components.schemas (so reading the spec doesn't leak the shape of internal endpoints). Types used by both hidden and visible routes still surface — the visible route needs them.

Opting out of all default error responses

Some endpoints — health checks, readiness probes, anything with no body or no error contract — don't need the framework's 400 / 422 / 404 / 4XX in the spec. Pass an explicit empty Errors slice to suppress every default and document only the 200 success path:

fiberoapi.Get(oapi, "/health",
    func(c fiber.Ctx, _ struct{}) (HealthStatus, struct{}) {
        return HealthStatus{Status: "ok"}, struct{}{}
    },
    fiberoapi.OpenAPIOptions{
        Summary: "Liveness probe",
        Errors:  []any{}, // ← explicit "no errors for this route"
    },
)

The distinction matters: Errors: nil (the zero value) keeps the defaults, Errors: []any{} (an explicitly empty slice) suppresses them. A slice that contains only nil entries is treated as nil for back-compat.

If you need a different shape, set Config.ValidationErrorHandler / Config.AuthErrorHandler — they receive the raw error (JSON type mismatches are wrapped so err.Error() stays friendly, but var ute *json.UnmarshalTypeError; errors.As(err, &ute) still recovers the original).

Unifying all errors under one shape (DefaultErrorShape)

By default, the library emits its own ErrorEnvelope shape for framework-level errors (parse, validation, auth, route-miss) while your custom errors use whatever struct you declared. That mismatch shows up in tools like Redoc / Stoplight as two distinct schemas per endpoint.

Set Config.DefaultErrorShape to a (zero) instance of your error type and the library uses that shape everywhere — both runtime responses and spec entries:

type ErrorResponse struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Details string `json:"details,omitempty"`
    Type    string `json:"type"`
}

oapi := fiberoapi.New(app, fiberoapi.Config{
    DefaultErrorShape: &ErrorResponse{}, // empty template — fields are filled per error
})

For each library-emitted error, the matching fields on your shape are populated via reflection (case-sensitive, applied only if present and settable):

Field Source
StatusCode or Code HTTP status code (400, 401, 403, 404, 405)
Message, Description, or Msg one-line human-readable summary
Type discriminator (type_error, parse_error, authentication_error, authorization_error, not_found, method_not_allowed)
Details joined extra context (allowed methods for 405, …)

One exception: the 422 validation response keeps the rich ErrorEnvelope shape (one entry per failing field with loc / constraint / field / value). Collapsing a multi-field validation failure into a single flat struct would lose the structured info that form-level UX needs. If you really want a flat 422, declare your own entry at status 422 in OpenAPIOptions.Errors — the per-route override still wins.

Result: in your spec every error response references #/components/schemas/ErrorResponse except 422, which stays on #/components/schemas/ErrorEnvelope.

Per-route entries declared via OpenAPIOptions.Errors still take precedence for their status code — so you can selectively override the default shape on a specific endpoint if you ever need to.

Custom domain errors (declared per route, visible in the spec)

For handler-emitted errors (conflict, not-found, precondition-failed, …), declare them via OpenAPIOptions.Errors. Each entry is an instance of any struct describing one error case — the library inspects it to populate the generated OpenAPI spec and the handler returns the same instance at runtime.

// One shared type in your app — all custom errors funnel through it so the
// spec has a single component schema and clients see one consistent shape.
type ErrorResponse struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Details string `json:"details,omitempty"`
    Type    string `json:"type"`
}

func (e *ErrorResponse) Error() string { return e.Message } // optional

func UserAlreadyExists(name string) *ErrorResponse {
    return &ErrorResponse{Code: 409, Message: fmt.Sprintf("user %q already exists", name), Type: "Conflict"}
}

func UserNotFound(name string) *ErrorResponse {
    return &ErrorResponse{Code: 404, Message: fmt.Sprintf("user %q not found", name), Type: "NotFound"}
}

fiberoapi.Post(oapi, "/users/:name",
    func(c fiber.Ctx, in CreateUserInput) (CreateUserOutput, error) {
        if in.Name == "admin" {
            return CreateUserOutput{}, UserAlreadyExists(in.Name)
        }
        return CreateUserOutput{Message: "ok"}, nil
    },
    fiberoapi.OpenAPIOptions{
        Errors: []any{
            UserAlreadyExists("admin"), // becomes the 409 example in the spec
            UserNotFound("ghost"),      // becomes the 404 example in the spec
        },
    },
)

How each entry maps to the spec:

Source Extracted via
Status code HTTPStatus() int method, else StatusCode / Code int field, else 500
Description Description() string method, else Message / Description / Msg string field, else HTTP reason phrase
Schema reflect.TypeOf(entry) — named types use $ref to components.schemas so multiple entries with the same type stay deduplicated
Example the entry value itself, JSON-marshalled

The handler's return type can be error (when the entry implements error), *ErrorResponse, or any other concrete type — the library uses reflection, not a type assertion, to read the status code.

Multiple entries at the same status code: the last one wins (typical when mixing Errors with the auto-emitted default envelopes). Use this to deliberately override the default 404 (route-miss) envelope with your own domain-404 shape for routes that report "resource not found".

404 Not Found

The same envelope is produced for unmatched routes when you opt in via oapi.UseNotFoundHandler(). Call it after registering every route — under the hood it installs a catch-all app.Use(handler) middleware in Fiber, which is matched in registration order, so it must come last to avoid swallowing real routes.

app := fiber.New()
oapi := fiberoapi.New(app)

fiberoapi.Get(oapi, "/users/:id", getUser, opts)
fiberoapi.Post(oapi, "/users", createUser, opts)
// ... every other route ...

oapi.UseNotFoundHandler() // ← last
app.Listen(":3000")

Response shape:

{
  "errors": [
    {
      "type": "not_found",
      "code": 404,
      "loc": ["path"],
      "field": "/users/42",
      "msg": "no route matches GET /users/42"
    }
  ],
  "response_context": { "response_id": "bf0e9029-..." }
}

The default handler does more than just emit the 404 envelope:

  • HEAD requests get a bodyless 404 (HTTP-conformant).
  • OPTIONS requests fall through (c.Next()) so downstream CORS middleware can answer preflights.
  • When the path is registered under another HTTP method, the response is 405 with an Allow header listing the supported methods and the envelope's entry type set to method_not_allowed.
  • The X-Request-Id header is sanitised before being echoed (max 128 bytes, charset [A-Za-z0-9._\-:]) — invalid values are dropped to neutralise log-injection vectors.
  • The echoed path is capped at ~1 KiB and validated as UTF-8.

Calling UseNotFoundHandler() more than once on the same OApiApp is a no-op after the first install. Once installed, the generated OpenAPI spec also lists a 404 response on every operation (referencing ErrorEnvelope) so the contract is documented for clients.

Override the handler entirely via Config.NotFoundHandler. Your handler receives a raw fiber.Ctx and owns the full response — call fiberoapi.NotFoundEnvelope(c) to reuse the library's shape from inside it. For users managing their own fiber.Config, fiberoapi.DefaultNotFoundHandler() returns a no-op-405 version of the catch-all you can install yourself.

Authentication & Authorization

Supported Security Schemes

Scheme Config Validator Interface
Bearer Token Type: "http", Scheme: "bearer" AuthorizationService (built-in)
HTTP Basic Type: "http", Scheme: "basic" BasicAuthValidator
API Key Type: "apiKey", In: "header"/"query"/"cookie" APIKeyValidator
AWS SigV4 Type: "http", Scheme: "AWS4-HMAC-SHA256" AWSSignatureValidator

Setup

Implement AuthorizationService (required) and any additional validator interfaces:

type MyAuthService struct{}

// Required: AuthorizationService
func (s *MyAuthService) ValidateToken(token string) (*fiberoapi.AuthContext, error) { ... }
func (s *MyAuthService) HasRole(ctx *fiberoapi.AuthContext, role string) bool { ... }
func (s *MyAuthService) HasScope(ctx *fiberoapi.AuthContext, scope string) bool { ... }
func (s *MyAuthService) CanAccessResource(ctx *fiberoapi.AuthContext, resourceType, resourceID, action string) (bool, error) { ... }
func (s *MyAuthService) GetUserPermissions(ctx *fiberoapi.AuthContext, resourceType, resourceID string) (*fiberoapi.ResourcePermission, error) { ... }

// Optional: BasicAuthValidator
func (s *MyAuthService) ValidateBasicAuth(username, password string) (*fiberoapi.AuthContext, error) { ... }

// Optional: APIKeyValidator
func (s *MyAuthService) ValidateAPIKey(key, location, paramName string) (*fiberoapi.AuthContext, error) { ... }

// Optional: AWSSignatureValidator
func (s *MyAuthService) ValidateAWSSignature(params *fiberoapi.AWSSignatureParams) (*fiberoapi.AuthContext, error) { ... }

Configure multiple security schemes (OR semantics between them):

config := fiberoapi.Config{
    EnableAuthorization: true,
    AuthService:         &MyAuthService{},
    SecuritySchemes: map[string]fiberoapi.SecurityScheme{
        "bearerAuth": {
            Type:         "http",
            Scheme:       "bearer",
            BearerFormat: "JWT",
            Description:  "JWT Bearer token",
        },
        "basicAuth": {
            Type:        "http",
            Scheme:      "basic",
            Description: "HTTP Basic authentication",
        },
        "apiKeyAuth": {
            Type:        "apiKey",
            In:          "header",
            Name:        "X-API-Key",
            Description: "API Key via header",
        },
    },
    // Any of these schemes can authenticate a request (OR semantics)
    DefaultSecurity: []map[string][]string{
        {"bearerAuth": {}},
        {"basicAuth": {}},
        {"apiKeyAuth": {}},
    },
}
oapi := fiberoapi.New(app, config)

Public vs Protected Routes

// Public route — no authentication
fiberoapi.Get(oapi, "/health", handler,
    fiberoapi.OpenAPIOptions{
        Summary:  "Health check",
        Security: "disabled",
    })

// Protected route — uses default security
fiberoapi.Get(oapi, "/profile", handler,
    fiberoapi.OpenAPIOptions{
        Summary: "Get profile",
    })

// Per-route security override
fiberoapi.Get(oapi, "/admin", handler,
    fiberoapi.WithSecurity(
        fiberoapi.OpenAPIOptions{Summary: "Admin endpoint"},
        []map[string][]string{{"bearerAuth": {}}}, // Only bearer, not API key
    ))

Declarative Role-Based Access Control

Roles are checked automatically before your handler runs. No manual checks needed.

// OR semantics: user needs at least ONE of the listed roles
fiberoapi.Get(oapi, "/documents/:id", handler,
    fiberoapi.WithRoles(
        fiberoapi.OpenAPIOptions{Summary: "Get document", Tags: []string{"documents"}},
        "admin", "editor",  // admin OR editor can access
    ))

// AND semantics: user needs ALL of the listed roles
fiberoapi.Delete(oapi, "/documents/:id", handler,
    fiberoapi.WithAllRoles(
        fiberoapi.OpenAPIOptions{Summary: "Delete document", Tags: []string{"documents"}},
        "admin", "moderator",  // must be admin AND moderator
    ))

// Inline via OpenAPIOptions
fiberoapi.Get(oapi, "/settings", handler,
    fiberoapi.OpenAPIOptions{
        Summary:         "Settings",
        RequiredRoles:   []string{"admin", "superadmin"},
        RequireAllRoles: false,  // OR semantics (default)
    })

Roles appear in the OpenAPI spec as extensions:

{
    "x-required-roles": ["admin", "editor"],
    "x-required-roles-mode": "any"
}

Permissions and Resource Access

// RequiredPermissions are documented in the OpenAPI spec description
fiberoapi.Put(oapi, "/documents/:id", handler,
    fiberoapi.OpenAPIOptions{
        Summary:             "Update document",
        RequiredRoles:       []string{"editor"},
        RequiredPermissions: []string{"document:write"},
    })

// Resource-based access via struct tags
type UpdateDocInput struct {
    DocumentID string `uri:"documentId" validate:"required" resource:"document" action:"write"`
    Title      string `json:"title" validate:"required"`
}

// Dynamic resource access check in handler
fiberoapi.RequireResourceAccess(c, authService, "document", docID, "delete")

Authentication Context

Access the authenticated user in handlers:

fiberoapi.Get(oapi, "/me", func(c fiber.Ctx, input struct{}) (fiber.Map, *fiberoapi.ErrorResponse) {
    authCtx, err := fiberoapi.GetAuthContext(c)
    if err != nil {
        return nil, &fiberoapi.ErrorResponse{Code: 401, Details: "Not authenticated"}
    }
    return fiber.Map{
        "user_id": authCtx.UserID,
        "roles":   authCtx.Roles,
        "scopes":  authCtx.Scopes,
        "claims":  authCtx.Claims,
    }, nil
}, fiberoapi.OpenAPIOptions{Summary: "Current user"})

Custom Error Handlers

Validation Errors

oapi := fiberoapi.New(app, fiberoapi.Config{
    ValidationErrorHandler: func(c fiber.Ctx, err error) error {
        return c.Status(400).JSON(fiber.Map{
            "success": false,
            "error":   err.Error(),
        })
    },
})

Authentication/Authorization Errors

oapi := fiberoapi.New(app, fiberoapi.Config{
    EnableAuthorization: true,
    AuthService:         authService,
    AuthErrorHandler: func(c fiber.Ctx, err *fiberoapi.AuthError) error {
        // err.StatusCode: 401, 403, or 5xx
        // err.Message: human-readable error message
        return c.Status(err.StatusCode).JSON(fiber.Map{
            "error":   err.Message,
            "status":  err.StatusCode,
        })
    },
})

Without custom handlers, default error responses are returned:

// 401 - Authentication failure
{"code": 401, "details": "invalid token", "type": "authentication_error"}

// 403 - Authorization failure
{"code": 403, "details": "requires one of: admin, editor", "type": "authorization_error"}

// 400 - Validation failure
{"code": 400, "details": "...", "type": "validation_error"}

Conditional Auth Middleware

Standalone middleware functions for use outside the declarative route system:

// Smart middleware that auto-detects security schemes and excludes doc routes
app.Use(fiberoapi.SmartAuthMiddleware(authService, config))

// Skip auth for specific paths
app.Use(fiberoapi.ConditionalAuthMiddleware(
    fiberoapi.BearerTokenMiddleware(authService),
    "/health", "/docs", "/openapi.json",
))

// Individual scheme middleware
app.Use(fiberoapi.BearerTokenMiddleware(authService))
app.Use(fiberoapi.BasicAuthMiddleware(authService))
app.Use(fiberoapi.APIKeyMiddleware(authService, scheme))
app.Use(fiberoapi.AWSSignatureMiddleware(authService))

// Role guard middleware
app.Use(fiberoapi.RoleGuard(authService, "admin"))

Security Helpers

opts := fiberoapi.OpenAPIOptions{Summary: "My endpoint"}

// Security
opts = fiberoapi.WithSecurity(opts, []map[string][]string{{"bearerAuth": {}}})
opts = fiberoapi.WithSecurityDisabled(opts)

// Roles
opts = fiberoapi.WithRoles(opts, "admin", "editor")       // OR semantics
opts = fiberoapi.WithAllRoles(opts, "admin", "moderator")  // AND semantics

// Documentation
opts = fiberoapi.WithPermissions(opts, "document:read", "document:write")
opts = fiberoapi.WithResourceType(opts, "document")

OpenAPI Spec Generation

The spec is available in both JSON and YAML:

// Automatic endpoints
// GET /openapi.json
// GET /openapi.yaml
// GET /docs (Redoc UI)

// Programmatic access
spec := oapi.GenerateOpenAPISpec()           // map[string]interface{}
yamlSpec, err := oapi.GenerateOpenAPISpecYAML() // string

Custom Documentation

oapi.SetupDocs(fiberoapi.DocConfig{
    Title:       "My API",
    Description: "My API description",
    Version:     "2.0.0",
    DocsPath:    "/documentation",
    JSONPath:    "/api-spec.json",
})

Testing

# Run all tests
go test -v ./...

# Run the auth example
go run _examples/auth/main.go
# Visit http://localhost:3002/docs

Testing with authentication:

# Bearer token
curl -H "Authorization: Bearer admin-token" http://localhost:3002/me

# Basic auth
curl --user admin:admin-pass http://localhost:3002/me

# API key
curl -H "X-API-Key: my-secret-api-key" http://localhost:3002/documents/doc-1

# Public endpoint
curl http://localhost:3002/health

Complete Example

See _examples/auth/main.go for a full working example with:

  • Multiple security schemes (Bearer, Basic, API Key, AWS SigV4)
  • Declarative role-based access control
  • Custom auth error handler
  • Public and protected routes
  • Resource-level authorization
  • OpenAPI documentation with security schemes

About

Small lib for create openapi documentation and expose it automatically (json and swagger ui)

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages