{"id":525,"name":null,"description":"A Faraday middleware that respects HTTP cache","url":"https://github.com/sourcelevel/faraday-http-cache","last_synced_at":"2026-04-30T05:01:00.905Z","repository":{"id":2410790,"uuid":"3378613","full_name":"sourcelevel/faraday-http-cache","owner":"sourcelevel","description":"A Faraday middleware that respects HTTP cache","archived":false,"fork":false,"pushed_at":"2026-04-14T00:24:08.000Z","size":512,"stargazers_count":343,"open_issues_count":4,"forks_count":89,"subscribers_count":16,"default_branch":"master","last_synced_at":"2026-04-24T00:46:50.963Z","etag":null,"topics":["cache","faraday","http","middleware","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sourcelevel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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":"2012-02-07T15:39:38.000Z","updated_at":"2026-04-23T07:25:01.000Z","dependencies_parsed_at":"2026-02-01T10:05:18.247Z","dependency_job_id":null,"html_url":"https://github.com/sourcelevel/faraday-http-cache","commit_stats":{"total_commits":369,"total_committers":41,"mean_commits":9.0,"dds":0.3739837398373984,"last_synced_commit":"3f1bf705c9b6050cf48d382b33bc0ee402012ccd"},"previous_names":["plataformatec/faraday-http-cache"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/sourcelevel/faraday-http-cache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcelevel%2Ffaraday-http-cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcelevel%2Ffaraday-http-cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcelevel%2Ffaraday-http-cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcelevel%2Ffaraday-http-cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sourcelevel","download_url":"https://codeload.github.com/sourcelevel/faraday-http-cache/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcelevel%2Ffaraday-http-cache/sbom","scorecard":{"id":737202,"data":{"date":"2025-08-11","repo":{"name":"github.com/sourcelevel/faraday-http-cache","commit":"f44ded4c9f6f794901c97eca1d82eb3ef2d5a5e6"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"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":"Code-Review","score":4,"reason":"Found 8/17 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":"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":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/sourcelevel/faraday-http-cache/lint.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/lint.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/sourcelevel/faraday-http-cache/lint.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/sourcelevel/faraday-http-cache/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/sourcelevel/faraday-http-cache/main.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/lint.yml:1","Warn: no topLevel permission defined: .github/workflows/main.yml:1","Info: no jobLevel write permissions found"],"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":"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":"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":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"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"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 21 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"}}]},"last_synced_at":"2025-08-22T16:12:37.718Z","repository_id":2410790,"created_at":"2025-08-22T16:12:37.719Z","updated_at":"2025-08-22T16:12:37.719Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32204710,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T00:06:41.111Z","status":"ssl_error","status_checked_at":"2026-04-24T00:06:35.224Z","response_time":53,"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"}},"owner":{"login":"sourcelevel","name":"SourceLevel","uuid":"39925474","kind":"organization","description":"Pull Requests, Collaboration, Teams, Individuals and DORA Metrics. Help teams succeed, improve accountability, check improvement plans.","email":"support@sourcelevel.io","website":"https://sourcelevel.io","location":"United States of America","twitter":"sourcelevelhq","company":null,"icon_url":"https://avatars.githubusercontent.com/u/39925474?v=4","repositories_count":13,"last_synced_at":"2024-03-26T07:41:56.387Z","metadata":{"has_sponsors_listing":false},"html_url":"https://github.com/sourcelevel","funding_links":[],"total_stars":389,"followers":16,"following":0,"created_at":"2022-11-03T09:34:35.819Z","updated_at":"2024-03-26T07:42:02.465Z","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sourcelevel","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sourcelevel/repositories"},"packages":[],"commits":{"id":19135,"full_name":"sourcelevel/faraday-http-cache","default_branch":"master","total_commits":388,"total_committers":43,"total_bot_commits":1,"total_bot_committers":1,"mean_commits":9.023255813953488,"dds":0.35051546391752575,"past_year_total_commits":13,"past_year_total_committers":4,"past_year_total_bot_commits":1,"past_year_total_bot_committers":1,"past_year_mean_commits":3.25,"past_year_dds":0.23076923076923073,"last_synced_at":"2026-04-28T04:03:20.065Z","last_synced_commit":"4fd5dd3400740b8ca8bfbf040cd570171b18bc8b","created_at":"2023-03-07T11:40:05.083Z","updated_at":"2026-04-28T04:01:43.189Z","committers":[{"name":"Lucas Mazza","email":"lucas.mazza@plataformatec.com.br","login":"lucasmazza","count":252},{"name":"Rafael Mendonça França","email":"rafael.franca@plataformatec.com.br","login":null,"count":18},{"name":"George Guimarães","email":"george.guimaraes@gmail.com","login":"georgeguimaraes","count":13},{"name":"Jiunn Haur Lim","email":"codex.is.poetry@gmail.com","login":null,"count":9},{"name":"Erich Soares Machado","email":"erichmachado@gmail.com","login":"erichmachado","count":9},{"name":"Svyatoslav Kryukov","email":"s.g.kryukov@yandex.ru","login":"skryukov","count":8},{"name":"Gustavo Araujo","email":"garaujodev@gmail.com","login":"garaujodev","count":8},{"name":"Olle Jonsson","email":"olle.jonsson@gmail.com","login":"olleolleolle","count":7},{"name":"Bernardo Chaves","email":"bernardo.chaves@plataformatec.com.br","login":null,"count":6},{"name":"Charlie Han","email":"charles_han@cable.comcast.com","login":"charliehan","count":5},{"name":"Daniel Schierbeck","email":"dasch@zendesk.com","login":"dasch","count":4},{"name":"Rhett Sutphin","email":"rhett@detailedbalance.net","login":"rsutphin","count":4},{"name":"Erich Kist","email":"erich.kist@plataformatec.com.br","login":null,"count":3},{"name":"Anton Holmgren","email":"me@antonholmgren.com","login":"alksl","count":3},{"name":"Brendan Dahl","email":"dahl.brendan@gmail.com","login":"dahlb","count":3},{"name":"Ethan Dennis","email":"ethanis@github.com","login":"ethanis","count":3},{"name":"Todd Mazierski","email":"todd@generalassemb.ly","login":null,"count":2},{"name":"Chris DiMartino","email":"vwchris@gmail.com","login":"cdimartino","count":2},{"name":"Christian Gregg","email":"c_arlt@hotmail.com","login":"CGA1123","count":2},{"name":"James Cotterill","email":"mail@jamescotterill.co.uk","login":"JamesCotterill","count":2},{"name":"Rob","email":"phorque@gmail.com","login":"dwo","count":2},{"name":"Scott Albertson","email":"scott@thoughtbot.com","login":"salbertson","count":2},{"name":"github-actions[bot]","email":"41898282+github-actions[bot]","login":"github-actions[bot]","count":1},{"name":"Yuki Inoue","email":"inoueyuworks@gmail.com","login":"Yuki-Inoue","count":1},{"name":"Takafumi Yamamoto","email":"bino98@gmail.com","login":"bino98","count":1},{"name":"NickLaMuro","email":"nicklamuro@gmail.com","login":"NickLaMuro","count":1},{"name":"Matthew Hutchinson","email":"matt@hiddenloop.com","login":"matthutchinson","count":1},{"name":"Andy Shipman","email":"ashipman@housetrip.com","login":null,"count":1},{"name":"Leon Dewey","email":"ldewey@Leons-MacBook-Pro.local","login":null,"count":1},{"name":"Phil Sturgeon","email":"me@philsturgeon.uk","login":null,"count":1},{"name":"Tim Cheadle","email":"timc@generalassemb.ly","login":null,"count":1},{"name":"Konstantin Shabanov","email":"mail@etehtsea.me","login":"etehtsea","count":1},{"name":"Jon Burgess","email":"jkburges@gmail.com","login":"jkburges","count":1},{"name":"Jean Boussier","email":"jean.boussier@gmail.com","login":"byroot","count":1},{"name":"Jan Stastny","email":"honza@stastnarodina.com","login":"jstastny","count":1},{"name":"Ismael Celis","email":"ismaelct@gmail.com","login":"ismasan","count":1},{"name":"Evan Raffel","email":"evman182","login":"evman182","count":1},{"name":"Edouard CHIN","email":"chin.edouard@gmail.com","login":"Edouard-chin","count":1},{"name":"Chris Beer","email":"cabeer@stanford.edu","login":"cbeer","count":1},{"name":"Brent Snook","email":"brent@fuglylogic.com","login":"brentsnook","count":1},{"name":"Andrew Marshall","email":"andrew@johnandrewmarshall.com","login":"amarshall","count":1},{"name":"Alex Handley","email":"alex@seriousfox.co.uk","login":"alex-handley","count":1},{"name":"Adam Lett","email":"adamlett@gmail.com","login":"KaptajnKold","count":1}],"past_year_committers":[{"name":"George Guimarães","email":"george.guimaraes@gmail.com","login":"georgeguimaraes","count":10},{"name":"github-actions[bot]","email":"41898282+github-actions[bot]","login":"github-actions[bot]","count":1},{"name":"Matthew Hutchinson","email":"matt@hiddenloop.com","login":"matthutchinson","count":1},{"name":"Edouard CHIN","email":"chin.edouard@gmail.com","login":"Edouard-chin","count":1}],"commits_url":"https://commits.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcelevel%2Ffaraday-http-cache/commits","host":{"name":"GitHub","url":"https://github.com","kind":"github","last_synced_at":"2026-04-30T00:00:07.427Z","repositories_count":6223397,"commits_count":900024277,"contributors_count":34899964,"owners_count":1147576,"icon_url":"https://github.com/github.png","host_url":"https://commits.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://commits.ecosyste.ms/api/v1/hosts/GitHub/repositories"}},"issues_stats":{"full_name":"sourcelevel/faraday-http-cache","html_url":"https://github.com/sourcelevel/faraday-http-cache","last_synced_at":"2026-04-28T04:01:05.974Z","status":"error","issues_count":42,"pull_requests_count":66,"avg_time_to_close_issue":20659082.57894737,"avg_time_to_close_pull_request":5616704.153846154,"issues_closed_count":38,"pull_requests_closed_count":65,"pull_request_authors_count":42,"issue_authors_count":36,"avg_comments_per_issue":2.6904761904761907,"avg_comments_per_pull_request":2.2272727272727275,"merged_pull_requests_count":49,"bot_issues_count":4,"bot_pull_requests_count":4,"past_year_issues_count":0,"past_year_pull_requests_count":4,"past_year_avg_time_to_close_issue":null,"past_year_avg_time_to_close_pull_request":595587.3333333334,"past_year_issues_closed_count":0,"past_year_pull_requests_closed_count":3,"past_year_pull_request_authors_count":3,"past_year_issue_authors_count":0,"past_year_avg_comments_per_issue":null,"past_year_avg_comments_per_pull_request":2.25,"past_year_bot_issues_count":0,"past_year_bot_pull_requests_count":2,"past_year_merged_pull_requests_count":3,"created_at":"2023-05-12T10:37:33.452Z","updated_at":"2026-04-28T04:01:05.974Z","repository_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcelevel%2Ffaraday-http-cache","issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcelevel%2Ffaraday-http-cache/issues","issue_labels_count":{},"pull_request_labels_count":{"dependencies":2,"autorelease: tagged":1,"autorelease: pending":1},"issue_author_associations_count":{"NONE":34,"CONTRIBUTOR":6,"COLLABORATOR":2},"pull_request_author_associations_count":{"CONTRIBUTOR":47,"NONE":13,"COLLABORATOR":6},"issue_authors":{"dependabot-preview[bot]":4,"teamon":2,"lucasmazza":2,"gottfrois":2,"bino98":1,"tarebyte":1,"minad":1,"salbertson":1,"dobbymoodge":1,"CarlosBoix":1,"apteryks":1,"joshuacronemeyer":1,"evman182":1,"jjb":1,"jstastny":1,"mjobin-mdsol":1,"ghosalmartin":1,"gmontard":1,"schopenhauer":1,"tjwallace":1,"lukesutton":1,"KaptajnKold":1,"kevinjalbert":1,"ybiquitous":1,"casperisfine":1,"Physium":1,"kazjote":1,"miccheng":1,"kookster":1,"mityakoval":1,"cgagon":1,"monfresh":1,"ekremkaraca":1,"mingleiwang":1,"jlecour":1,"dwo":1},"pull_request_authors":{"olleolleolle":7,"lucasmazza":6,"skryukov":5,"dasch":4,"JamesCotterill":2,"dependabot-preview[bot]":2,"github-actions[bot]":2,"charliehan":2,"toddmazierski":2,"dwo":2,"vkill":1,"jkburges":1,"ismasan":1,"timcheadle":1,"etehtsea":1,"skylar-anderson":1,"matthutchinson":1,"alksl":1,"cbeer":1,"evman182":1,"jstastny":1,"jimjh":1,"mjobin-mdsol":1,"bino98":1,"NickLaMuro":1,"Vichugo1995":1,"Yuki-Inoue":1,"chrisface":1,"cdimartino":1,"ybiquitous":1,"ethanis":1,"ryuichi7":1,"pschambacher":1,"tjwallace":1,"KaptajnKold":1,"casperisfine":1,"mrship":1,"philsturgeon":1,"cgagon":1,"CGA1123":1,"Edouard-chin":1,"salbertson":1},"host":{"name":"GitHub","url":"https://github.com","kind":"github","last_synced_at":"2026-04-28T00:00:08.715Z","repositories_count":14438145,"issues_count":34381571,"pull_requests_count":112701709,"authors_count":11247534,"icon_url":"https://github.com/github.png","host_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories","owners_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/owners","authors_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors"},"past_year_issue_labels_count":{},"past_year_pull_request_labels_count":{"autorelease: pending":1,"autorelease: tagged":1},"past_year_issue_author_associations_count":{},"past_year_pull_request_author_associations_count":{"CONTRIBUTOR":4},"past_year_issue_authors":{},"past_year_pull_request_authors":{"github-actions[bot]":2,"Edouard-chin":1,"matthutchinson":1},"maintainers":[{"login":"lucasmazza","count":8,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/lucasmazza"}],"active_maintainers":[]},"events":{"total":{"ReleaseEvent":1,"PullRequestEvent":1,"ForkEvent":1,"WatchEvent":5,"IssueCommentEvent":1,"PushEvent":7},"last_year":{"ReleaseEvent":1,"PullRequestEvent":1,"WatchEvent":3,"IssueCommentEvent":1,"PushEvent":7}},"keywords":["cache","faraday","http","middleware","ruby"],"dependencies":[{"ecosystem":"rubygems","filepath":"Gemfile","sha":null,"kind":"manifest","created_at":"2022-08-06T12:15:18.967Z","updated_at":"2022-08-06T12:15:18.967Z","repository_link":"https://github.com/sourcelevel/faraday-http-cache/blob/master/Gemfile","dependencies":[{"id":584943195,"package_name":"faraday_middleware","ecosystem":"rubygems","requirements":"\u003e= 0","direct":true,"kind":"runtime","optional":false},{"id":584943196,"package_name":"faraday-em_http","ecosystem":"rubygems","requirements":"\u003e= 0","direct":true,"kind":"runtime","optional":false},{"id":584943197,"package_name":"activesupport","ecosystem":"rubygems","requirements":"\u003e= 5.0","direct":true,"kind":"runtime","optional":false},{"id":584943198,"package_name":"em-http-request","ecosystem":"rubygems","requirements":"~\u003e 1.1","direct":true,"kind":"runtime","optional":false},{"id":584943199,"package_name":"rake","ecosystem":"rubygems","requirements":"~\u003e 13.0","direct":true,"kind":"runtime","optional":false},{"id":584943200,"package_name":"rspec","ecosystem":"rubygems","requirements":"~\u003e 3.1","direct":true,"kind":"runtime","optional":false},{"id":584943201,"package_name":"sinatra","ecosystem":"rubygems","requirements":"~\u003e 2.0","direct":true,"kind":"runtime","optional":false},{"id":584943202,"package_name":"webrick","ecosystem":"rubygems","requirements":"\u003e= 0","direct":true,"kind":"runtime","optional":false}]},{"ecosystem":"rubygems","filepath":"faraday-http-cache.gemspec","sha":null,"kind":"manifest","created_at":"2022-08-06T12:15:19.099Z","updated_at":"2022-08-06T12:15:19.099Z","repository_link":"https://github.com/sourcelevel/faraday-http-cache/blob/master/faraday-http-cache.gemspec","dependencies":[{"id":584943258,"package_name":"faraday","ecosystem":"rubygems","requirements":"\u003e= 0.8","direct":true,"kind":"runtime","optional":false}]},{"ecosystem":"actions","filepath":".github/workflows/lint.yml","sha":null,"kind":"manifest","created_at":"2023-07-11T00:32:06.105Z","updated_at":"2023-07-11T00:32:06.105Z","repository_link":"https://github.com/sourcelevel/faraday-http-cache/blob/master/.github/workflows/lint.yml","dependencies":[{"id":11309370418,"package_name":"actions/checkout","ecosystem":"actions","requirements":"v2","direct":true,"kind":"composite","optional":false},{"id":11309370422,"package_name":"ruby/setup-ruby","ecosystem":"actions","requirements":"v1","direct":true,"kind":"composite","optional":false}]},{"ecosystem":"actions","filepath":".github/workflows/main.yml","sha":null,"kind":"manifest","created_at":"2023-07-11T00:32:06.865Z","updated_at":"2023-07-11T00:32:06.865Z","repository_link":"https://github.com/sourcelevel/faraday-http-cache/blob/master/.github/workflows/main.yml","dependencies":[{"id":11309374985,"package_name":"actions/checkout","ecosystem":"actions","requirements":"v2","direct":true,"kind":"composite","optional":false},{"id":11309374986,"package_name":"ruby/setup-ruby","ecosystem":"actions","requirements":"v1","direct":true,"kind":"composite","optional":false}]}],"score":9.610524895640422,"created_at":"2024-12-15T21:38:08.258Z","updated_at":"2026-04-30T05:01:00.906Z","avatar_url":"https://github.com/sourcelevel.png","language":"Ruby","monthly_downloads":0,"readme":"# Faraday Http Cache\n\n[![Gem Version](https://badge.fury.io/rb/faraday-http-cache.svg)](https://rubygems.org/gems/faraday-http-cache)\n[![Build](https://github.com/sourcelevel/faraday-http-cache/actions/workflows/main.yml/badge.svg)](https://github.com/sourcelevel/faraday-http-cache/actions)\n\nA [Faraday](https://github.com/lostisland/faraday) middleware that respects HTTP cache,\nby checking expiration and validation of the stored responses.\n\n## Installation\n\nAdd it to your Gemfile:\n\n```ruby\ngem 'faraday-http-cache'\n```\n\n## Usage and configuration\n\nYou have to use the middleware in the Faraday instance that you want to,\nalong with a suitable `store` to cache the responses. You can use the new\nshortcut using a symbol or passing the middleware class\n\n```ruby\nclient = Faraday.new do |builder|\n  builder.use :http_cache, store: Rails.cache\n  # or\n  builder.use Faraday::HttpCache, store: Rails.cache\n\n  builder.adapter Faraday.default_adapter\nend\n```\n\nThe middleware accepts a `store` option for the cache backend responsible for recording\nthe API responses that should be stored. Stores should respond to `write`, `read` and `delete`,\njust like an object from the `ActiveSupport::Cache` API.\n\n```ruby\n# Connect the middleware to a Memcache instance.\nstore = ActiveSupport::Cache.lookup_store(:mem_cache_store, ['localhost:11211'])\n\nclient = Faraday.new do |builder|\n  builder.use :http_cache, store: store\n  builder.adapter Faraday.default_adapter\nend\n\n# Or use the Rails.cache instance inside your Rails app.\nclient = Faraday.new do |builder|\n  builder.use :http_cache, store: Rails.cache\n  builder.adapter Faraday.default_adapter\nend\n```\nThe default store provided is a simple in memory cache that lives on the client instance.\nThis type of store **might not be persisted across multiple processes or connection instances**\nso it is probably not suitable for most production environments.\nMake sure that you configure a store that is suitable for you.\n\nThe stdlib `JSON` module is used for serialization by default, which can struggle with unicode\ncharacters in responses in Ruby \u003c 3.1. For example, if your JSON returns `\"name\": \"Raül\"` then\nyou might see errors like:\n\n```\nResponse could not be serialized: \"\\xC3\" from ASCII-8BIT to UTF-8. Try using Marshal to serialize.\n```\n\nFor full unicode support, or if you expect to be dealing with images, you can use the stdlib\n[Marshal][marshal] instead. Alternatively you could use another json library like `oj` or `yajl-ruby`.\n\n```ruby\nclient = Faraday.new do |builder|\n  builder.use :http_cache, store: Rails.cache, serializer: Marshal\n  builder.adapter Faraday.default_adapter\nend\n```\n\n### Stale-While-Revalidate and background refresh hooks\n\nThe middleware supports `stale-while-revalidate` directives from the `Cache-Control` header.\nWhen a cached response is stale but still inside the `stale-while-revalidate` window, the middleware\nwill serve the stale response immediately.\n\nYou can provide an `:on_stale` callback to trigger your own asynchronous refresh logic:\n\n```ruby\nclient = Faraday.new do |builder|\n  builder.use :http_cache,\n    store: Rails.cache,\n    on_stale: lambda { |request:, env:, cached_response:|\n      RefreshApiCacheJob.perform_later(request.url.to_s)\n    }\n  builder.adapter Faraday.default_adapter\nend\n```\n\nThe callback receives:\n\n- `request`: `Faraday::HttpCache::Request`\n- `env`: current `Faraday::Env`\n- `cached_response`: `Faraday::HttpCache::Response`\n\n### Strategies\n\nYou can provide a `:strategy` option to the middleware to specify the strategy to use.\n\n```ruby\nclient = Faraday.new do |builder|\n  builder.use :http_cache, store: Rails.cache, strategy: Faraday::HttpCache::Strategies::ByVary\n  builder.adapter Faraday.default_adapter\nend\n```\n\nAvailable strategies are:\n\n#### `Faraday::HttpCache::Strategies::ByUrl`\n\nThe default strategy.\nIt Uses URL + HTTP method to generate cache keys and stores an array of request + response for each key.\n\n#### `Faraday::HttpCache::Strategies::ByVary`\n\nThis strategy uses headers from `Vary` header to generate cache keys.\nIt also uses cache to store `Vary` headers mapped to the request URL.\nThis strategy is more suitable for caching private responses with the same URLs but different results for different users, like `https://api.github.com/user`.\n\n*Note:* To automatically remove stale cache keys, you might want to use the `:expires_in` option.\n\n```ruby\nstore = ActiveSupport::Cache.lookup_store(:redis_cache_store, expires_in: 1.day, url: 'redis://localhost:6379/0')\nclient = Faraday.new do |builder|\n  builder.use :http_cache, store: store, strategy: Faraday::HttpCache::Strategies::ByVary\n  builder.adapter Faraday.default_adapter\nend\n```\n\n#### Custom strategies\n\nYou can write your own strategy by subclassing `Faraday::HttpCache::Strategies::BaseStrategy` and implementing `#write`, `#read` and `#delete` methods.\n\n### Logging\n\nYou can provide a `:logger` option that will receive debug information based on the middleware\noperations:\n\n```ruby\nclient = Faraday.new do |builder|\n  builder.use :http_cache, store: Rails.cache, logger: Rails.logger\n  builder.adapter Faraday.default_adapter\nend\n\nclient.get('https://site/api/users')\n# logs \"HTTP Cache: [GET users] miss, store\"\n```\n\n### Instrumentation\n\nIn addition to logging you can instrument the middleware by passing in an `:instrumenter` option\nsuch as ActiveSupport::Notifications (compatible objects are also allowed).\n\nThe event `http_cache.faraday` will be published every time the middleware\nprocesses a request. In the event payload, `:env` contains the response Faraday env and\n`:cache_status` contains a Symbol indicating the status of the cache processing for that request:\n\n- `:unacceptable` means that the request did not go through the cache at all.\n- `:miss` means that no cached response could be found.\n- `:invalid` means that the cached response could not be validated against the server.\n- `:valid` means that the cached response *could* be validated against the server.\n- `:fresh` means that the cached response was still fresh and could be returned without even\n  calling the server.\n- `:stale` means that the cached response was stale, but served while inside\n  `stale-while-revalidate` window.\n\n```ruby\nclient = Faraday.new do |builder|\n  builder.use :http_cache, store: Rails.cache, instrumenter: ActiveSupport::Notifications\n  builder.adapter Faraday.default_adapter\nend\n\n# Subscribes to all events from Faraday::HttpCache.\nActiveSupport::Notifications.subscribe \"http_cache.faraday\" do |*args|\n  event = ActiveSupport::Notifications::Event.new(*args)\n  cache_status = event.payload[:cache_status]\n  statsd = Statsd.new\n\n  case cache_status\n  when :fresh, :valid, :stale\n    statsd.increment('api-calls.cache_hits')\n  when :invalid, :miss\n    statsd.increment('api-calls.cache_misses')\n  when :unacceptable\n    statsd.increment('api-calls.cache_bypass')\n  end\nend\n```\n\n## See it live\n\nYou can clone this repository, install its dependencies with Bundler (run `bundle install`) and\nexecute the files under the `examples` directory to see a sample of the middleware usage.\nFor stale-while-revalidate behavior with `:on_stale`, see `examples/stale_while_revalidate.rb`.\n\n## What gets cached?\n\nThe middleware will use the following headers to make caching decisions:\n- Vary\n- Cache-Control\n- Age\n- Last-Modified\n- ETag\n- Expires\n\n### Cache-Control\n\nThe `max-age`, `must-revalidate`, `proxy-revalidate`, `s-maxage` and\n`stale-while-revalidate` directives are checked.\n\n### Shared vs. non-shared caches\n\nBy default, the middleware acts as a \"shared cache\" per RFC 2616. This means it does not cache\nresponses with `Cache-Control: private`. This behavior can be changed by passing in the\n`:shared_cache` configuration option:\n\n```ruby\nclient = Faraday.new do |builder|\n  builder.use :http_cache, shared_cache: false\n  builder.adapter Faraday.default_adapter\nend\n\nclient.get('https://site/api/some-private-resource') # =\u003e will be cached\n```\n\n## License\n\nCopyright (c) 2012-2018 Plataformatec.\nCopyright (c) 2019 SourceLevel and contributors.\n\n  [marshal]: https://www.ruby-doc.org/core-3.0/Marshal.html\n","funding_links":[],"readme_doi_urls":[],"works":{},"citation_counts":{},"total_citations":0,"keywords_from_contributors":["activerecord","rubygem","activejob","mvc","feature-flag","data-validation","ruby-gem","octokit-rb","github-api","rack"],"project_url":"https://ruby.ecosyste.ms/api/v1/projects/525","html_url":"https://ruby.ecosyste.ms/projects/525"}