{"id":47717037,"url":"https://github.com/reststore/restkit","last_synced_at":"2026-04-02T19:02:24.055Z","repository":{"id":348009157,"uuid":"1196077940","full_name":"RestStore/RestKit","owner":"RestStore","description":"Type-Safe REST API Framework With OpenAPI Support","archived":false,"fork":false,"pushed_at":"2026-03-31T19:43:38.000Z","size":205,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-31T21:28:04.933Z","etag":null,"topics":["api","api-rest","go","golang","rest","rest-api","restful"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RestStore.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-30T10:54:02.000Z","updated_at":"2026-03-31T19:43:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/RestStore/RestKit","commit_stats":null,"previous_names":["telikz/restkit","reststore/restkit"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/RestStore/RestKit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RestStore%2FRestKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RestStore%2FRestKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RestStore%2FRestKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RestStore%2FRestKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RestStore","download_url":"https://codeload.github.com/RestStore/RestKit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RestStore%2FRestKit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31313858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","api-rest","go","golang","rest","rest-api","restful"],"created_at":"2026-04-02T19:02:13.773Z","updated_at":"2026-04-02T19:02:24.029Z","avatar_url":"https://github.com/RestStore.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RestKit - Type-Safe REST API Framework With OpenAPI Support\n\n[![Go Version](https://img.shields.io/github/go-mod/go-version/RestStore/RestKit?style=flat-square\u0026label=go)](https://golang.org/)\n[![Tests](https://github.com/RestStore/RestKit/actions/workflows/go.yml/badge.svg)](https://github.com/RestStore/RestKit/actions)\n[![Go Report Card](https://goreportcard.com/badge/github.com/reststore/restkit)](https://goreportcard.com/report/github.com/reststore/restkit)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/RestStore/RestKit/blob/main/LICENCE)\n[![Maintained](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/RestStore/RestKit/graphs/commit-activity)\n[![GitHub stars](https://img.shields.io/github/stars/RestStore/RestKit?style=flat-square)](https://github.com/RestStore/RestKit/stargazers)\n\nRestKit is a modern Go framework for building type-safe REST APIs with automatic OpenAPI documentation. It leverages generics to provide compile-time type safety while keeping the API simple and expressive.\n\n## 🎯 Features\n\n- **Type-Safe Endpoints** - Define request/response types with compile-time type checking using Go generics\n- **Three Endpoint Patterns** - Full (Request + Response), Response-only, or Request-only endpoints\n- **Automatic OpenAPI 3.0** - Generate OpenAPI specs directly from your endpoint definitions\n- **Swagger UI Integration** - Built-in interactive API documentation\n- **Flexible Middleware** - CORS, logging, panic recovery, plus custom middleware support\n- **Request Binding \u0026 Validation** - JSON parsing, path parameters, struct validation with customization\n- **Response Serialization** - Type-safe JSON responses with proper error handling\n- **Endpoint Grouping** - Organize endpoints with common prefixes and shared middleware\n- **Router Agnostic** - Built on standard net/http with adapters for Chi and other routers\n- **Error Codes** - Standardized error responses with typed error codes\n\n## ⚙️ Installation\n\nRestKit requires **Go 1.26 or higher**. Install it with:\n\n```bash\ngo get -u github.com/reststore/restkit\n```\n\n## ⚡️ Quickstart\n\nHere's a complete example with a type-safe user creation endpoint:\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\trest \"github.com/reststore/restkit\"\n)\n\n// Define your request and response types\ntype CreateUserReq struct {\n\tName  string `json:\"name\" validate:\"required,min=2\"`\n\tEmail string `json:\"email\" validate:\"required,email\"`\n}\n\ntype UserRes struct {\n\tID    int    `json:\"id\"`\n\tName  string `json:\"name\"`\n\tEmail string `json:\"email\"`\n}\n\n// Handler with compile-time type safety\nfunc createUserHandler(ctx context.Context, req CreateUserReq) (UserRes, error) {\n\treturn UserRes{\n\t\tID:    1,\n\t\tName:  req.Name,\n\t\tEmail: req.Email,\n\t}, nil\n}\n\nfunc main() {\n\t// Create API with metadata\n\tapi := rest.NewApi().\n\t\tWithVersion(\"1.0.0\").\n\t\tWithTitle(\"User API\").\n\t\tWithDescription(\"Manage users\")\n\n\t// Define endpoint with fluent builder\n\tcreateUserEndpoint := rest.NewEndpoint[CreateUserReq, UserRes]().\n\t\tWithTitle(\"Create User\").\n\t\tWithDescription(\"Create a new user\").\n\t\tWithPath(\"/users\").\n\t\tWithMethod(\"POST\").\n\t\tWithHandler(createUserHandler)\n\n\tapi.Add(createUserEndpoint)\n\n\t// Enable Swagger UI accessible at /swagger\n\tapi.WithSwaggerUI()\n\n\t// Add middleware\n\tapi.WithMiddleware(rest.LoggingMiddleware())\n\tapi.WithMiddleware(rest.CORSMiddleware())\n\n\t// Start server\n\tserver := \u0026http.Server{\n\t\tAddr:         \":8080\",\n\t\tHandler:      api.Mux(),\n\t\tReadTimeout:  15 * time.Second,\n\t\tWriteTimeout: 15 * time.Second,\n\t}\n\n\tlog.Println(\"Server running on http://localhost:8080\")\n\tlog.Println(\"Swagger UI: http://localhost:8080/swagger\")\n\tlog.Fatal(server.ListenAndServe())\n}\n```\n\nVisit `http://localhost:8080/swagger` to see the interactive Swagger UI.\n\n## 📖 Endpoint Types\n\nRestKit provides three endpoint patterns, each with sensible defaults:\n\n### Full Endpoint (Request + Response)\n\n```go\nendpoint := rest.NewEndpoint[RequestType, ResponseType]().\n\tWithPath(\"/resource\").\n\tWithMethod(\"POST\").\n\tWithHandler(func(ctx context.Context, req RequestType) (ResponseType, error) {\n\t\t// Your logic here\n\t\treturn res, nil\n\t})\n```\n\n**Defaults:** POST method, JSON bind/write, auto-generated schemas\n\n### Response-Only Endpoint\n\n```go\nendpoint := rest.NewEndpointRes[ResponseType]().\n\tWithPath(\"/resource/{id}\").\n\tWithHandler(func(ctx context.Context) (ResponseType, error) {\n\t\t// Your logic here\n\t\treturn res, nil\n\t})\n```\n\n**Defaults:** GET method, auto-generated response schema\n\n### Request-Only Endpoint\n\n```go\nendpoint := rest.NewEndpointReq[RequestType]().\n\tWithPath(\"/resource/{id}\").\n\tWithHandler(func(ctx context.Context, req RequestType) error {\n\t\t// Your logic here\n\t\treturn nil\n\t})\n```\n\n**Defaults:** DELETE method, JSON bind, auto-generated request schema\n\n## 👥 Endpoint Grouping\n\nOrganize related endpoints with a common prefix:\n\n```go\nuserGroup := rest.NewGroup(\"/api/v1/users\").\n\tWithTitle(\"Users\").\n\tWithDescription(\"User management\")\n\n// Add endpoints to group\nuserGroup.WithEndpoints(\n\tgetUser(),\n\tlistUsers(),\n\tcreateUser(),\n\tupdateUser(),\n\tdeleteUser(),\n)\n\napi.AddGroup(userGroup)\n\n// Routes become:\n// GET /api/v1/users/{id}\n// GET /api/v1/users\n// POST /api/v1/users\n// PUT /api/v1/users/{id}\n// DELETE /api/v1/users/{id}\n```\n\n## 📝 Request Binding\n\nBy default, endpoints use JSON binding. Customize with:\n\n```go\n// JSON Binding (default)\nendpoint.WithBind(rest.JSONBinder[RequestType]())\n\n// Path Parameter Binding\nendpoint.WithBind(rest.PathParamBinder[int](rest.StringToInt))\n\n// Custom Binding\nendpoint.WithBind(func(r *http.Request) (RequestType, error) {\n\t// Custom parsing logic\n\treturn req, nil\n})\n```\n\n## ✍️ Response Writing\n\nDefault JSON response writing can be customized:\n\n```go\n// JSON Response (default)\nendpoint.WithWrite(rest.JSONWriter[ResponseType]())\n\n// Custom Response\nendpoint.WithWrite(func(w http.ResponseWriter, res ResponseType) error {\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\treturn json.NewEncoder(w).Encode(res)\n})\n```\n\n## ✔️ Validation\n\nValidation is opt-in. By default, no validation is performed.\n\nTo enable struct tag validation using go-playground/validator:\n\n```go\nimport \"github.com/reststore/restkit/validation/playground\"\n\ntype CreateUserReq struct {\n    Name  string `json:\"name\" validate:\"required,min=2,max=50\"`\n    Email string `json:\"email\" validate:\"required,email\"`\n    Age   int    `json:\"age\" validate:\"gte=18,lte=120\"`\n}\n```\n\nImporting the playground package automatically enables validation for all endpoints.\n\nSee [go-playground/validator docs](https://github.com/go-playground/validator) for all available tags.\n\n## 🔌 Middleware\n\nRestKit includes common middleware and supports custom middleware:\n\n### Built-in Middleware\n\n```go\n// HTTP request/response logging\napi.WithMiddleware(rest.LoggingMiddleware())\n\n// CORS with default or custom options\napi.WithMiddleware(rest.CORSMiddleware())\n\n// Panic recovery (converts panics to 500 responses)\napi.WithMiddleware(rest.RecoveryMiddleware())\n```\n\n### Custom Middleware\n\n```go\napi.WithMiddleware(func(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// Before handler\n\t\tlog.Printf(\"Request: %s %s\", r.Method, r.URL.Path)\n\t\tnext.ServeHTTP(w, r)\n\t\t// After handler\n\t})\n})\n```\n\nMiddleware runs in the order added and is applied globally to all endpoints.\n\n## 📖 OpenAPI \u0026 Swagger UI\n\nRestKit automatically generates OpenAPI 3.0 specs from your endpoints:\n\n```go\napi.WithSwaggerUI(\"/docs\") // Enable Swagger UI at /docs\n// or keep it empty for default /swagger\n```\n\nAccess at:\n- **Swagger UI**: `/docs`\n- **OpenAPI JSON**: `/docs/openapi.json`\n\nThe spec is generated from:\n- Endpoint titles and descriptions\n- Auto-generated schemas from request/response types\n- HTTP methods and paths\n- Endpoint grouping (becomes API tags)\n\n## 🛣️ Path Parameters\n\nAccess URL parameters in your handler:\n\n```go\nfunc getUser(ctx context.Context) (UserRes, error) {\n\tuserID := rest.URLParam(ctx, \"id\")\n\t// Fetch and return user\n}\n\n// Define endpoint\ngetEndpoint := rest.NewEndpointRes[UserRes]().\n\tWithPath(\"/users/{id}\").\n\tWithHandler(getUser)\n```\n\nParameters are extracted from the path pattern and available in the context.\n\n## ⚠️ Error Handling\n\nRestKit provides standardized error responses with typed error codes:\n\n```go\n// Default error handler (JSON)\nendpoint.WithErrorHandler(rest.JSONErrorWriter)\n\n// Custom error handler\nendpoint.WithErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) {\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tw.WriteHeader(http.StatusBadRequest)\n\tjson.NewEncoder(w).Encode(map[string]string{\n\t\t\"error\": err.Error(),\n\t})\n})\n```\n\nError codes include:\n- `ErrCodeBadRequest` - Malformed requests\n- `ErrCodeValidation` - Validation failures\n- `ErrCodeBind` - Request parsing errors\n- `ErrCodeNotFound` - Resource not found\n- `ErrCodeUnauthorized` - Authentication required\n- `ErrCodeForbidden` - Access denied\n- `ErrCodeInternal` - Server errors\n- `ErrCodeMissingParam` - Missing path parameters\n- `ErrCodeConfiguration` - Endpoint misconfiguration\n\n## 🔍 Schema Generation\n\nSchemas are automatically generated from your Go types for OpenAPI documentation:\n\n```go\ntype User struct {\n\tID    int    `json:\"id\"`\n\tName  string `json:\"name\"`\n\tEmail string `json:\"email\"`\n}\n\n// Schema auto-generated for OpenAPI spec\nendpoint.WithResponseSchema(rest.SchemaFrom[User]())\n\n// Or override manually:\nendpoint.WithResponseSchema(map[string]any{\n\t\"type\": \"object\",\n\t\"properties\": map[string]any{\n\t\t\"id\":    map[string]any{\"type\": \"integer\"},\n\t\t\"name\":  map[string]any{\"type\": \"string\"},\n\t\t\"email\": map[string]any{\"type\": \"string\"},\n\t},\n\t\"required\": []string{\"id\", \"name\", \"email\"},\n})\n```\n\n## 🔀 Router Integration\n\nRestKit is built on Go's standard net/http. Use adapters to integrate with other routers:\n\n### Chi Router Adapter\n\n```go\nimport restchi \"github.com/reststore/restkit/adapters/chi\"\n\n// Register RestKit endpoints with Chi\nchiRouter := chi.NewRouter()\nrestchi.RegisterRoutes(chiRouter, api)\n\n// Start server with Chi router\nhttp.ListenAndServe(\":8080\", chiRouter)\n```\n\n### Mount External Router\n\n```go\n// Mount external Chi router to RestKit API\nrestchi.Mount(api, \"/\", chiRouter,\n\t[]restkit.RouteMeta{\n\t\t{\n\t\t\tMethod: \"GET\",\n\t\t\tPath:   \"/users\",\n\t\t\tInfo: restkit.RouteInfo{\n\t\t\t\tSummary:      \"List users\",\n\t\t\t\tResponseType: []User{},\n\t\t\t},\n\t\t},\n\t)\n```\n\n## 💡 Philosophy\n\nRestKit brings simplicity to Go with compile-time type safety.\nTaking inspiration from frameworks like FastEndpoints in .NET, RestKit provides a familiar, fluent API for defining REST endpoints while leveraging Go's strengths.\n\nThe framework is designed around:\n- **Type Safety** - Catch errors at compile time, not runtime\n- **Minimal Boilerplate** - Get productive quickly\n- **Standard Library** - Built on Go's net/http, no external runtime dependencies\n- **Developer Experience** - Familiar patterns from modern web frameworks\n- **Performance** - Fast HTTP handling without reflection in hot paths\n\n## 🚀 Benchmarks\n\nRestKit keeps performance close to raw handlers while giving you type safety and automatic OpenAPI docs.\nHere's how it stacks up:\n\n### Real-World Performance\n\nTesting against raw Chi and stdlib, RestKit stays competitive:\n\n| What | RestKit | Raw Chi | Stdlib |\n|------|---------|---------|--------|\n| Simple GET | 138 µs | 136 µs | 136 µs |\n| GET with params | 140 µs | 138 µs | 138 µs |\n| POST with JSON | 195 µs | 165 µs | 171 µs |\n\nFor simple endpoints, we're within 1-2% of raw handlers. POST requests show a bit more overhead because RestKit is automatically validating and binding your request types, things you'd normally write by hand.\n\n### Handler-Level Performance\n\nAt the handler level, the overhead is minimal:\n\n```\nHandler call                    6.5 ns\nHandler with path params       6.8 µs\nRoute context creation         474 ns\n```\n\nMost of your time goes into HTTP overhead, network I/O, and your actual business logic, not the framework.\n\n### Benchmark Yourself\n\nWant to see the numbers on your machine? Run:\n\n```bash\ngo test -bench=. -benchmem ./tests\n```\n\nSpecific comparisons:\n\n```bash\n# Just RestKit endpoints\ngo test -bench=RestKit -benchmem ./tests\n\n# Compare RestKit, Chi, and stdlib side-by-side\ngo test -bench='RestKit|Chi|Stdlib' -benchmem ./tests\n```\n\n## 👀 Examples\n\nSee the `examples/` directory for complete working examples:\n\n```bash\n# Basic example with groups and versions\ngo run ./examples/basic\n\n# Chi router integration\ngo run ./examples/chi\n\n# Mounting external Chi router\ngo run ./examples/chi_mount\n```\n\nThen visit `http://localhost:8080/docs` to explore the API.\n\n## 💻 Development\n\nTo contribute to RestKit:\n\n```bash\n# Run tests\ngo test ./...\n\n# Run formatting and linting\ngo fmt ./... \u0026\u0026 gofumpt -l -w . \u0026\u0026 golines -w -m 80 .\n```\n\n## 👍 Contributing\n\nContributions are welcome! Please:\n\n1. Open an issue to discuss your changes\n2. Fork the repository\n3. Create a feature branch\n4. Submit a pull request\n\n## 📄 License\n\nLicensed under the Apache License 2.0. See the [LICENSE](./LICENCE) file for details.\n\nCopyright 2026 Robin Olsen\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freststore%2Frestkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freststore%2Frestkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freststore%2Frestkit/lists"}