{"id":21626977,"url":"https://github.com/komuw/ong","last_synced_at":"2025-04-11T12:46:39.856Z","repository":{"id":36974919,"uuid":"208572460","full_name":"komuw/ong","owner":"komuw","description":"ong, is a Go http toolkit. ","archived":false,"fork":false,"pushed_at":"2024-04-14T16:29:56.000Z","size":13299,"stargazers_count":15,"open_issues_count":37,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-16T03:52:29.859Z","etag":null,"topics":["go","golang","middleware"],"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/komuw.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2019-09-15T09:45:29.000Z","updated_at":"2024-04-22T20:45:40.300Z","dependencies_parsed_at":"2023-09-23T04:16:03.254Z","dependency_job_id":"52baa09f-8747-4fab-aabf-2968dcd8b0e2","html_url":"https://github.com/komuw/ong","commit_stats":null,"previous_names":[],"tags_count":91,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/komuw%2Fong","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/komuw%2Fong/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/komuw%2Fong/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/komuw%2Fong/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/komuw","download_url":"https://codeload.github.com/komuw/ong/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248402546,"owners_count":21097331,"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","middleware"],"created_at":"2024-11-25T01:15:05.245Z","updated_at":"2025-04-11T12:46:39.828Z","avatar_url":"https://github.com/komuw.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ong\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/komuw/ong.svg)](https://pkg.go.dev/github.com/komuw/ong)     \n[![ci](https://github.com/komuw/ong/actions/workflows/ci.yml/badge.svg)](https://github.com/komuw/ong/actions)     \n[![codecov](https://codecov.io/gh/komuw/ong/branch/main/graph/badge.svg?token=KMX47WCNK0)](https://codecov.io/gh/komuw/ong)     \n\n\nOng is a small http toolkit. \n\nIt's name is derived from Tanzanian artiste, [Remmy Ongala](https://en.wikipedia.org/wiki/Remmy_Ongala).\n\n\nInspired by; `How I Write HTTP Web Services after Eight Years`[1][2] by Mat Ryer.    \n\n\nYou really should **not** use this library/toolkit.    \nInstead, use the Go `net/http` package; and if you need some extra bits, may I suggest the awesome [github.com/gorilla](https://github.com/gorilla) web toolkit.    \n\n\nThis library is made just for me, it might be unsafe \u0026 it does not generally accept code contributions.       \n\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/komuw/ong/config\"\n\t\"github.com/komuw/ong/log\"\n\t\"github.com/komuw/ong/middleware\"\n\t\"github.com/komuw/ong/mux\"\n\t\"github.com/komuw/ong/server\"\n)\n\nfunc main() {\n\tl := log.New(context.Background(), os.Stdout, 1000)\n\tsecretKey := \"super-h@rd-Pas1word\"\n\topts := config.WithOpts(\n\t\t\"localhost\",\n\t\t65081,\n\t\tsecretKey,\n\t\tconfig.DirectIpStrategy,\n\t\tl,\n\t) // dev options.\n\t// alternatively for production:\n\t//   opts := config.LetsEncryptOpts(...)\n\n\tmx := mux.New(\n\t\topts,\n\t\tnil,\n\t\tmux.NewRoute(\n\t\t\t\"hello/\",\n\t\t\tmux.MethodGet,\n\t\t\thello(\"hello world\"),\n\t\t),\n\t\tmux.NewRoute(\n\t\t\t\"check/:age/\",\n\t\t\tmux.MethodAll,\n\t\t\tcheck(),\n\t\t),\n\t)\n\n\terr := server.Run(mx, opts)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\tos.Exit(1)\n\t}\n}\n\nfunc hello(msg string) http.HandlerFunc {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tcspNonce := middleware.GetCspNonce(r.Context())\n\t\tcsrfToken := middleware.GetCsrfToken(r.Context())\n\t\tfmt.Printf(\"hello called cspNonce: %s, csrfToken: %s\", cspNonce, csrfToken)\n\n\t\t// use msg, which is a dependency specific to this handler\n\t\tfmt.Fprint(w, msg)\n\t}\n}\n\nfunc check() http.HandlerFunc {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tage := mux.Param(r.Context(), \"age\")\n\t\t_, _ = fmt.Fprintf(w, \"Age is %s\", age)\n\t}\n}\n```\n\n`go run -race ./...`       \n\nA more complete example can be found in the `example/` folder.      \n\n\n\n### References:\n1. https://www.youtube.com/watch?v=rWBSMsLG8po     \n2. https://pace.dev/blog/2018/05/09/how-I-write-http-services-after-eight-years.html     \n\n\n### Features:\nThe simplest production ready program using `ong` http toolkit would be something like;\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/komuw/ong/config\"\n\t\"github.com/komuw/ong/log\"\n\t\"github.com/komuw/ong/mux\"\n\t\"github.com/komuw/ong/server\"\n)\n\nfunc main() {\n\tlogger := log.New(context.Background(), os.Stdout, 1000)\n\tdomain := \"example.com\"\n\tsecretKey := \"super-h@rd-Pas1word\"\n\temail := \"hey@example.com\"\n\topts := config.LetsEncryptOpts(\n\t\tdomain, secretKey, config.DirectIpStrategy, logger, email, []string{domain})\n\n\tmx := mux.New(opts, nil, mux.NewRoute(\"hello/\", mux.MethodGet, hello()))\n\t_ = server.Run(mx, opts)\n}\n\nfunc hello() http.HandlerFunc {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tfmt.Fprint(w, \"hello\")\n\t}\n}\n```\nIf you do that, these are the features you would enjoy automatically without doing any extra configuration;\n1. Http server. You get a server that automatically;     \n   - sets GOMEMLIMIT \u0026 GOMAXPROCS to match linux container memory \u0026 cpu quotas.  \n   - fetches and auto renews TLS certificates from [letsencrypt](https://letsencrypt.org/) or any other compatible ACME authority.\n   - serves pprof endpoints that are secured by basic authentication. The `secretKey` is used as the username and password.\n   - handles automatic http-\u003ehttps redirection.\n   - implements robust http timeouts to prevent attacks.\n   - limits size of request bodies to prevent attacks.\n   - shutsdown cleanly after receiving termination signals. If running in kubernetes, the shutdown is [well co-ordinated](https://twitter.com/thockin/status/1560398974929973248) to prevent errors.\n   - Reuses port(`SO_REUSEPORT`) and reuses address(`SO_REUSEADDR`). This makes it possible to do zero downtime deploys. \n2. Automatic ratelimiting.\n3. Automatic loadshedding.\n4. Automatic proper handling of [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)\n5. Automatic [CSRF](https://developer.mozilla.org/en-US/docs/Glossary/CSRF) protection.\n6. Automatic logging of erroring requests with correlation IDs included.\n   The logging is lightweight so it only logs when an error occurs. Importantly, when the error occurs, it also includes all the log statements that occured before(**including** the non-error ones).\n   This is possible because [ong/log](https://pkg.go.dev/github.com/komuw/ong/log) uses a [circular buffer](https://www.komu.engineer/blogs/09/log-without-losing-context#Solution)\n7. Automatic recovery of panics in http handlers and logging of the same including stack traces.\n8. Automatic addition of the [real client IP](https://adam-p.ca/blog/2022/03/x-forwarded-for/) to request context.\n9. Protection against inadvertent form re-submission.\n10. Automatically sets appropriate secure headers(`X-Content-Type-Options`, `Content-Security-Policy`, `X-Frame-Options`, `Cross-Origin-Resource-Policy`, `Cross-Origin-Opener-Policy`, `Referrer-Policy`, `Strict-Transport-Security`)\n11. Automatic addition of TLS fingerprint to request context. \n12. Set's up secure authenticated encrypted http sessions.\n13. Uses a http request multiplexer that;     \n    - panics(during application startup) if there are any conflicting routes.\n    - has a debugging tool where if given a url, it will return the corresponding http handler for that url.\n    - can capture path parameters\n\n\nThose are the automatic ones. There are a few additional features that you can opt into;\n1. A [http client](https://pkg.go.dev/github.com/komuw/ong/client) that properly handles [server-side request forgery](https://en.wikipedia.org/wiki/Server-side_request_forgery) attacks. \n2. A [cookie](https://pkg.go.dev/github.com/komuw/ong/cookie) package that enables you to work with both plain text cookies and also authenticated encrypted cookies.\n3. A [cryptography](https://pkg.go.dev/github.com/komuw/ong/cry) package that simplifies using authenticated encryption and also hashing.\n4. An [errors](https://pkg.go.dev/github.com/komuw/ong/errors) package that includes error wrapping and stack trace support.\n5. An [id](https://pkg.go.dev/github.com/komuw/ong/id) package that can generate unique random human friendly identifiers, as well as uuid4(does not leak its creation time) and uuid8(has good database locality).\n6. A [log](https://pkg.go.dev/github.com/komuw/ong/log) package that implements [slog.Logger](https://pkg.go.dev/log/slog#Logger) and is backed by an [slog.Handler](https://pkg.go.dev/log/slog#Handler) that stores log messages into a circular buffer.  \n7. A [sess](https://pkg.go.dev/github.com/komuw/ong/sess) package that makes it easy to work with http sessions that are backed by tamper-proof \u0026 encrypted cookies.   \n8. A [sync](https://pkg.go.dev/github.com/komuw/ong/sync) package that makes it easier to work with groups of goroutines working on subtasks of a common task.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkomuw%2Fong","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkomuw%2Fong","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkomuw%2Fong/lists"}