{"id":23340213,"url":"https://github.com/sierrasoftworks/girder","last_synced_at":"2025-06-13T00:03:26.192Z","repository":{"id":71482049,"uuid":"66298655","full_name":"SierraSoftworks/girder","owner":"SierraSoftworks","description":"Girder is an oppinionated Go web API toolkit","archived":false,"fork":false,"pushed_at":"2023-12-18T23:02:29.000Z","size":581,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-13T17:17:29.078Z","etag":null,"topics":["framework","golang","gorilla-mux","rest-api"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SierraSoftworks.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":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-08-22T18:41:12.000Z","updated_at":"2023-02-24T17:50:03.000Z","dependencies_parsed_at":"2023-12-19T01:54:31.843Z","dependency_job_id":"30717f07-0844-4fbd-9627-b802ffaa858c","html_url":"https://github.com/SierraSoftworks/girder","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SierraSoftworks%2Fgirder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SierraSoftworks%2Fgirder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SierraSoftworks%2Fgirder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SierraSoftworks%2Fgirder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SierraSoftworks","download_url":"https://codeload.github.com/SierraSoftworks/girder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247675283,"owners_count":20977373,"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":["framework","golang","gorilla-mux","rest-api"],"created_at":"2024-12-21T04:20:11.090Z","updated_at":"2025-04-07T14:45:13.855Z","avatar_url":"https://github.com/SierraSoftworks.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Girder\n**A Go web API toolkit designed to reduce common boilerplate**\n\n**⚠ WARNING** Opinionated code ahead\n\n Girder is a relatively opinionated toolkit, it assumes you will be building\n an API which consumes structured, serializable objects (JSON for example) and\n then produces responses in a similar format.\n\n It has been inspired from a wide number of different projects I've developed over\n the years on everything from C# to Node.js and finally Go, so it'll take inspiration\n from some of those along the way. That being said, Girder doesn't aim to be a\n framework upon which you'll build a full application - instead it is meant to provide\n just the glue between your handlers and the `http` layer.\n\n## Example\n\n ```go\npackage main\n\nimport (\n    \"fmt\"\n    \"log\"\n    \"net/http\"\n\n    \"github.com/SierraSoftworks/girder\"\n    \"github.com/gorilla/mux\"\n)\n\nfunc hello(c *girder.Context) (interface{}, error) {\n    return fmt.Sprintf(\"Hello %s\", c.Vars[\"name\"]), nil\n}\n\nfunc main() {\n    h := girder.NewHandler(hello)\n\n    r := mux.NewRouter()\n    r.Path(\"/api/v1/hello/{name}\").Method(\"GET\").Handler(h)\n\n    if err := http.ListenAndServe(\":8080\", r); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n## Design\nGirder is designed such that all requests are routed through a `girder.Handler`. This handler\nis responsible for all request pre-processing, dispatching the request and its context to your\nhandler function, and finally serializing the response from your handler function into the response.\n\nIn addition to this, it is responsible for converting any errors you return into a well formatted\nerror object.\n\nA `girder.HandlerFunc` looks like this, keeping things nice and simple to write and with very little\noverhead.\n\n```go\nfunc handlerFunc(c *girder.Context) (interface{}, error) {\n    return MyData{\"x\"}, nil\n}\n```\n\nGirder's handlers have a `Preprocessors` slice which contains functions which will be executed\nbefore your handler. These functions may optionally return an error to bypass further execution\nand are an excellent place to handle things like authentication and authorization or logging.\n\n## Usage\n\n### Deserializing a Request\nYou'll commonly implement systems in which you accept data as part of a `POST` request's body.\nIn these cases, you'll want an easy way to deserialize the request into some object of your\nchoosing. Girder makes this spectacularly simple, here's a quick echo function.\n\n```go\nfunc handlerFunc(c *girder.Context) (interface{}, error) {\n    var req RequestData\n    if err := c.ReadBody(\u0026req); err != nil {\n        return nil, err\n    }\n\n    return req, nil\n}\n```\n\n### Accessing Gorilla Mux Route Parameters\nGirder expects that you, like every other Go developer, will be using [Gorilla Mux](https://github.com/gorilla/mux)\nas your router of choice. One of the great features it provides out of the box is support for route\nparameters. You can access your route parameters directly from the context using the `Vars` property.\n\n```go\n// GET /api/v1/hello/{name}\nfunc handlerFunc(c *girder.Context) (interface{}, error) {\n    name := c.Vars[\"name\"]\n    return fmt.Sprintf(\"Hello %s\", name), nil\n}\n```\n\n### User Authentication\nUser authentication is a common enough use case that we've decided to build it into Girder\nout of the box. Users are provided by a callback when you register your authorization preprocessor\nand are expected to provide both a `GetID()` method (for use within your application) and a\n`GetPermissions()` method which allows Girder to determine whether the user has permission to\naccess a route or not.\n\n```go\npackage main\n\nimport (\n    \"net/http\"\n\n    \"github.com/SierraSoftworks/girder\"\n    \"github.com/SierraSoftworks/girder/errors\"\n    \"github.com/gorilla/mux\"\n)\n\ntype UserStore struct {\n    users []User\n}\n\nfunc (s *UserStore) GetUser(token *girder.AuthorizationToken) (girder.User, error) {\n    if token.Type != \"Token\" {\n        return nil, errors.NewError(401, \"Unauthorized\", \"You failed to provide a valid authentication token type with your request.\")\n    }\n\n    for _, user := range s.users {\n        for _, t := range user.tokens {\n            if t == token.Value {\n                return user, nil\n            }\n        }\n    }\n\n    return nil, nil\n}\n\ntype User struct {\n    id          string\n    permissions []string\n    tokens      []string\n}\n\n// Extend your user type with the GetID() and GetPermissions() functions\nfunc (u *User) GetID() string {\n    return u.id\n}\n\nfunc (u *User) GetPermissions() []string {\n    return u.permissions\n}\n\n// GET /api/v1/hello\nfunc hello(c *girder.Context) (interface{}, error) {\n    user, err := users.GetByID(c.User.ID())\n    if err != nil {\n        return nil, errors.From(err)\n    }\n\n    return fmt.Sprintf(\"Hello %s\", user.Name), nil\n}\n\nfunc main() {\n    // Point girder at your user store\n    store := \u0026UserStore{\n        users: []User{\n            User{\n                id: \"bob\",\n                tokens: []string{\"0123456789abcdef\"},\n                permissions: []string{\"hello\"},\n            },\n        },\n    }\n\n    r := mux.NewRouter()\n    r.Path(\"/api/v1/hello\").Handler(girder.NewHandler(hello).RequireAuthentication(store.GetUser).RequirePermission(\"hello\"))\n\n    http.ListenAndServe(\":8080\", r)\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsierrasoftworks%2Fgirder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsierrasoftworks%2Fgirder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsierrasoftworks%2Fgirder/lists"}