{"id":13723258,"url":"https://github.com/nanmu42/limitio","last_synced_at":"2025-04-14T19:00:23.090Z","repository":{"id":70181220,"uuid":"370556384","full_name":"nanmu42/limitio","owner":"nanmu42","description":"Golang io.Reader and io.Writer but with limits","archived":false,"fork":false,"pushed_at":"2023-02-14T03:08:10.000Z","size":17,"stargazers_count":77,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T07:22:29.552Z","etag":null,"topics":["go","golang","io"],"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/nanmu42.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"nanmu42"}},"created_at":"2021-05-25T03:48:22.000Z","updated_at":"2025-03-14T23:54:53.000Z","dependencies_parsed_at":"2023-02-22T16:45:11.570Z","dependency_job_id":null,"html_url":"https://github.com/nanmu42/limitio","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanmu42%2Flimitio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanmu42%2Flimitio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanmu42%2Flimitio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanmu42%2Flimitio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nanmu42","download_url":"https://codeload.github.com/nanmu42/limitio/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248943374,"owners_count":21186954,"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":["go","golang","io"],"created_at":"2024-08-03T01:01:37.934Z","updated_at":"2025-04-14T19:00:22.972Z","avatar_url":"https://github.com/nanmu42.png","language":"Go","funding_links":["https://github.com/sponsors/nanmu42"],"categories":["Go"],"sub_categories":[],"readme":"# LimitIO\n\n[![GoDoc](https://godoc.org/github.com/nanmu42/limitio?status.svg)](https://pkg.go.dev/github.com/nanmu42/limitio)\n[![Build status](https://github.com/nanmu42/limitio/workflows/test/badge.svg)](https://github.com/nanmu42/limitio/actions)\n[![codecov](https://codecov.io/gh/nanmu42/limitio/branch/master/graph/badge.svg)](https://codecov.io/gh/nanmu42/limitio)\n[![Go Report Card](https://goreportcard.com/badge/github.com/nanmu42/limitio)](https://goreportcard.com/report/github.com/nanmu42/limitio)\n\n`io.Reader` and `io.Writer` with limit.\n\n```bash\ngo get github.com/nanmu42/limitio\n```\n\n## Rationale and Usage\n\nThere are times when a limited reader or writer comes in handy.\n\n1. wrap upstream so that reading is metered and limited:\n\n```go\n// request is an incoming http.Request\nrequest.Body = limitio.NewReadCloser(c.Request.Body, maxRequestBodySize, false)\n\n// deal with the body now with easy mind. It's maximum size is assured.\n```\n\nYes, `io.LimitReader` works the same way, but throws `EOF` on exceeding limit, which is confusing.\n\nLimitIO provides error that can be identified.\n\n```go\ndecoder := json.NewDecoder(request.Body)\nerr := decoder.Decode(\u0026myStruct)\nif err != nil {\n    if errors.Is(err, limitio.ErrThresholdExceeded) {\n        // oops, we reached the limit\n    }\n\n    err = fmt.Errorf(\"other error happened: %w\", err)\n    return\n}\n```\n\n2. wrap downstream so that writing is metered and limited(or instead, just pretending writing):\n\n```go\n// request is an incoming http.Request.\n// Say, we want to record its body somewhere in the middleware,\n// but feeling uneasy since its body might be HUGE, which may\n// result in OOM and a successful DDOS...\n\nvar reqBuf bytes.buffer\n\n// a limited writer comes to rescue!\n// `true` means after reaching `RequestBodyMaxLength`,\n// `limitedReqBuf` will start pretending writing so that\n// io.TeeReader continues working while reqBuf stays unmodified.\nlimitedReqBuf := limitio.NewWriter(\u0026reqBuf, RequestBodyMaxLength, true)\n\nrequest.Body = \u0026readCloser{\n    Reader: io.TeeReader(request.Body, limitedReqBuf), \n    Closer: c.Request.Body,\n}\n```\n\nLimitIO provides Reader, Writer and their Closer versions, for details, see [docs](https://pkg.go.dev/github.com/nanmu42/limitio).\n\n## Status: Stable\n\nLimitIO is well battle tested under production environment.\n\nAPIs are subjected to change in backward compatible way during 1.x releases.\n\n## License\n\nMIT License\n\nCopyright (c) 2021 LI Zhennan\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnanmu42%2Flimitio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnanmu42%2Flimitio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnanmu42%2Flimitio/lists"}