okapi

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: May 28, 2025 License: MIT Imports: 29 Imported by: 11

README

OKAPI - Lightweight Go Web Framework

Tests Go Report Card Go Reference GitHub Release

Okapi is a modern, minimalist HTTP web framework for Go, inspired by the simplicity of FastAPI. Designed to be intuitive, lightweight, and powerful, Okapi makes it easy to build fast and flexible web applications and REST APIs.

Okapi logo


Features

  • Clean and expressive API design
  • Powerful binding from JSON, forms, query, headers, and path parameters
  • Route grouping and middleware chaining
  • Built-in middleware: Basic Auth, JWT, OAuth
  • Easy custom middleware support
  • Templating engine integration
  • Static file serving
  • Built entirely on Go’s standard library
  • Simple and clear documentation

Installation

mkdir myapi && cd myapi
go mod init myapi
go get github.com/jkaninda/okapi

Quick Start

Create a file named main.go:

package main

import (
	"net/http"
	"github.com/jkaninda/okapi"
)

func main() {
	o := okapi.New()

	o.Get("/", func(c okapi.Context) error {
		return c.JSON(http.StatusOK, okapi.M{"message": "Welcome to Okapi!"})
	})

	if err := o.Start(); err != nil {
		panic(err)
	}
}

Run your server:

go run .

Visit http://localhost:8080 to see the response:

{"message": "Welcome to Okapi!"}

Routing

Okapi supports all standard HTTP methods:

o.Get("/books", getBooks)
o.Post("/books", createBook)
o.Get("/books/:id", getBook)
o.Put("/books/:id", updateBook)
o.Delete("/books/:id", deleteBook)
Route Groups

Organize routes with nesting and middleware:

api := o.Group("/api")

v1 := api.Group("/v1")
v1.Get("/users", getUsers)

admin := api.Group("/admin", adminMiddleware)
admin.Get("/dashboard", getDashboard)

Request Handling

Path Parameters
o.Get("/books/:id", func(c okapi.Context) error {
	id := c.Param("id")
	return c.String(http.StatusOK, id)
})
Query Parameters
o.Get("/books", func(c okapi.Context) error {
	name := c.Query("name")
	return c.String(http.StatusOK, name)
})
Struct Binding

Bind request data into a struct from multiple sources:

type Book struct {
	ID    int    `json:"id" param:"id" query:"id" form:"id"`
	Name  string `json:"name" form:"name" max:"50"`
	Price int    `json:"price" form:"price" required:"true"`
}

o.Post("/books", func(c okapi.Context) error {
	book := &Book{}
	if err := c.Bind(book); err != nil {
		return err
	}
	return c.JSON(http.StatusOK, book)
})

Supported sources:

  • Path parameters: param
  • Query parameters: query
  • Form fields: form
  • JSON body: json
  • Headers: header

Middleware

Built-in Example (Basic Auth)
auth := okapi.BasicAuthMiddleware{
	Username: "admin",
	Password: "password",
	Realm:    "Restricted",
}

o.Use(auth.Middleware)
o.Get("/admin", adminHandler)
Custom Middleware
func logger(next okapi.HandlerFunc) okapi.HandlerFunc {
	return func(c okapi.Context) error {
		start := time.Now()
		err := next(c)
		log.Printf("Request took %v", time.Since(start))
		return err
	}
}

o.Use(logger)

Templating

Using a Custom Renderer
o.Renderer = okapi.RendererFunc(func(w io.Writer, name string, data interface{}, c okapi.Context) error {
	tmpl, err := template.ParseFiles("templates/" + name + ".html")
	if err != nil {
		return err
	}
	return tmpl.ExecuteTemplate(w, name, data)
})
Or Using a Struct-Based Renderer
type Template struct {
	templates *template.Template
}

func (t *Template) Render(w io.Writer, name string, data interface{}, c okapi.Context) error {
	return t.templates.ExecuteTemplate(w, name, data)
}

tmpl := &Template{
	templates: template.Must(template.ParseGlob("templates/*.html")),
}

o.Renderer = tmpl
Rendering a View
o.Get("/", func(c okapi.Context) error {
	return c.Render(http.StatusOK, "welcome", okapi.M{
		"title":   "Welcome Page",
		"message": "Hello from Okapi!",
	})
})

Static File Serving

Serve static assets and individual files:

// Serve a single file
o.Get("/favicon.ico", func(c okapi.Context) error {
	return c.ServeFile("public/favicon.ico")
})

// Serve an entire directory
o.Static("/static", "public/assets")

Contributing

Contributions are welcome!

  1. Fork the repository
  2. Create a feature branch
  3. Commit your changes
  4. Push to your fork
  5. Open a Pull Request


Give a Star! ⭐

⭐ If you find Okapi useful, please consider giving it a star on GitHub!

License

This project is licensed under the MIT License. See the LICENSE file for details.

Copyright (c) 2025 Jonas Kaninda

Documentation

Index

Constants

View Source
const (
	ContentTypeHeader = "Content-Type"
	AcceptHeader      = "Accept"
	LocationHeader    = "Location"
	FrameworkName     = "Okapi"
	TRUE              = "true"
)
View Source
const (
	StatusNotFound            = http.StatusNotFound
	StatusBadRequest          = http.StatusBadRequest
	StatusUnauthorized        = http.StatusUnauthorized
	StatusForbidden           = http.StatusForbidden
	StatusInternalServerError = http.StatusInternalServerError
)

Constants for HTTP Status Codes

View Source
const (
	DELETE  = http.MethodDelete
	GET     = http.MethodGet
	HEAD    = http.MethodHead
	OPTIONS = http.MethodOptions
	POST    = http.MethodPost
	PUT     = http.MethodPut
	PATCH   = http.MethodPatch
	CONNECT = http.MethodConnect
	TRACE   = http.MethodTrace
)

HTTP methods

View Source
const (
	JSON           = "application/json"
	XML            = "application/xml"
	HTML           = "text/html"
	FORM           = "application/x-www-form-urlencoded"
	FormData       = "multipart/form-data"
	PLAIN          = "text/plain"
	PLAINTEXT      = "text/plain"
	CSV            = "text/csv"
	JAVASCRIPT     = "application/javascript"
	YAML           = "application/yaml"
	YamlX          = "application/x-yaml"
	YamlText       = "text/yaml"
	PROTOBUF       = "application/protobuf"
	FormURLEncoded = "application/x-www-form-urlencoded"
)

Mime types

Variables

View Source
var (
	ErrNotFound               = errors.New("not found")
	ErrFailedToParseMultiPart = errors.New("failed to parse multipart data")
	ErrInvalidMultiPartData   = errors.New("invalid multipart data")
)

Constants for Error Handling

View Source
var (
	DefaultWriter      io.Writer = os.Stdout
	DefaultErrorWriter io.Writer = os.Stderr
	DefaultPort        int       = 8080
	DefaultAddr        string    = ":8080"
)
View Source
var (
	ErrNoRenderer = errors.New("no renderer set for context")
)

Functions

func GenerateJwtToken

func GenerateJwtToken(secret []byte, claims jwt.MapClaims, ttl time.Duration) (string, error)

GenerateJwtToken generates a JWT with custom claims and expiry

func RealIP

func RealIP(r *http.Request) string

RealIP extracts the real IP address of the client from the HTTP Request.

func ValidateAddr

func ValidateAddr(addr string) bool

ValidateAddr checks if the entrypoint address is valid. A valid entrypoint address should be in the format ":<port>" or "<IP>:<port>", where <IP> is a valid IP address and <port> is a valid port number (1-65535).

Types

type BasicAuthMiddleware

type BasicAuthMiddleware struct {
	Username string
	Password string
	Realm    string
}

BasicAuthMiddleware provides basic authentication for routes.

func (*BasicAuthMiddleware) Middleware

func (b *BasicAuthMiddleware) Middleware(next HandleFunc) HandleFunc

Middleware is a basic authentication middleware that checks the request's Basic Auth credentials.

type BodyLimit

type BodyLimit struct {
	MaxBytes int64
}

BodyLimit is a middleware that limits the size of the request body.

func (BodyLimit) Middleware

func (b BodyLimit) Middleware(next HandleFunc) HandleFunc

Middleware is a middleware that limits the size of the request body to prevent excessive memory usage.

type Context

type Context struct {
	http.Handler

	// Request is the http.Request object
	Request *http.Request
	// Response http.ResponseWriter
	Response Response
	// CtxData is a key/value store for storing data in the context
	CtxData            map[string]any
	MaxMultipartMemory int64 // Maximum memory for multipart forms
	// contains filtered or unexported fields
}

func (*Context) AbortWithError

func (c *Context) AbortWithError(code int, err error) error

AbortWithError writes an error response with the given status code. Returns the error for chaining.

func (*Context) Accept

func (c *Context) Accept() []string

Accept returns the Accept header values as a slice.

func (*Context) AcceptLanguage

func (c *Context) AcceptLanguage() []string

AcceptLanguage returns the Accept-Language header values as a slice. Trims whitespace from each language tag.

func (*Context) B

func (c *Context) B(v any) error

B is a shortcut for Bind, allowing you to bind request data to a struct.

func (*Context) BadRequestError

func (c *Context) BadRequestError(message string)

BadRequestError writes a 400 Bad Request response.

func (*Context) Bind

func (c *Context) Bind(out any) error

Bind binds the request data to the provided struct based on the content type and tags.

func (*Context) BindForm

func (c *Context) BindForm(v any) error

func (*Context) BindJSON

func (c *Context) BindJSON(v any) error

func (*Context) BindMultipart

func (c *Context) BindMultipart(out any) error

func (*Context) BindProtoBuf

func (c *Context) BindProtoBuf(v proto.Message) error

func (*Context) BindQuery

func (c *Context) BindQuery(v any) error

func (*Context) BindXML

func (c *Context) BindXML(v any) error

func (*Context) BindYAML

func (c *Context) BindYAML(v any) error

func (*Context) ContentType

func (c *Context) ContentType() string

ContentType returns the Content-Type header value.

func (*Context) Cookie

func (c *Context) Cookie(name string) (string, error)

Cookie retrieves a cookie value by name. Returns empty string and error if cookie not found.

func (*Context) Copy

func (c *Context) Copy() *Context

Copy creates a shallow copy of the context with a new data map. Maintains thread safety during the copy operation.

func (*Context) Data

func (c *Context) Data(code int, contentType string, data []byte) error

Data writes a raw byte response with the given content type and status code.

func (*Context) Error

func (c *Context) Error(code int, message string) error

Error writes an error response with the given status code and message.

func (*Context) Form

func (c *Context) Form(key string) string

Form retrieves a form value after parsing the form data.

func (*Context) FormFile

func (c *Context) FormFile(key string) (*multipart.FileHeader, error)

FormFile retrieves a file from multipart form data. Returns the file and any error encountered.

func (*Context) FormValue

func (c *Context) FormValue(key string) string

FormValue retrieves a form value, including multipart form data.

func (*Context) Get

func (c *Context) Get(key string) (any, bool)

Get retrieves a value from the context's data store with thread-safe access. Returns the value and a boolean indicating if the key exists.

func (*Context) GetBool

func (c *Context) GetBool(key string) bool

GetBool retrieves a boolean value from the context. Returns false if key doesn't exist or value isn't a bool.

func (*Context) GetInt

func (c *Context) GetInt(key string) int

GetInt retrieves an integer value from the context. Returns 0 if key doesn't exist or value isn't an int.

func (*Context) GetInt64

func (c *Context) GetInt64(key string) int64

GetInt64 retrieves an int64 value from the context. Returns 0 if key doesn't exist or value isn't an int64.

func (*Context) GetString

func (c *Context) GetString(key string) string

GetString retrieves a string value from the context. Returns empty string if key doesn't exist or value isn't a string.

func (*Context) GetTime

func (c *Context) GetTime(key string) (time.Time, bool)

GetTime retrieves a time.Time value from the context's data store.

func (*Context) HTML

func (c *Context) HTML(code int, file string, data any) error

HTML renders an HTML template from a file with the given status code.

func (*Context) HTMLView

func (c *Context) HTMLView(code int, templateStr string, data any) error

HTMLView renders an HTML template from a string with the given status code.

func (*Context) Header

func (c *Context) Header(key string) string

Header gets a request header by key.

func (*Context) Headers

func (c *Context) Headers() map[string][]string

Headers returns all request headers as a map.

func (*Context) InternalServerError

func (c *Context) InternalServerError(message string)

InternalServerError writes a 500 Internal Server Error response.

func (*Context) IsSSE

func (c *Context) IsSSE() bool

IsSSE checks if the request is for Server-Sent Events (SSE).

func (*Context) IsWebSocketUpgrade

func (c *Context) IsWebSocketUpgrade() bool

IsWebSocketUpgrade checks if the request is a WebSocket upgrade request.

func (*Context) JSON

func (c *Context) JSON(code int, v any) error

JSON writes a JSON response with the given status code.

func (*Context) NotFoundError

func (c *Context) NotFoundError(message string)

NotFoundError writes a 404 Not Found response.

func (*Context) Param

func (c *Context) Param(key string) string

Param retrieves a URL path parameter value.

func (*Context) Query

func (c *Context) Query(key string) string

Query retrieves a URL query parameter value. Returns empty string if parameter doesn't exist.

func (*Context) QueryMap

func (c *Context) QueryMap() map[string]string

QueryMap returns all query parameters as a map. Only includes the first value for each parameter.

func (*Context) RealIP

func (c *Context) RealIP() string

RealIP returns the client's real IP address, handling proxies.

func (*Context) Redirect

func (c *Context) Redirect(code int, location string)

Redirect sends a redirect response to the specified location.

func (*Context) Referer

func (c *Context) Referer() string

Referer retrieves the Referer header value from the request.

func (*Context) Render

func (c *Context) Render(code int, name string, data interface{}) error

Render renders a template using the configured Renderer.

func (*Context) ServeFile

func (c *Context) ServeFile(path string)

ServeFile serves a file from the filesystem.

func (*Context) ServeFileAttachment

func (c *Context) ServeFileAttachment(path, filename string)

ServeFileAttachment serves a file as an attachment (download).

func (*Context) ServeFileFromFS

func (c *Context) ServeFileFromFS(filepath string, fs http.FileSystem)

ServeFileFromFS serves a file from a custom http.FileSystem.

func (*Context) ServeFileInline

func (c *Context) ServeFileInline(path, filename string)

ServeFileInline serves a file to be displayed inline in the browser.

func (*Context) Set

func (c *Context) Set(key string, value any)

Set stores a value in the context's data store with thread-safe access. Initializes the data map if it doesn't exist.

func (*Context) SetCookie

func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)

SetCookie sets a cookie with various configurable options. Defaults path to "/" if empty.

func (*Context) SetHeader

func (c *Context) SetHeader(key, value string)

SetHeader sets a response header.

func (*Context) ShouldBind

func (c *Context) ShouldBind(v any) (bool, error)

func (*Context) String

func (c *Context) String(code int, data any) error

String is an alias for Text for convenience.

func (*Context) Text

func (c *Context) Text(code int, v any) error

Text writes a plain text response with the given status code.

func (*Context) WriteStatus

func (c *Context) WriteStatus(code int)

WriteStatus writes the HTTP status code to the response.

func (*Context) XML

func (c *Context) XML(code int, v any) error

XML writes an XML response with the given status code.

func (*Context) YAML

func (c *Context) YAML(code int, data any) error

YAML writes a YAML response with the given status code.

type Group

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

func (*Group) BasePath

func (g *Group) BasePath() string

func (*Group) Delete

func (g *Group) Delete(path string, h HandleFunc) *Route

func (*Group) Get

func (g *Group) Get(path string, h HandleFunc) *Route

func (*Group) Group

func (g *Group) Group(path string, middlewares ...Middleware) *Group

Group creates a nested subgroup with an additional path segment

func (*Group) Head

func (g *Group) Head(path string, h HandleFunc) *Route

func (*Group) Okapi

func (g *Group) Okapi() *Okapi

func (*Group) Options

func (g *Group) Options(path string, h HandleFunc) *Route

func (*Group) Patch

func (g *Group) Patch(path string, h HandleFunc) *Route

func (*Group) Post

func (g *Group) Post(path string, h HandleFunc) *Route

func (*Group) Put

func (g *Group) Put(path string, h HandleFunc) *Route

func (*Group) SetBasePath

func (g *Group) SetBasePath(basePath string)

func (*Group) Trace

func (g *Group) Trace(path string, h HandleFunc) *Route

func (*Group) Use

func (g *Group) Use(m Middleware)

type HandleFunc

type HandleFunc func(c Context) error

HandleFunc is a function type that takes a Context and returns an error.

func LoggerMiddleware

func LoggerMiddleware(next HandleFunc) HandleFunc

LoggerMiddleware is a middleware that logs request details like method, URL, client IP, status, duration, referer, and user agent.

type JWTAuth

type JWTAuth struct {
	SecretKey   []byte
	TokenLookup string // e.g., "header:Authorization", "query:token", "cookie:jwt"
	ContextKey  string // where to store claims in context, e.g. "user"
}

JWTAuth holds the config for JWT verification middleware.

func (JWTAuth) Middleware

func (j JWTAuth) Middleware(next HandleFunc) HandleFunc

Middleware validates JWT tokens from the configured source

func (JWTAuth) ValidateToken

func (j JWTAuth) ValidateToken(c Context) (jwt.MapClaims, error)

ValidateToken checks the JWT token and returns the claims if valid

type Logger

type Logger struct {
}

Logger is a middleware that logs request details such as method, URL, client IP, status, duration, referer, and user agent.

type M

type M map[string]any

M is shortcut of map[string]any

type Message

type Message struct {
	// ID is the identifier for the SSE connection.
	ID string `json:"id" xml:"id"`
	// Data is the Data to be sent to the SSE connection.
	Data any `json:"message"`
	// Event is the event type for the SSE connection.
	Event string `json:"event"`
}

Message is a struct that represents a Server-Sent Events (SSE) connection.

func (*Message) Close

func (s *Message) Close(w http.ResponseWriter) error

Close closes the SSE connection by flushing the response writer.

func (*Message) Send

func (s *Message) Send(w http.ResponseWriter, data any, eventType string) (string, error)

Send sends a message to the SSE connection.

type Middleware

type Middleware func(next HandleFunc) HandleFunc

type Okapi

type Okapi struct {
	Server    *http.Server
	TLSServer *http.Server

	Renderer Renderer
	// contains filtered or unexported fields
}

func Default

func Default(options ...OptionFunc) *Okapi

Default creates a new Okapi instance with default settings

func New

func New(options ...OptionFunc) (e *Okapi)

New creates a new Okapi instance

func (*Okapi) Any

func (o *Okapi) Any(path string, h HandleFunc) *Route

func (*Okapi) Connect

func (o *Okapi) Connect(path string, h HandleFunc) *Route

func (*Okapi) Delete

func (o *Okapi) Delete(path string, h HandleFunc) *Route

func (*Okapi) Get

func (o *Okapi) Get(path string, h HandleFunc) *Route

func (*Okapi) GetContext

func (o *Okapi) GetContext() *Context

GetContext returns the current context

func (*Okapi) Group

func (o *Okapi) Group(path string, middlewares ...Middleware) *Group

Group creates a new group with the specified path

func (*Okapi) HandleFunc

func (o *Okapi) HandleFunc(method, path string, h HandleFunc)

HandleFunc adds a route with a custom handler function

func (*Okapi) Head

func (o *Okapi) Head(path string, h HandleFunc) *Route

func (*Okapi) Middlewares

func (o *Okapi) Middlewares() []Middleware

Middlewares returns the list of middlewares

func (*Okapi) Next

func (o *Okapi) Next(h HandleFunc) HandleFunc

Next applies the middlewares in correct order

func (*Okapi) Options

func (o *Okapi) Options(path string, h HandleFunc) *Route

func (*Okapi) Patch

func (o *Okapi) Patch(path string, h HandleFunc) *Route

func (*Okapi) Post

func (o *Okapi) Post(path string, h HandleFunc) *Route

func (*Okapi) Put

func (o *Okapi) Put(path string, h HandleFunc) *Route

func (*Okapi) Routes

func (o *Okapi) Routes() []Route

func (*Okapi) ServeHTTP

func (o *Okapi) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements the http.Handler interface

func (*Okapi) SetContext

func (o *Okapi) SetContext(ctx *Context)

func (*Okapi) Shutdown

func (o *Okapi) Shutdown(server *http.Server) error

func (*Okapi) Start

func (o *Okapi) Start() error

Start starts the Okapi server

func (*Okapi) StartServer

func (o *Okapi) StartServer(server *http.Server) error

StartServer starts the Okapi server with the specified HTTP server

func (*Okapi) Static

func (o *Okapi) Static(prefix string, dir string)

Static serves static files under a path prefix, without directory listing

func (*Okapi) StaticFS

func (o *Okapi) StaticFS(prefix string, fs http.FileSystem)

StaticFS serves static files from a custom http.FileSystem (e.g., embed.FS).

func (*Okapi) StaticFile

func (o *Okapi) StaticFile(path string, filepath string)

StaticFile serves a single file at the specified path.

func (*Okapi) Stop

func (o *Okapi) Stop()

Stop stops the Okapi server

func (*Okapi) Trace

func (o *Okapi) Trace(path string, h HandleFunc) *Route

func (*Okapi) Use

func (o *Okapi) Use(middlewares ...Middleware)

Use adds middleware to the Okapi instance

func (*Okapi) With

func (o *Okapi) With(options ...OptionFunc) *Okapi

With applies the provided options to the Okapi instance

type OptionFunc

type OptionFunc func(*Okapi)

func WithAccessLogDisabled

func WithAccessLogDisabled() OptionFunc

WithAccessLogDisabled disables the access log for the Okapi instance

func WithAddr

func WithAddr(addr string) OptionFunc

WithAddr sets the address for the Okapi instance

func WithDebug

func WithDebug() OptionFunc

WithDebug sets the debug mode for the Okapi instance

func WithLogger

func WithLogger(logger *slog.Logger) OptionFunc

WithLogger sets the logger for the Okapi instance

func WithMux

func WithMux(mux *mux.Router) OptionFunc

WithMux sets the router for the Okapi instance

func WithPort

func WithPort(port int) OptionFunc

WithPort sets the port for the Okapi instance

func WithServer

func WithServer(server *http.Server) OptionFunc

WithServer sets the HTTP server for the Okapi instance

func WithStrictSlash

func WithStrictSlash(strict bool) OptionFunc

WithStrictSlash sets the strict slash mode for the Okapi instance

func WithTLSServer

func WithTLSServer(server *http.Server) OptionFunc

WithTLSServer sets the TLS server for the Okapi instance

type Param

type Param struct {
	Param struct {
		Key   string
		Value string
	}
}

type Params

type Params []Param

func (*Params) Get

func (p *Params) Get(key string) (string, bool)

type Renderer

type Renderer interface {
	Render(io.Writer, string, interface{}, Context) error
}

type RendererFunc

type RendererFunc func(io.Writer, string, interface{}, Context) error

func (RendererFunc) Render

func (f RendererFunc) Render(w io.Writer, name string, data interface{}, c Context) error

type Response

type Response interface {
	http.ResponseWriter
	BodyBytesSent() int
	Status() int
	Close()
	Hijack() (net.Conn, *bufio.ReadWriter, error)
}

Response interface defines the methods for writing HTTP responses.

type Route

type Route struct {
	Name   string
	Path   string
	Method string
	Handle HandleFunc
	// contains filtered or unexported fields
}

type Router

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

type Send

type Send func(data any, eventType string) (string, error)

type ValidateFunc

type ValidateFunc func(data any) error

ValidateFunc is a function type that implements the Validator interface

func (ValidateFunc) Validate

func (vf ValidateFunc) Validate(data any) error

type Validator

type Validator interface {
	// Validate validates the data and returns an error if validation fails
	Validate(data any) error
}

Directories

Path Synopsis
examples
group command
middleware command
multipart command
sample command
sse command
template command

Jump to

Keyboard shortcuts

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