{"id":15902847,"url":"https://github.com/erikh/rate-limiter","last_synced_at":"2025-08-14T12:32:39.934Z","repository":{"id":184721043,"uuid":"672344308","full_name":"erikh/rate-limiter","owner":"erikh","description":"Example rate limiting handlers with davisjr","archived":false,"fork":false,"pushed_at":"2023-08-21T20:46:45.000Z","size":12,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-13T12:03:14.546Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/erikh.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}},"created_at":"2023-07-29T18:49:15.000Z","updated_at":"2023-08-14T08:17:42.000Z","dependencies_parsed_at":"2024-10-28T07:58:04.789Z","dependency_job_id":"2ed12dc8-7c82-47c1-ad9d-344826555415","html_url":"https://github.com/erikh/rate-limiter","commit_stats":{"total_commits":8,"total_committers":1,"mean_commits":8.0,"dds":0.0,"last_synced_commit":"38429bd77263d2f34c282055c61fa40a01a73ad0"},"previous_names":["erikh/rate-limiter"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikh%2Frate-limiter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikh%2Frate-limiter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikh%2Frate-limiter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikh%2Frate-limiter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/erikh","download_url":"https://codeload.github.com/erikh/rate-limiter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229827034,"owners_count":18130384,"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":[],"created_at":"2024-10-06T12:00:22.798Z","updated_at":"2024-12-15T13:42:04.777Z","avatar_url":"https://github.com/erikh.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rate limiting example with davisjr\n\ndavisjr is a small HTTP framework I wrote for rust-lang. Here's an example of a\nrate limiting middleware I composed with it for a job interview.\n\nSome introduction:\n\n[davisjr](https://github.com/erikh/davisjr) is derived from the\n[ratpack](https://github.com/zerotier/ratpack) crate I developed for zerotier\nfor the construction of the [coyote](https://github.com/zerotier/coyote)\nproject amongst other things. It was designed while grousing about the\nverbosity of other rust HTTP frameworks, and is designed to be very simple\nas a result. The idea is that any handler function can also be middleware,\nand any handler that returns a \"None\" response is expected to have its\nrequest handled by the next handler in the chain, or a 500 is returned. I\nencourage you to read the docs, there should be ample.\n\nThis allowed me to keep this rate limiter very simple. It uses a map of keys\nfor the API keys, pointing at a map of routes, which then point at vector of\nInstant time values. This could probably be cheaper as far as memory use\ngoes, but allowed me to keep simple pruning routines. The result is a handler\nwhich is only a few lines of code and repurposed for any occasion.\n\nThe fed data structure is just route -\u003e tuple of duration + count, the latter\nhalf meaning \"how many requests in how much time\". The tests fix this all at 1\nsecond for ease of testing, but try to exercise all cases. They use the testing\nframework in davisjr which allows you to do HTTP request testing without\ninvolving any syscalls.\n\nThere is also an example program that is more or less the same as the tests but\ntakes a YAML configuration file and turns that into the fed data structure (the\n\"Limit Map\"). Ease of deserialization was aided by my\n[fancy-duration](https://github.com/erikh/fancy-duration) crate which is very\nsimilar to golang durations and their text representations. The provided\nconfiguration file uses one second intervals, which are represented as \"1s\",\nfor example.\n\nTo run the example:\n\n```\ncargo run --example limit-handler example_config.yaml # or provide your own config\n```\n\nIt listens on `0.0.0.0:8000` and the routes are programmed as a part of the\nconfiguration file.\n\nTo run the tests:\n\n```\ncargo test\n```\n\nThis took approximately 3 hours to code from `cargo new` to now, but I took\nseveral breaks to think about it, and the challenge I received yesterday, but\nspent most of the evening on a Friday night considering ways to solve it while\nflooding my brain with malt beverages.\n\nOn Sunday (7/30), I reworked the example to have a dynamic router, so all the routes\nyou program into the config work, an oversight I made. I also took a clippy\npass Saturday sometime. I got bored and decided to noodle on it a bit. Hope\nthat's ok.\n\nThanks for the opportunity.\n\n-Erik\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferikh%2Frate-limiter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferikh%2Frate-limiter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferikh%2Frate-limiter/lists"}