Kai is a tiny Go HTTP framework for building clean REST APIs.
It offers method-based routing with path params and simple route groups.
Middleware chaining is first-class with Next()/Abort() control flow.
The context API keeps handlers short with helpers for JSON, text, files, and redirects.
Built-in utilities cover logging, recovery, CORS, request IDs, timeouts, and rate limits.
- Method-based routing with path params (e.g.
/users/:id). - Global and per-route middleware with
Next()andAbort(). - Context helpers for JSON, text, status, headers, and redirects.
- Query parsing and request body caching.
- File upload helpers and simple file serving.
- Built-in middleware: logger, panic recovery, CORS, request ID, timeout, rate limit, secure headers, gzip.
go get github.com/dipto-kainin/kaipackage main
import (
"github.com/dipto-kainin/kai"
)
func main() {
app := kai.NewApp()
// Global middleware
app.Use(kai.Logger(), kai.DamageControl())
app.GET("/hello", func(c *kai.Context) {
c.JSON(200, map[string]string{
"message": "Hello, World!",
})
})
_ = app.Play(8000)
}Run it:
go run ./cmdapp := kai.NewApp()
api := app.Group("/api")
api.GET("/users/:id", func(c *kai.Context) {
id := c.Param("id")
c.JSON(200, map[string]string{"id": id})
})Middleware can call c.Next() to continue or c.Abort() to stop the chain.
app.Use(kai.RequestID(), kai.Timeout(5*time.Second))The project now includes a fuller example in cmd/example/crud_showcase.go. It demonstrates:
GET /api/poststo list records with optional query filters.GET /api/posts/:idto fetch one record by path param.POST /api/poststo create a record from JSON.PUT /api/posts/:idto fully update a record from JSON.DELETE /api/posts/:idto remove a record.POST /api/posts/:id/fileto upload a multipart file.GET /api/posts/:id/fileto download the uploaded file.DELETE /api/posts/:id/fileto remove the uploaded file.
Run the example server:
go run ./cmdList posts:
curl "http://localhost:8000/api/posts?limit=10&published=true"Get one post:
curl http://localhost:8000/api/posts/1Create a post:
curl -X POST http://localhost:8000/api/posts \
-H "Content-Type: application/json" \
-d '{
"title": "Write docs",
"content": "Document the framework with realistic examples.",
"published": false
}'Update a post:
curl -X PUT http://localhost:8000/api/posts/1 \
-H "Content-Type: application/json" \
-d '{
"title": "Ship the first endpoint",
"content": "The example now shows full CRUD plus files.",
"published": true
}'Delete a post:
curl -X DELETE http://localhost:8000/api/posts/1Upload a file to a post:
curl -X POST http://localhost:8000/api/posts/2/file \
-F "file=@./README.md"Download that file:
curl -OJ http://localhost:8000/api/posts/2/fileDelete that file:
curl -X DELETE http://localhost:8000/api/posts/2/fileExample JSON response from GET /api/posts/1:
{
"id": 1,
"title": "Ship the first endpoint",
"content": "This seeded record helps you try GET and PUT immediately.",
"published": true,
"created_at": "2026-04-14T10:00:00Z",
"updated_at": "2026-04-14T10:00:00Z"
}Param(key)for path params.Query(key)andQueryDefault(key, fallback).BodyBytes()andBodyString().JSON(code, obj),String(code, message),Status(code).Set(key, value)/Get(key)for request-scoped data.GetJSON()for simple JSON request parsing.GetFileBytes(fieldName),SaveToDest(dest, fieldName)for multipart uploads.ServeFile(path),Redirect(code, location).
See the example handlers in cmd/example/test_routes.go.
Kai is licensed under the MIT License. The license text lives in LICENSE.
.
├── app.go
├── context.go
├── middleware.go
├── router.go
├── utils/
│ ├── errors.go
│ └── path.go
└── cmd/
├── main.go
└── example/
├── test_control.go
├── test_control1.go
└── test_routes.go