{"id":17882193,"url":"https://github.com/mackee/tanukirpc","last_synced_at":"2025-03-22T12:31:35.727Z","repository":{"id":250998199,"uuid":"835675485","full_name":"mackee/tanukirpc","owner":"mackee","description":"`tanukirpc` is a practical, fast-developing, type-safe, and easy-to-use RPC/Router library for Go.","archived":false,"fork":false,"pushed_at":"2025-02-14T17:24:25.000Z","size":156,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-14T16:03:57.036Z","etag":null,"topics":["go","golang","router","rpc-framework","web-application","web-framework"],"latest_commit_sha":null,"homepage":"","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/mackee.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":"2024-07-30T10:05:55.000Z","updated_at":"2025-02-15T07:07:27.000Z","dependencies_parsed_at":"2024-07-31T07:59:04.479Z","dependency_job_id":"72acb42f-f516-44f2-a5e6-b7d2b8527a36","html_url":"https://github.com/mackee/tanukirpc","commit_stats":null,"previous_names":["mackee/tanukirpc"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mackee%2Ftanukirpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mackee%2Ftanukirpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mackee%2Ftanukirpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mackee%2Ftanukirpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mackee","download_url":"https://codeload.github.com/mackee/tanukirpc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244959443,"owners_count":20538625,"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","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":["go","golang","router","rpc-framework","web-application","web-framework"],"created_at":"2024-10-28T12:48:42.599Z","updated_at":"2025-03-22T12:31:35.711Z","avatar_url":"https://github.com/mackee.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tanukirpc\n\n`tanukirpc` is a practical, fast-developing, type-safe, and easy-to-use RPC/Router library for Go. This library base on [`go-chi/chi`](https://github.com/go-chi/chi).\n\n## Installation\n\n```bash\ngo get -u github.com/mackee/tanukirpc\n```\n\n## Usage\n\nThis is a simple example of how to use `tanukirpc`.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/mackee/tanukirpc\"\n)\n\ntype helloRequest struct {\n\tName string `urlparam:\"name\"`\n}\n\ntype helloResponse struct {\n\tMessage string `json:\"message\"`\n}\n\nfunc hello(ctx tanukirpc.Context[struct{}], req helloRequest) (*helloResponse, error) {\n\treturn \u0026helloResponse{\n\t\tMessage: fmt.Sprintf(\"Hello, %s!\", req.Name),\n\t}, nil\n}\n\nfunc main() {\n\tr := tanukirpc.NewRouter(struct{}{})\n\tr.Get(\"/hello/{name}\", tanukirpc.NewHandler(hello))\n\n\tif err := r.ListenAndServe(context.Background(), \":8080\"); err != nil {\n\t\tfmt.Println(err)\n\t}\n}\n```\n\n## Features\n\n- :o: Type-safe request/response handler\n- :o: URL parameter, Query String, JSON, Form, or custom binding\n- :o: Request validation by [go-playground/validator](https://github.com/go-playground/validator)\n- :o: Custom error handling\n- :o: Registry injection\n  - for a Dependency Injection\n- :o: A development server command that automatically restarts on file changes\n  - use `tanukiup` command\n- :o: Generate TypeScript client code\n  - use `gentypescript` command\n- :o: defer hooks for cleanup\n- :o: Session management\n- :o: Authentication flow\n  - :o: OpenID Connect\n\n### Registry injection\n\nRegistry injection is unique feature of `tanukirpc`. You can inject a registry object to the handler function.\n\nAdditionally, Registry can be generated for each request. For more details, please refer to [_example/simple-registry](./_example/simple-registry).\n\n#### Use case\n\n* Database connection\n* Logger\n* Authentication information\n* Resource binding by path parameter. Examples can be found in [_example/todo](./_example/todo).\n\n### Request binding\n\n`tanukirpc` supports the following request bindings by default:\n\n* URL parameter (like a `/entity/{id}` path): use the `urlparam` struct tag\n* Query String: use the `query` struct tag\n* JSON (`application/json`): use the `json` struct tag\n* Form (`application/x-www-form-urlencoded`): use the `form` struct tag\n* Raw Body: use the `rawbody` struct tag with []byte or io.ReadCloser\n  * also support naked []byte or io.ReadCloser\n\nIf you want to use other bindings, you can implement the `tanukirpc.Codec` interface and specify it using the `tanukirpc.WithCodec` option when initializing the router.\n\n```go\ntanukirpc.NewRouter(YourRegistry, tanukirpc.WithCodec(yourCodec))\n```\n\n### Request validation\n\n`tanukirpc` automatically validation by `go-playground/validator` when contains `validate` struct tag in request struct.\n\n```go\ntype YourRequest struct {\n    Name string `form:\"name\" validate:\"required\"`\n}\n```\n\nIf you want to use custom validation, you can implement the `tanukirpc.Validatable` interface in your request struct. `tanukirpc` will call the `Validatable.Validate` method after binding the request and before calling the handler function.\n\n### Error handling\n\n`tanukirpc` has a default error handler. If you want to use custom error handling, you can implement the `tanukirpc.ErrorHooker` interface and use this with the `tanukirpc.WithErrorHooker` option when initializing the router.\n\n#### Response with Status Code\n\nIf you want to return a response with a specific status code, you can use the `tanukirpc.WrapErrorWithStatus`.\n\n```go\n// this handler returns a 404 status code\nfunc notFoundHandler(ctx tanukirpc.Context[struct{}], struct{}) (*struct{}, error) {\n    return nil, tanukirpc.WrapErrorWithStatus(http.StatusNotFound, errors.New(\"not found\"))\n}\n```\n\nAlso, you can use the `tanukirpc.ErrorRedirectTo` function. This function returns a response with a 3xx status code and a `Location` header.\n\n```go\n// this handler returns a 301 status code\nfunc redirectHandler(ctx tanukirpc.Context[struct{}], struct{}) (*struct{}, error) {\n    return nil, tanukirpc.ErrorRedirectTo(http.StatusMovedPermanently, \"/new-location\")\n}\n```\n\n### Middleware\n\nYou can use `tanukirpc` with [go-chi/chi/middleware](https://pkg.go.dev/github.com/go-chi/chi/v5@v5.1.0/middleware) or `func (http.Handler) http.Handler` style middlewares. [gorilla/handlers](https://pkg.go.dev/github.com/gorilla/handlers) is also included in this.\n\nIf you want to use middleware, you can use `*Router.Use` or `*Router.With`.\n\n### `tanukiup` command\n\nThe `tanukiup` command is very useful during development. When you start your server via the `tanukiup` command, it detects file changes, triggers a build, and restarts the server.\n\n### Usage\nYou can use the `tanukiup` command as follows:\n```sh\n$ go run github.com/mackee/tanukirpc/cmd/tanukiup -dir ./...\n```\n\n- The `-dir` option specifies the directory to be watched. By appending `...` to the end, it recursively includes all subdirectories in the watch scope. If you want to exclude certain directories, use the `-ignore-dir` option. You can specify multiple directories by providing comma-separated values or by using the option multiple times. By default, the server will restart when files with the `.go` extension are updated.\n\n- The `-addr` option allows the `tanukiup` command to act as a server itself. After building and starting the server application created with `tanukirpc`, it proxies requests to this process. The application must be started with `*tanukirpc.Router.ListenAndServe`; otherwise, the `-addr` option will not function. Only the paths registered with `tanukirpc.Router` will be proxied to the server application.\n\n- Additionally, there is an option called `-catchall-target` that can be used in conjunction with `-addr`. This option allows you to proxy requests for paths that are not registered with `tanukirpc.Router` to another server address. This is particularly useful when working with a frontend development server (e.g., webpack, vite).\n\nAdditionally, it detects the `go:generate` lines for the `gentypescript` command mentioned later, and automatically runs them before restarting.\n\n### Client code generation\n\nA web application server using `tanukirpc` can generate client-side code based on the type information of each endpoint.\n\n`gentypescript` generates client-side code specifically for TypeScript. By using the generated client implementation, you can send and receive API requests with type safety for each endpoint.\n\nTo generate the client code, first call `genclient.AnalyzeTarget` with the router as an argument to clearly define the target router.\n\nNext, add the following go:generate line:\n\n```go\n//go:generate go run github.com/mackee/tanukirpc/cmd/gentypescript -out ./frontend/src/client.ts ./\n```\n\nThe `-out` option specifies the output file name. Additionally, append `./` to specify the package to be analyzed.\n\nWhen you run `go generate ./` in the package containing this file, or when you start the server via the aforementioned `tanukiup` command, the TypeScript client code will be generated.\n\nFor more detailed usage, refer to the [_example/todo](./_example/todo) directory.\n\n### Defer hooks\n\n`tanukirpc` supports defer hooks for cleanup. You can register a function to be called after the handler function has been executed.\n\n```go\nfunc (ctx *tanukirpc.Context[struct{}], struct{}) (*struct{}, error) {\n    ctx.Defer(func() error {\n        // Close the database connection, release resources, logging, enqueue job etc...\n    })\n    return \u0026struct{}{}, nil\n}\n```\n\n### Session Management\n\n`tanukirpc` provides convenient utilities for session management. You can use the `gorilla/sessions` package or other session management libraries.\n\nTo get started, create a session store and wrap it using `tanukirpc/auth/gorilla.NewStore`.\n```go\nimport (\n    \"github.com/gorilla/sessions\"\n    \"github.com/mackee/tanukirpc/sessions/gorilla\"\n    tsessions \"github.com/mackee/tanukirpc/sessions\"\n)\n\nfunc newStore(secrets []byte) (tsessions.Store, error) {\n    sessionStore := sessions.NewCookieStore(secrets)\n    store, err := gorilla.NewStore(sessionStore)\n    if err != nil {\n        return nil, err\n    }\n    return store, nil\n}\n```\n\nIn `RegistryFactory`, you can create a session using the `tanukirpc/sessions.Store`.\n\n```go\ntype RegistryFactory struct {\n    Store tsessions.Store\n}\n\ntype Registry struct {\n    sessionAccessor tsessions.Accessor\n}\n\nfunc (r *RegistryFactory) NewRegistry(w http.ResponseWriter, req *http.Request) (*Registry, error) {\n\taccessor, err := r.Store.GetAccessor(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get session accessor: %w\", err)\n\t}\n\n    return \u0026Registry{\n        sessionAccessor: accessor,\n    }, nil\n}\n\nfunc (r *Registry) Session() tsessions.Accessor {\n    return r.sessionAccessor\n}\n```\n\nThe `Registry` type implements the `tanukirpc/sessions.RegistryWithAccessor` interface.\n\n### Authentication Flow\n\n`tanukirpc` supports the OpenID Connect authentication flow. You can use the `tanukirpc/auth/oidc.NewHandlers` function to create handlers for this flow, which includes a set of handlers to facilitate user authentication.\n\n#### Requirements\n\n`tanukirpc/auth/oidc.Handlers` requires a `Registry` that implements the `tanukirpc/sessions.RegistryWithAccessor` interface. For more details, refer to the [Session Management](#session-management) section.\n\n#### Usage\n\n```go\noidcAuth := oidc.NewHandlers(\n    oauth2Config, // *golang.org/x/oauth2.Config\n    provider,     // *github.com/coreos/go-oidc/v3/oidc.Provider\n)\nrouter.Route(\"/auth\", func(router *tanukirpc.Router[*Registry]) {\n    router.Get(\"/redirect\", tanukirpc.NewHandler(oidcAuth.Redirect))\n    router.Get(\"/callback\", tanukirpc.NewHandler(oidcAuth.Callback))\n    router.Get(\"/logout\", tanukirpc.NewHandler(oidcAuth.Logout))\n})\n```\n\n## License\n\nCopyright (c) 2024- [mackee](https://github.com/mackee)\n\nLicensed under MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmackee%2Ftanukirpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmackee%2Ftanukirpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmackee%2Ftanukirpc/lists"}