{"id":42572718,"url":"https://github.com/go-humble/rest","last_synced_at":"2026-01-28T21:24:10.591Z","repository":{"id":32014785,"uuid":"35585907","full_name":"go-humble/rest","owner":"go-humble","description":"A small go package for sending requests to a RESTful API and unmarshaling the response. Compiles to javascript via gopherjs.","archived":false,"fork":false,"pushed_at":"2017-05-20T21:41:48.000Z","size":4496,"stargazers_count":12,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-06-20T02:09:47.104Z","etag":null,"topics":["go","gopherjs"],"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/go-humble.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-14T02:20:14.000Z","updated_at":"2022-12-01T05:14:52.000Z","dependencies_parsed_at":"2022-09-02T20:21:56.524Z","dependency_job_id":null,"html_url":"https://github.com/go-humble/rest","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/go-humble/rest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-humble%2Frest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-humble%2Frest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-humble%2Frest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-humble%2Frest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-humble","download_url":"https://codeload.github.com/go-humble/rest/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-humble%2Frest/sbom","scorecard":{"id":431982,"data":{"date":"2025-08-11","repo":{"name":"github.com/go-humble/rest","commit":"b6425c1a8c3fd1ed0bc881df9e6178a977319e7d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: test/server/tmp/runner-build:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-19T03:35:31.855Z","repository_id":32014785,"created_at":"2025-08-19T03:35:31.855Z","updated_at":"2025-08-19T03:35:31.855Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28852375,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T15:15:36.453Z","status":"ssl_error","status_checked_at":"2026-01-28T15:15:13.020Z","response_time":57,"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":["go","gopherjs"],"created_at":"2026-01-28T21:24:09.977Z","updated_at":"2026-01-28T21:24:10.574Z","avatar_url":"https://github.com/go-humble.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"Humble/Rest\n=============\n\n[![Version](https://img.shields.io/badge/version-0.2.0-5272B4.svg)](https://github.com/go-humble/rest/releases)\n[![GoDoc](https://godoc.org/github.com/go-humble/rest?status.svg)](https://godoc.org/github.com/go-humble/rest)\n\nA small go package for sending requests to a RESTful API and unmarshaling the\nresponse. Rest sends requests using CRUD semantics. It supports requests with a\nContent-Type of either application/x-www-form-urlencoded or application/json and\nparses json responses from the server. Rest works great as a stand-alone package\nor in combination with other [Humble](https://github.com/go-humble) packages.\n\nRest is written in pure go. It feels like go, follows go idioms when possible, and\ncompiles with the go tools. But it is meant to be compiled to javascript and run\nin the browser.\n\n\nBrowser Support\n---------------\n\nRest works with IE9+ (with a\n[polyfill for typed arrays](https://github.com/inexorabletash/polyfill/blob/master/typedarray.js))\nand all other modern browsers. Rest compiles to javascript via\n[gopherjs](https://github.com/gopherjs/gopherjs) and this is a gopherjs\nlimitation.\n\nRest is regularly tested with the latest versions of Firefox, Chrome, and Safari on Mac OS.\nEach major or minor release is tested with IE9+ and the latest versions of Firefox and Chrome\non Windows.\n\n\nInstallation\n------------\n\nInstall rest like you would any other go package:\n\n```bash\ngo get github.com/go-humble/rest\n```\n\nYou will also need to install gopherjs if you don't already have it. The latest version is\nrecommended. Install gopherjs with:\n\n```\ngo get -u github.com/gopherjs/gopherjs\n```\n\n\nQuickstart Guide\n----------------\n\nRest follows CRUD semantics, so there are methods for\n[`Create`](https://godoc.org/github.com/go-humble/rest/#Client.Create),\n[`Read`](https://godoc.org/github.com/go-humble/rest/#Client.Read),\n[`Update`](https://godoc.org/github.com/go-humble/rest/#Client.Update), and\n[`Delete`](https://godoc.org/github.com/go-humble/rest/#Client.Delete).\nIn addition, there is a method for getting all of a specific type of resources, which we\ncall [`ReadAll`](https://godoc.org/github.com/go-humble/rest/#Client.ReadAll).\n\n### The Model Interface\n\nThe `Create`, `Read`, `Update`, `Delete`, and `ReadAll` methods all expect `Model`\n(or a slice of `Model`) as an argument.\n[`Model`](https://godoc.org/github.com/go-humble/rest/#Model) is an interface\nwhich all your models should implement. It consists of only two methods:\n\n``` go\ntype Model interface {\n\t// ModelId returns a unique identifier for the model. It is used for determining\n\t// which URL to send a request to.\n\tModelId() string\n\t// RootURL returns the url for the REST resource corresponding to this model.\n\t// If you want to send requests to the same server, it should look something\n\t// like \"/todos\". If you want to send requests to a different server, you can\n\t// include the entire domain in the url, e.g. \"http://example.com/todos\". Note\n\t// that the trailing slash should not be included.\n\tRootURL() string\n}\n```\n\nBecause of the way reflection is used to encode the data, a Model must have an\nunderlying type of either a struct or a pointer to a struct, and any fields you want\nto be included in requests/responses need to be exported.\n\nIf you like, you can embed [`DefaultId`](https://godoc.org/github.com/go-humble/rest/#DefaultId)\nto give your models an `Id` property and a `ModelId` method which simply returns it.\n\nHere's a full example of a Todo type which implements `Model`:\n\n``` go\ntype Todo struct {\n\tTitle        string\n\tIsCompleted  bool\n\trest.DefaultId\n}\n\nfunc (t *Todo) RootURL() {\n\t\"/todos\"\n}\n```\n\n### Instantiating a Client\n\nBefore sending any requests, you need to instantiate a new client. Typically, you will only need\nto do this once per application. It's sometimes a good idea to make this a top-level variable.\n\n``` go\nvar client = rest.NewClient()\n```\n\nYou can set the `ContentType` property of the client to change the Content-Type header of all\nrequests sent. By default, all new clients have a `ContentType` of `ContentURLEncoded`, which\ncorresponds to the header value \"application/x-www-form-urlencoded\". Alternatively, you can\nset the `ContentType` to `ContentJSON` in order to send requests with the Content-Type header\n\"application/json\". Rest will automatically encode the body of requests based on the header.\n\n```go\n// Create a new client which uses json instead of url encoding\nvar client = \u0026rest.Client{\n\tContentType: ContentJSON,\n}\n```\n\n### Create\n\nThe [`Create`](https://godoc.org/github.com/go-humble/rest/#Client.Create) method sends a POST\nrequest to the model's root url. It is used to create new models on the server. Create will\nmutate the given model, setting its fields based on the response from the server.\n\n``` go\ntodo := \u0026Todo{\n\tTitle: \"Discover the meaning of life\",\n}\nif err := client.Create(todo); err != nil {\n\t// Handle err\n}\n```\n\nIf you are using url encoding, the request sent to the server in the above example would look\nlike this:\n\n```\nPOST /todos\n\nTitle=Discover%20the%20meaning%20of%20life\n```\n\nAnd the response from the server should look like this:\n\n``` json\n{\n\t\"Id\": \"9fjq293n8fw8\",\n\t\"Title\": \"Discover the meaning of life\",\n\t\"IsCompleted\": false\n}\n```\n\n### Read\n\nThe [`Read`](https://godoc.org/github.com/go-humble/rest/#Client.Read) method sends a GET\nrequest to the model's root url with the given id appended. It is used to get existing models\nfrom the server. Read will mutate the given model, setting its fields based on the response\nfrom the server.\n\n``` go\n// Create a new todo which is initially empty.\ntodo := Todo{}\n// Call Read to get it from the server and fill in\n// all the fields of todo.\nif err := client.Read(\"9fjq293n8fw8\", \u0026todo); err != nil {\n\t// Handle err\n}\nfmt.Println(todo.Title)\n// Output:\n//  \"Discover the meaning of life\"\n```\n\nThe example above would send a GET request to \"/todos/9fjq293n8fw8\". The response from\nthe server should look like this:\n\n``` json\n{\n\t\"Id\": \"9fjq293n8fw8\",\n\t\"Title\": \"Discover the meaning of life\",\n\t\"IsCompleted\": false\n}\n```\n\n### Update\n\nThe [`Update`](https://godoc.org/github.com/go-humble/rest/#Client.Update) method sends a PATCH\nrequest to the model's root url with the model id appended. It is used to update existing models\non the server. Update will mutate the given model, setting its fields based on the response from\nthe server.\n\n``` go\n// Assume todo is an existing model with a valid id.\n// Here's how we would mark it as completed on the\n// server.\ntodo.IsCompleted = true\nif err := client.Update(todo); err != nil {\n\t// Handle err\n}\n```\n\nIf you are using url encoding, the request sent to the server in the above example would look\nlike this:\n\n```\nPATCH /todos/9fjq293n8fw8\n\nIsCompleted=true\n```\n\nAnd the response from the server should look like this:\n\n``` json\n{\n\t\"Id\": \"9fjq293n8fw8\",\n\t\"Title\": \"Discover the meaning of life\",\n\t\"IsCompleted\": true\n}\n```\n\n### Delete\n\nThe [`Delete`](https://godoc.org/github.com/go-humble/rest/#Client.Update) method sends a DELETE\nrequest to the model's root url with the model id appended. It is used to delete existing models\nfrom the server. Delete does not do anything with the response from the server and the given model\nis not mutated.\n\n``` go\n// Assume todo is an existing model with a valid id.\nif err := client.Delete(todo); err != nil {\n\t// Handle err\n}\n```\n\nThe example above would send a DELETE request to \"/todos/9fjq293n8fw8\". The response from\nthe server is not used by the rest package, but it should typically either be an empty json\nresponse:\n\n``` json\n{}\n```\n\nOr the model that was deleted:\n\n``` json\n{\n\t\"Id\": \"9fjq293n8fw8\",\n\t\"Title\": \"Discover the meaning of life\",\n\t\"IsCompleted\": true\n}\n```\n\n### ReadAll\n\nThe [`ReadAll`](https://godoc.org/github.com/go-humble/rest/#Client.ReadAll)\nmethod sends a GET request to the model's root url. It is used to get all\nexisting models of a given type from the server. `ReadAll` accepts an\n`interface{}` as an argument but will return an error if it is not a pointer to\na slice of some type that implements `Model`. (ReadAll does not accept\n`[]rest.Model` because that would require an additional, non-free cast. In go,\na slice of some interface is not the same as a slice of some concrete type that\nimplements the interface, and you cannot convert freely from one to the other.)\n`ReadAll` will mutate the given slice based on the response from the server,\ngrowing or shrinking it as needed.\n\n``` go\ntodos := []Todo{}\nif err := client.ReadAll(\u0026todos); err != nil {\n\t// Handle err\n}\n```\n\nThe example above would send a GET request to \"/todos\". The response from\nthe server should look like this:\n\n``` json\n[\n\t{\n\t\t\"Id\": \"9fjq293n8fw8\",\n\t\t\"Title\": \"Discover the meaning of life\",\n\t\t\"IsCompleted\": true\n\t},\n\t{\n\t\t\"Id\": \"af948j2f0jdh\",\n\t\t\"Title\": \"Read a good book\",\n\t\t\"IsCompleted\": false\n\t}\n]\n```\n\n### Handling Errors\n\nWhenever a non-2xx status code is returned by the server, the `Create`,\n`Read`, `Update`, `Delete`, and `ReadAll` methods will return an\n[`HTTPError`](https://godoc.org/github.com/go-humble/rest/#HTTPError),\nwhich contains pretty much everything you need to know from the response.\n\n``` go\ntype HTTPError struct {\n\t// URL is the url that the request was sent to\n\tURL string\n\t// Body is the body of the response\n\tBody []byte\n\t// StatusCode is the http status code of the response\n\tStatusCode int\n}\n```\n\nIt is up to the caller to decide what to do based on the type of error\nthat occurred. A typical flow might look something like this:\n\n``` go\ntodo := Todo{}\nif err := client.Read(\"9fjq293n8fw8\", \u0026todo); err != nil {\n\t// Check if the error was of type rest.HTTPError and if so,\n\t// if the status code was 404. This can be a pretty common\n\t// error and should be handled appropriately.\n\tif httpErr, ok := err.(rest.HTTPError); ok \u0026\u0026 httpErr.StatusCode == 404 {\n\t\tlog.Println(\"Could not find todo with with the given id.\")\n\t\t// NOTE: Probably want to render a message to the user\n\t\t// in this case.\n\t\treturn\n\t}\n\t// Handle some other type of error.\n\tlog.Fatal(err)\n}\n```\n\nTesting\n-------\n\nRest uses the [karma test runner](http://karma-runner.github.io/0.12/index.html) to test\nthe code running in actual browsers.\n\nThe tests require the following additional dependencies:\n\n- [node.js](http://nodejs.org/) (If you didn't already install it above)\n- [karma](http://karma-runner.github.io/0.12/index.html)\n- [karma-qunit](https://github.com/karma-runner/karma-qunit)\n\nDon't forget to also install the karma command line tools with `npm install -g karma-cli`.\n\nYou will also need to install a launcher for each browser you want to test with, as well as the\nbrowsers themselves. Typically you install a karma launcher with `npm install -g karma-chrome-launcher`.\nYou can edit the config file at `karma/test-mac.conf.js` or create a new one (e.g. `karma/test-windows.conf.js`)\nif you want to change the browsers that are tested on.\n\nOnce you have installed all the dependencies, start karma with `karma start karma/test-mac.conf.js` (or\nyour customized config file, if applicable). Once karma is running, you can keep it running in between tests.\n\nThe tests communicate with a special idempotent test server, which does some basic validation and mocks\nthe kinds of responses we would expect from a real REST server. Before running the tests, you need to start\nthe test server with `go run test/server/main.go`.\n\nNext you need to compile the test.go file to javascript so it can run in the browsers:\n\n```\ngopherjs build karma/go/rest_test.go -o karma/js/rest_test.js\n```\n\nFinally run the tests with `karma run karma/test-mac.conf.js` (changing the name of the config file if needed).\n\nIf you are on a unix-like operating system, you can recompile and run the tests in one go by running\nthe provided bash script: `./karma/test.sh`.\n\n\nContributing\n------------\n\nSee [CONTRIBUTING.md](https://github.com/go-humble/rest/blob/master/CONTRIBUTING.md)\n\n\nLicense\n-------\n\nRest is licensed under the MIT License. See the [LICENSE](https://github.com/go-humble/rest/blob/master/LICENSE)\nfile for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-humble%2Frest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-humble%2Frest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-humble%2Frest/lists"}