{"id":47762755,"url":"https://github.com/taskcluster/httpbackoff","last_synced_at":"2026-04-03T05:49:08.927Z","repository":{"id":32777729,"uuid":"36369478","full_name":"taskcluster/httpbackoff","owner":"taskcluster","description":"HTTP retry library with exponential backoff support and intelligent handling of http status codes and networking exceptions","archived":false,"fork":false,"pushed_at":"2024-07-14T09:12:03.000Z","size":87,"stargazers_count":16,"open_issues_count":4,"forks_count":8,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-08-14T01:51:49.365Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/taskcluster.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-05-27T13:43:58.000Z","updated_at":"2025-04-09T10:10:23.000Z","dependencies_parsed_at":"2024-06-18T19:50:28.680Z","dependency_job_id":"218b9549-baee-4016-b7b1-c982d1fc27f7","html_url":"https://github.com/taskcluster/httpbackoff","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/taskcluster/httpbackoff","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskcluster%2Fhttpbackoff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskcluster%2Fhttpbackoff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskcluster%2Fhttpbackoff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskcluster%2Fhttpbackoff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/taskcluster","download_url":"https://codeload.github.com/taskcluster/httpbackoff/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taskcluster%2Fhttpbackoff/sbom","scorecard":{"id":869245,"data":{"date":"2025-08-11","repo":{"name":"github.com/taskcluster/httpbackoff","commit":"d08c5119c3c8418bf4b2c7027e3c557bcde87f65"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.1,"checks":[{"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":"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":"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":"Code-Review","score":4,"reason":"Found 9/20 approved changesets -- score normalized to 4","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":"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":"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":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Mozilla Public License 2.0: 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":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/taskcluster/.github/SECURITY.md:1","Info: Found linked content: github.com/taskcluster/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/taskcluster/.github/SECURITY.md:1","Info: Found text in security policy: github.com/taskcluster/.github/SECURITY.md:1"],"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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 20 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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"}}]},"last_synced_at":"2025-08-24T03:38:46.402Z","repository_id":32777729,"created_at":"2025-08-24T03:38:46.402Z","updated_at":"2025-08-24T03:38:46.402Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31337184,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T04:42:29.251Z","status":"ssl_error","status_checked_at":"2026-04-03T04:42:12.667Z","response_time":107,"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":[],"created_at":"2026-04-03T05:49:08.256Z","updated_at":"2026-04-03T05:49:08.917Z","avatar_url":"https://github.com/taskcluster.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg align=\"right\" src=\"http://media.taskcluster.net/logo/logo-96x120.png\" /\u003e\n\n# httpbackoff\n\n[![Build Status](https://travis-ci.org/taskcluster/httpbackoff.svg?branch=main)](https://travis-ci.org/taskcluster/httpbackoff)\n[![GoDoc](https://godoc.org/github.com/taskcluster/httpbackoff?status.svg)](https://godoc.org/github.com/taskcluster/httpbackoff)\n[![Coverage Status](https://coveralls.io/repos/taskcluster/httpbackoff/badge.svg?branch=main\u0026service=github)](https://coveralls.io/github/taskcluster/httpbackoff?branch=master)\n[![License](https://img.shields.io/badge/license-MPL%202.0-orange.svg)](http://mozilla.org/MPL/2.0)\n\nAutomatic http retries for intermittent failures, with exponential backoff,\nbased on https://github.com/cenkalti/backoff.\n\nThe reason for a separate library, is that this library handles http status\ncodes to know whether to retry or not.  HTTP codes in range 500-599, and code\n429 are retried. Connection failures are also retried. Status codes 400-499\n(except for 429) are considered permanent errors and are not retried.\n\nThe Retry function performs the http request and retries if temporary errors\noccur. It takes a single parameter as its input - a function to perform the\nhttp request. This function must return `(resp *http.Response, tempError error,\npermError error)` where `tempError` must be non-nil if a temporary error occurs\n(e.g.  dropped connection), and `permError` must be non-nil if an error occurs\nthat does not warrant retrying the request (e.g. badly formed url).\n\nFor example, the following code that is not using retries:\n\n```go\nres, err := http.Get(\"http://www.google.com/robots.txt\")\n```\n\ncan be rewritten as:\n\n```go\nres, attempts, err := httpbackoff.Retry(func() (*http.Response, error, error) {\n\tresp, err := http.Get(\"http://www.google.com/robots.txt\")\n\t// assume all errors are temporary\n    return resp, err, nil\n})\n```\n\nPlease note the additional return value `attempts` is an `int` specifying how\nmany http calls were made (i.e. = 1 if no retries, otherwise \u003e 1).\n\nThe go http package has 9 functions that return `(*http.Reponse, error)` that\ncan potentially be retried:\n\n* http://golang.org/pkg/net/http/#Client.Do\n* http://golang.org/pkg/net/http/#Client.Get\n* http://golang.org/pkg/net/http/#Client.Head\n* http://golang.org/pkg/net/http/#Client.Post\n* http://golang.org/pkg/net/http/#Client.PostForm\n* http://golang.org/pkg/net/http/#Get\n* http://golang.org/pkg/net/http/#Head\n* http://golang.org/pkg/net/http/#Post\n* http://golang.org/pkg/net/http/#PostForm\n\nTo simplify using these functions, 9 utility functions have been written that\nwrap these. Therefore you can simplify this example above further with:\n\n```go\nres, _, err := httpbackoff.Get(\"http://www.google.com/robots.txt\")\n```\n\n## Configuring back off settings\n\nTo use cusom back off settings (for example, in testing, you might want to fail quickly), instead of calling the package functions, you can call methods of HTTPRetryClient with the same name:\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"net/http/httputil\"\n\t\"time\"\n\n\t\"github.com/cenkalti/backoff\"\n\t\"github.com/taskcluster/httpbackoff\"\n)\n\nfunc main() {\n\t// Note, you only need to create a client if you want to customise\n\t// the back off settings. In this example, we want to, but if you\n\t// wish to use the reasonable default settings, no need to do this.\n\tretryClient := httpbackoff.Client{\n\t\tBackOffSettings: \u0026backoff.ExponentialBackOff{\n\t\t\tInitialInterval:     1 * time.Millisecond,\n\t\t\tRandomizationFactor: 0.2,\n\t\t\tMultiplier:          1.2,\n\t\t\tMaxInterval:         5 * time.Millisecond,\n\t\t\tMaxElapsedTime:      20 * time.Millisecond,\n\t\t\tClock:               backoff.SystemClock,\n\t\t},\n\t}\n\n\tres, _, err := retryClient.Get(\"http://www.google.com/robots.txt\")\n\tif err != nil {\n\t\tlog.Fatalf(\"%s\", err)\n\t}\n\tdata, err := httputil.DumpResponse(res, true)\n\tif err != nil {\n\t\tlog.Fatalf(\"%s\", err)\n\t}\n\tlog.Print(string(data))\n}\n```\n\n## Testing\n\nThe package has tests, which run in travis. See http://travis-ci.org/taskcluster/httpbackoff.\n\n## Concurrency\n\nAs far as I am aware, there is nothing in this library that prevents it from\nbeing used concurrently. Please let me know if you find any problems!\n\n## Contributing\nContributions are welcome. Please fork, and issue a Pull Request back with an\nexplanation of your changes. Also please include tests for any functional\nchanges.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaskcluster%2Fhttpbackoff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaskcluster%2Fhttpbackoff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaskcluster%2Fhttpbackoff/lists"}