{"id":21672391,"url":"https://github.com/redis-developer/basic-redis-rate-limiting-demo-go-lang","last_synced_at":"2025-08-01T04:14:36.720Z","repository":{"id":49537387,"uuid":"342769465","full_name":"redis-developer/basic-redis-rate-limiting-demo-go-lang","owner":"redis-developer","description":"A basic redis rate limiting demo written in Go language","archived":false,"fork":false,"pushed_at":"2023-06-27T07:44:22.000Z","size":5823,"stargazers_count":6,"open_issues_count":0,"forks_count":4,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-12T03:52:57.293Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/redis-developer.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":"2021-02-27T04:23:42.000Z","updated_at":"2023-09-27T20:06:06.000Z","dependencies_parsed_at":"2024-06-19T09:50:01.676Z","dependency_job_id":"46f94ba8-2151-4d8d-a91a-56c0877e20dd","html_url":"https://github.com/redis-developer/basic-redis-rate-limiting-demo-go-lang","commit_stats":{"total_commits":39,"total_committers":4,"mean_commits":9.75,"dds":0.4871794871794872,"last_synced_commit":"e981f321e710a27d5673119a73155b062611fa22"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redis-developer%2Fbasic-redis-rate-limiting-demo-go-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redis-developer%2Fbasic-redis-rate-limiting-demo-go-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redis-developer%2Fbasic-redis-rate-limiting-demo-go-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redis-developer%2Fbasic-redis-rate-limiting-demo-go-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/redis-developer","download_url":"https://codeload.github.com/redis-developer/basic-redis-rate-limiting-demo-go-lang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248514209,"owners_count":21116899,"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-11-25T13:29:12.678Z","updated_at":"2025-04-12T03:53:03.991Z","avatar_url":"https://github.com/redis-developer.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rate Limiting app using Go and Redis\n\nA Rate-Limiter app built using Go and uses Redis as a backend\n\n\n## Technical Stack\n\n- Frontend: Go\n- Backend: Redis\n\n## How it works\n\nThis app will block connections from a client after surpassing certain amount of requests (default: 10) per time (default: 10 sec)\n\nThe application will return after each request the following headers. That will let the user know how many requests they have remaining before the run over the limit.\n\nOn the 10th run server should return an HTTP status code of **429 Too Many Requests**\n\n### Cookies\n\nUser identification based on cookies, on first request user will receive a cookie if it not exists\n`CookieName: user-limiter`\n`CookieValue: md5(\u003ccurrent time\u003e)`\n`\u003ccurrent time\u003e` - request time in a format: `2006-01-02 15:04:05.999999999 -0700 MST`\n\n### Redis Commands\n\n- Read requests for user by `user-limiter` cookie: `GET requests.\u003cUSER_IDENTIFIER\u003e` - get `USER_IDENTIFIER` from request cookie\n\n  - E.g `GET requests.0cbc6611f5540bd0809a388dc95a615b`\n\n- Set request counter with expired 10 sec if not exist in `requests.\u003cUSER_IDENTIFIER\u003e`: `SETEX requests.\u003cUSER_IDENTIFIER\u003e 10 0`\n\n  - E.g `SETEX requests.0cbc6611f5540bd0809a388dc95a615b 10 0`\n\n- Increment requests counter for each of user request: `INC requests.\u003cUSER_IDENTIFIER\u003e`\n\n  - E.g `INC requests.0cbc6611f5540bd0809a388dc95a615b`\n\n- Get requests number for user: `GET requests.\u003cUSER_IDENTIFIER\u003e`\n  - E.g `GET requests.0cbc6611f5540bd0809a388dc95a615b`\n\n#### Code for rate limiting\n\n```Go\nfunc (c Controller) AcceptedRequest(user string, limit int) (int, bool) {\n\tkey := c.key(user)\n\n\tif _, err := c.r.Get(key); err == redis.Nil {\n\t\terr := c.r.Set(key, \"0\", time.Second * time.Duration(limit))\n\t\tif err != nil {\n\t\t\tlog.Println(err)\n\t\t\treturn 0, false\n\t\t}\n\t}\n\n\tif err := c.r.Inc(key); err != nil {\n\t\tlog.Println(err)\n\t\treturn 0, false\n\t}\n\n\trequests, err := c.r.Get(key)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn 0,false\n\t}\n\trequestsNum, err := strconv.Atoi(requests)\n\tif err != nil {\n\t\tlog.Println(err)\n\t\treturn 0, false\n\t}\n\n\tif requestsNum \u003e limit {\n\t\treturn requestsNum, false\n\t}\n\n\treturn requestsNum, true\n}\n```\n\nWhere `c` corresponds to the active controller and `c.r` is a Redis client.\n\n### Response\n\n#### Status codes\n\n`200 - OK` - responded `PONG`\n\n`406 - Not Acceptable` - could not read cookie from request, it may have effect when cookies not allowed on browser side\n\n`429 - To Many Requests` - user send more than 10 requests / 10sec\n\n#### Headers\n\n`X-RateLimit-Limit: 10` - allowed number of limits per 10sec\n\n`X-RateLimit-Remaining: 9` - number of left request in 10sec window\n\n### Available commands\n\n```\n\"SETEX\", \"GET\", \"DEL\", \"INCR\"\n```\n\n## Hot to run it locally?\n\n### Prerequisites\n\n- Golang - v1.15\n\n### Local installation\n\n```\ngit clone https://github.com/redis-developer/basic-redis-rate-limiting-demo-go-lang/\n\n# copy file and set proper data inside\ncp .env.example .env\n\n# install dependencies\ngo get\n\n# run\ngo run main.go\n\n# open on browser\nhttp://localhost:5000\n\n```\n\n### Env variables:\n\n- API_HOST - host that server is listening on, default is all interfaces\n- API_PORT - port that server is listening on, default is 5000\n- API_PUBLIC_PATH - frontend location\n- REDIS_HOST - host for redis instance\n- REDIS_PORT - port for redis instance, default is 6379\n- REDIS_PASSWORD - password for redis. Running redis by docker-compose, there's no password. Running by https://redislabs.com/try-free/ you have to pass this variable.\n\n# Deployment\n\nTo make deploys work, you need to create free account in https://redislabs.com/try-free/ and get Redis' instance informations - REDIS_HOST, REDIS_PORT and REDIS_PASSWORD. You must pass them as environmental variables (in .env file or by server config, like `Heroku Config Variables`).\n\n### Google Cloud Run\n\n[![Run on Google\nCloud](https://deploy.cloud.run/button.svg)](https://deploy.cloud.run/?git_repo=https://github.com/redis-developer/basic-redis-rate-limiting-demo-go-lang.git)\n\n### Heroku\n\n[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredis-developer%2Fbasic-redis-rate-limiting-demo-go-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredis-developer%2Fbasic-redis-rate-limiting-demo-go-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredis-developer%2Fbasic-redis-rate-limiting-demo-go-lang/lists"}