{"id":26356477,"url":"https://github.com/dolanor/rip","last_synced_at":"2026-03-09T07:31:29.325Z","repository":{"id":142421806,"uuid":"428455177","full_name":"dolanor/rip","owner":"dolanor","description":"REST in peace","archived":false,"fork":false,"pushed_at":"2026-02-25T00:02:39.000Z","size":787,"stargazers_count":88,"open_issues_count":18,"forks_count":1,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-02-25T05:35:43.716Z","etag":null,"topics":["hacktoberfest","rest","rest-api","restful-api"],"latest_commit_sha":null,"homepage":"https://rip.rest","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dolanor.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-11-15T23:39:03.000Z","updated_at":"2026-02-25T00:02:43.000Z","dependencies_parsed_at":null,"dependency_job_id":"40ca5b87-ae38-429e-954b-d033fa72dbc9","html_url":"https://github.com/dolanor/rip","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/dolanor/rip","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolanor%2Frip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolanor%2Frip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolanor%2Frip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolanor%2Frip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dolanor","download_url":"https://codeload.github.com/dolanor/rip/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dolanor%2Frip/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30287425,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: 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":["hacktoberfest","rest","rest-api","restful-api"],"created_at":"2025-03-16T13:30:39.107Z","updated_at":"2026-03-09T07:31:29.295Z","avatar_url":"https://github.com/dolanor.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RIP ⚰ [![Go Reference](https://pkg.go.dev/badge/github.com/dolanor/rip.svg)](https://pkg.go.dev/github.com/dolanor/rip) [![Go Report Card](https://goreportcard.com/badge/github.com/dolanor/rip)](https://goreportcard.com/report/github.com/dolanor/rip)\n\nREST in peace\n\n![gopher resting in peace](.meta/assets/rip.png)\n\n## TL;DR\n\nLook at the [examples](examples).\n\nThe smallest/simplest is the one with the [GORM provider](examples/gormprovider/main.go).\n\n## Why?\n\nCreating RESTful API in Go is in a way simple and fun in the first time, but also repetitive and error prone the more resources you handle.  \nCopy pasting nearly the same code for each resource you want to GET or POST to except for the request and response types is not that cool, and `interface{}` neither.  \nLet's get the best of both worlds with **GENERICS** 🎆 *everybody screams* 😱  \n\n## How?\n\nThe idea would be to use the classic `net/http` package with handlers created from Go types.\n\n```go\nhttp.HandleFunc(rip.HandleEntities(\"/users\", NewUserProvider(), nil))\n```\n\nand it would generate all the necessary boilerplate to have some sane (IMO) HTTP routes.\n```go\n// HandleEntities associates an urlPath with an entity provider, and handles all HTTP requests in a RESTful way:\n//\n//\tPOST   /entities/    : creates the entity\n//\tGET    /entities/:id : get the entity\n//\tPUT    /entities/:id : updates the entity (needs to pass the full entity data)\n//\tDELETE /entities/:id : deletes the entity\n//\tGET    /entities/    : lists the entities (accepts page and page_size query param)\n//\n// It also handles fields\n//\n//\tGET    /entities/:id/name : get only the name field of the entity\n//\tPUT    /entities/:id/name : updates only the name entity field\n\n```\n\n\ngiven that `UserProvider` implements the `rip.EntityProvider` interface\n\n```go\ntype EntityProvider[Ent any] interface {\n\tCreate(ctx context.Context, ent Ent) (Ent, error)\n\tGet(ctx context.Context, id string) (Ent, error)\n\tUpdate(ctx context.Context, ent Ent) error\n\tDelete(ctx context.Context, id string) error\n\tList(ctx context.Context, offset, limit int) ([]Ent, error)\n}\n```\n\nA few providers are already available in [providers](providers) and allow for 1-line implementation of a CRUD backend for a custom type. With:\n\n```go\n\tp := gormprovider.New[Album](db, logger)\n```\n\nYou have a provider you can pass to `rip.HandleEntities()` and get a full REST server running, querying and saving data in a database.\n\n⚠️: Disclaimer, the API is not stable yet, use or contribute at your own risks\n\n\n\\* *Final code may differ from actual shown footage*\n\n## Play with it\n\n```console\ngo run github.com/dolanor/rip/examples/srv-example@latest\n// open your browser to http://localhost:8888/users/ and start editing users\n```\n\n## Features\n\n- support for multiple encoding automatically selected with `Accept` and `Content-Type` headers, or entity extension `/entities/1.json`\n  - JSON\n  - protobuf\n  - YAML\n  - XML\n  - msgpack\n  - HTML (read version)\n  - HTML forms (write version)\n- middlewares\n- automatic generation of HTML forms for live editing of entities\n\n### Encoding\n\nYou can add your own encoding for your own mime type (I plan on adding some domain type encoding for specific entities, see #13).\nIt is quite easy to create if your encoding API follows generic standard library encoding packages like `encoding/json`. [Here is how `encoding/json` codec is implemented for RIP](encoding/json/json.go)\n\n## Talks\n\nI gave a [talk at GoLab 2023](https://www.youtube.com/watch?v=_OgqCKrONX8).\nI presented it again at [FOSDEM 2024](https://www.youtube.com/watch?v=Z9DOhBCpQi4).\n\nThe slides are [in my talks repository](https://github.com/dolanor/talks/blob/main/rip/rip.slide)\n\n(The FOSDEM talk present the more up-to-date API (per-route handler options), demo video (instead of live coding), + a live 3D demo, BUT, I couldn't display my note, so a lot of hesitation and parasite words, sorry about that)\n\n\n## TODO\n\n- [x] middleware support\n- [ ] I'd like to have more composability in the entity provider (some are read-only, some can't list, some are write only…), haven't figured out the right way to design that, yet.\n- [ ] it should work for nested entities\n- [ ] improve the error API\n- [ ] support for hypermedia discoverability\n- [x] support for multiple data representation\n- [ ] add automatic OpenAPI schema\n- [ ] add automatic API client\n\n## Thanks\n\n- logo from Thierry Pfeiffer\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdolanor%2Frip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdolanor%2Frip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdolanor%2Frip/lists"}