{"id":17018104,"url":"https://github.com/krsoninikhil/go-rest-kit","last_synced_at":"2025-07-26T20:32:44.724Z","repository":{"id":199560830,"uuid":"703180773","full_name":"krsoninikhil/go-rest-kit","owner":"krsoninikhil","description":"FastAPI like controllers for gin based Go apps. Ready made packages for quickly setting up REST APIs in Go","archived":false,"fork":false,"pushed_at":"2024-09-13T17:10:31.000Z","size":124,"stargazers_count":26,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-02T06:05:12.684Z","etag":null,"topics":["api","golang","rest","tools"],"latest_commit_sha":null,"homepage":"https://nikhilsoni.me/2024/05/27/fastapi-like-controllers-for-gin-based-go-apps/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/krsoninikhil.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-10T18:42:07.000Z","updated_at":"2024-10-14T08:51:00.000Z","dependencies_parsed_at":"2023-10-11T00:47:40.465Z","dependency_job_id":"e6ede977-da91-481e-a389-97b6fb15f811","html_url":"https://github.com/krsoninikhil/go-rest-kit","commit_stats":null,"previous_names":["krsoninikhil/go-rest-kit"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/krsoninikhil/go-rest-kit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krsoninikhil%2Fgo-rest-kit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krsoninikhil%2Fgo-rest-kit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krsoninikhil%2Fgo-rest-kit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krsoninikhil%2Fgo-rest-kit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krsoninikhil","download_url":"https://codeload.github.com/krsoninikhil/go-rest-kit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krsoninikhil%2Fgo-rest-kit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267227351,"owners_count":24056353,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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","golang","rest","tools"],"created_at":"2024-10-14T06:44:32.291Z","updated_at":"2025-07-26T20:32:44.702Z","avatar_url":"https://github.com/krsoninikhil.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-rest-kit\nReady made packages for quickly setting up REST APIs in Go. \nSpecially avoiding to write handlers and request parsing for every new API you want.\nLimitation here is most packages are helful if you're using Gin for your APIs.\n\n## Motivation\nFrameworks like FastAPI for Python are able to provide automatic request parsing and validation based on type hints\nand Python insn't even a typed language. I could not find any framework providing similar feature in Go, i.e. not \nhaving to repeat the same parsing and error handling in every API handler. \n\nI should be able to write following handler / controller similar to FastAPI by just defining `SpecificRequest` and `SpecificResponse` i.e. get request body type as argument and return response type along with error:\n```go\nfunc myHandler(ctx context.Context, request SpecificRequest) (*SpecificResponse, error) {}\n```\n\n## Setup\nThis module is written with generic usecases in mind, which serves well in most usecase e.g. CRUD APIs. \nIf you have a custom requirement, it's recommended to clone the repo in your development machine and use the local\nversion of the module by replacing module path. This allows you extend and customize \nthe types and methods provided as per your requirement.\n\n```bash\ngo get github.com/krsoninikhil/go-rest-kit\ngit clone github.com/krsoninikhil/go-rest-kit ../\ngo mod edit -replace github.com/krsoninikhil/go-rest-kit=../go-rest-kit\n```\n\n## Example\n\n### 1. Exposing CRUD APIs\nExposing simple CRUD APIs is as simple as following\n- Ensure your model implements `crud.Model`, you can embed `pgdb.BaseModel` to get default implementation for few methods.\n- Define your request and response types and have them implement `crud.Request` and `crud.Response` interfaces.\n- Add routes specifying your request, response and model types\n  \n\u003e This example also shows use of request binding methods, and how you can avoid writing repeated code for parsing request body.\n\n```go\n// models.go\ntype BusinessType struct {\n    Name string\n    Icon string\n    pgdb.BaseModel\n}\n\nfunc (b BusinessType) ResourceName() string { return fmt.Sprintf(\"%T\", b) }\n\n// entities.go\ntype (\n    BusinessTypeRequest struct {\n        Name string `json:\"name\" binding:\"required\"`\n        Icon string `json:\"icon\"`\n    }\n    BusinessTypeResponse struct {\n        BusinessTypeRequest\n        ID int `json:\"id\"`\n    }\n)\n\n// implement `crud.Request`\nfunc (b BusinessTypeRequest) ToModel(_ *gin.Context) BusinessType {\n    return BusinessType{Name: b.Name, Icon: b.Icon}\n}\n\n// implement `crud.Response`\nfunc (b BusinessTypeResponse) FillFromModel(m models.BusinessType) crud.Response[models.BusinessType] {\n    return BusinessTypeResponse{\n        ID: m.ID, \n        BusinessTypeRequest: BusinessTypeRequest{Name: m.Name, Icon: m.Icon},\n    }\n}\nfunc (b BusinessTypeResponse) ItemID() int { return b.ID }\n\n// setup routes\nfunc main() {\n    businessTypeDao        = crud.Dao[models.BusinessType]{PGDB: db} // use your own doa if you need custom implementation\n\tbusinessTypeCtlr = crud.Controller[models.BusinessType, types.BusinessTypeResponse, types.BusinessTypeRequest]{\n        Svc: \u0026businessTypeDao, // using dao for service as no business logic is required here\n    } // prewritten controller struct with CRUD methods\n    \n    r := gin.Default()\n\tr.GET(\"/business-types\", request.BindGet(businessTypeCtlr.Retrieve))\n    r.GET(\"/business-types\", request.BindGet(businessTypeCtlr.List))\n\tr.POST(\"/business-types\", request.BindCreate(businessTypeCtlr.Create))\n\tr.PATCH(\"/business-types\", request.BindUpdate(businessTypeCtlr.Update))\n\tr.DELETE(\"/business-types\", request.BindDelete(businessTypeCtlr.Delete))\n    // start your server\n}\n```\n\nBest part here is -- you can replace any component (controller, usecase or dao) with your own implementation.\n\n### 2. Load Your Application Config\nConfigs are loaded from yaml files where empty values are overriden from environment, which is set using `.env` file.\ne.g. if `redis.password` in your yaml is empty, it will be set by `REDIS_PASSWORD` env value. Neat, Hmm?\n\n```go\n// define application config\ntype Config struct {\n    DB pgdb.Config\n    Twilio twilio.Config\n    Auth auth.Config\n    Env string\n}\n// implement `config.AppConfig`\nfunc (c *Config) EnvPath() string    { return \"./.env\" } // path to your .env file\nfunc (c *Config) SourcePath() string { return fmt.Sprintf(\"./api/%s.yml\", c.Env) } // path to your yaml configuration file\nfunc (c *Config) SetEnv(env string) { c.Env = env } // embed `config.BaseConfig` to avoid defining SetEnv\n\nfunc main() {\n    var (\n        ctx = context.Background()\n\t    conf Config\n    )\n\tconfig.Load(ctx, \u0026conf)\n    // that's about it, you use the `conf` now, e.g. see below usage for creating postgres connection\n    db := pgdb.NewPGConnection(ctx, conf.DB)\n}\n```\n\n### 3. Exposing Auth APIs -- Signup, OTP Verification and Token Refresh\n\u003e This also shows an example use of `pgdb` and `twillio` packages.\n\nAssuming you have a `models.User` already defined, exposing auth APIs are just about defining your routes. Easy peazy!\n\n```go\nfunc main() {\n    // reusing gin engine `r`, configuration `conf` and postgres connection `db` from above examples\n    var (\n        cache          = cache.NewInMemory() // im memory cache impelementation is provided for the purpose of examples\n        // injecting dependencies, use your own implementation for any object if default isn't enough for your usecase\n\t\tuserDao        = auth.NewUserDao[models.User](db)\n\t\tauthSvc        = auth.NewService(conf.Auth, userDao)\n\t\tsmsProvider    = twilio.NewClient(conf.Auth.Twilio)\n\t\totpSvc         = auth.NewOTPSvc(conf.Auth.OTP, smsProvider, cache) // \n\t\tauthController = auth.NewController(authSvc, otpSvc, cache)\n\t)\n\n\tr.POST(\"/auth/otp/send\", request.BindCreate(authController.SendOTP))\n\tr.POST(\"/auth/otp/verify\", request.BindCreate(authController.VerifyOTP))\n\tr.POST(\"/auth/token/refresh\", request.BindCreate(authController.RefreshToken))\n\tr.GET(\"/countries/:alpha2Code\", request.BindGet(authController.CountryInfo))\n    // start your server\n}\n```\n\n### Getting Rid Of Repeated Code For Request Parsing In Every Handler\nIf you usecase is not a typical CRUD, don't worry, you can still use the generic binding from `request` package.\nWhile `request.BindGet` would parse only the query string for GET request, `request.BindAll` would parse values\nfrom request uri, body and query based on the tags defined in request struct.\n\n```go\nfunc main() {\n    r := gin.Default()\n    r.GET(\"/business-types/insights\", request.BindGet(businessTypeInsights))\n    r.GET(\"/business-types/insights-2\", request.BindAll(businessTypeInsights))\n}\n\ntype (\n    RequestType struct {}\n    ResponseType struct {}\n)\n\nfunc businessTypeInsights(c *gin.Context, req RequestType) (*ResponseType, error) {\n    // your customer controller\n    return nil, apperrors.NewServerError(errors.New(\"not implemented\"))\n}\n\n```\n\nSee full example for better understanding the implementation and usage [here](./examples/main.go).\n\n## Packages Implementation Details\n\n- `request`: Provides parameter binding based on defined request type, this allows controllers to receive the request parameters and body as a argument and not have to parse and unmarshal the request in every controller.\n    - `request.WithBinding` takes a fast-api like controller as argument and converts it to a `gin` controller.\n    - `request.BindGet`, `request.BindCreate`, `request.BindUpdate` and `request.BindDelete` all takes a method and converts it go `gin` controller while providing parsed and validated request body to the function argument. Since these binding methods require the function signature to be defined, it assumes that the `Get` and `Delete` binding expects the argument struct to be parsed from URI and query params while `Update` and `Delete` exepects a struct for parsing URI and another for request body. See example to a better idea of usage.\n\n- `crud`: Provides controllers for any resource like which request typical CRUD apis. These controller methods follow the signature that can be used directly with above explained `request` package binding methods. CRUD apis for any new model become just about registering these controllers with router. See example.\n    - `crud.Controller`: Controller for a resource like `GET /resource`\n    - `crud.NestedController`: Controller for a nested resources like `GET /parent/:parentID/resource`\n\n- `apperrors`: Provides error that any typical API exposing application will require. Idea is to add more as per your requirement.\n\n- `config`: Provides quick method to load and parse your config files to the provide struct. See example.\n\n- `pgdb`: Provides config and constructor to create a new connection. See example.\n  \n- `integrations`: Provides frequently used third party client like Twilio for sending OTPs.\n  \n- `auth`: Almost all backend apps will require API to signup by a mobile no. and respond with JWT token on OTP verification. This also comes with controller for refreshing the tokens.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrsoninikhil%2Fgo-rest-kit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrsoninikhil%2Fgo-rest-kit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrsoninikhil%2Fgo-rest-kit/lists"}