{"id":21726330,"url":"https://github.com/nanvenomous/optic","last_synced_at":"2025-08-19T13:06:38.891Z","repository":{"id":175330027,"uuid":"651669667","full_name":"nanvenomous/optic","owner":"nanvenomous","description":"A simplified, generic, entity based web library for golang that's drop in compatible with net/http","archived":false,"fork":false,"pushed_at":"2023-07-14T05:07:11.000Z","size":187,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"mainline","last_synced_at":"2025-04-12T23:09:14.742Z","etag":null,"topics":["best","blazingly-fast","comparison","framework","generics","go","golang","http","memory-efficient","reddit","requests","server","simple","web","web-application","web-development"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nanvenomous.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-06-09T19:17:16.000Z","updated_at":"2025-04-02T09:26:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"eaee22f1-6f32-4fa2-a0df-9634b3a5641b","html_url":"https://github.com/nanvenomous/optic","commit_stats":null,"previous_names":["nanvenomous/optic","nanvenomous/toss"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanvenomous%2Foptic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanvenomous%2Foptic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanvenomous%2Foptic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanvenomous%2Foptic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nanvenomous","download_url":"https://codeload.github.com/nanvenomous/optic/tar.gz/refs/heads/mainline","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248643004,"owners_count":21138355,"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":["best","blazingly-fast","comparison","framework","generics","go","golang","http","memory-efficient","reddit","requests","server","simple","web","web-application","web-development"],"created_at":"2024-11-26T03:24:29.995Z","updated_at":"2025-04-12T23:09:21.211Z","avatar_url":"https://github.com/nanvenomous.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# (o)ptic\n\nA generic web extension to [net/http](https://pkg.go.dev/net/http)\n\nOptic helps you call backend functions from your frontend by sending a regular go struct and recieving a struct back\n\nIt is especially useful when making requests to a go service from a go client (WASM app, cli, tui ...)\n\n## Install\n```bash\ngo get github.com/nanvenomous/optic\n```\nThen import with\n```go\nimport (\n\t\"github.com/nanvenomous/optic\"\n)\n```\n\n## Quick example\n\nDefine the entities and error interface\n```go\ntype solution struct {\n\tAnswer int\n}\ntype division struct {\n\tTop    int\n\tBottom int\n}\ntype userHTTPError struct {\n\tMessage string\n\tCode    int\n}\nfunc (e *userHTTPError) GetCode() int {\n\treturn e.Code\n}\n```\n\nSetup the service route\n```go\nfunc divide(recieved *division, _ *http.Request) (*solution, optic.HTTPError) {\n\tif recieved.Bottom == 0 { // return an error\n\t\treturn nil, \u0026userHTTPError{Code: http.StatusUnprocessableEntity, Message: \"Impossible to divide by Zero\"}\n\t}\n\treturn \u0026solution{Answer: recieved.Top / recieved.Bottom}, nil\n}\n\nfunc main() {\n\tvar (\n\t\terr       error\n\t\tencodeErr = \u0026userHTTPError{Code: http.StatusInternalServerError, Message: \"Failed to encode your response.\"}\n\t\tdecodeErr = \u0026userHTTPError{Code: http.StatusNotAcceptable, Message: \"Failed to decode your request body.\"}\n\t\tmux       *http.ServeMux\n\t)\n\tmux = http.NewServeMux()\n\toptic.SetupService(port, userOpticRoute, encodeErr, decodeErr, mux)\n\t// An optical mirror simply recieves information and sends information back\n\toptic.Mirror(divide) // by default optic will use function name as route\n\terr = optic.Serve() // run the service\n}\n```\n\nSetup the client and make a request\n```go\nfunc main {\n\toptic.SetupClient(host, port, userOpticRoute, false)\n\t// Make requests\n\tvar (\n\t\terr     error          // internal error\n\t\thttpErr *userHTTPError // service exception\n\t\tsln     solution       // output\n\t)\n\t//                                                     send                          receive\n\thttpErr, err = optic.Glance[userHTTPError](\"/divide/\", \u0026division{Top: 4, Bottom: 2}, \u0026sln)\n\tfmt.Println(err, httpErr) // \u003cnil\u003e \u003cnil\u003e\n\tfmt.Println(sln.Answer)   // 2\n}\n```\n\n## net/http compatibility\nOptic is drop in compatible with [net/http](https://pkg.go.dev/net/http)\n\nGive optic a `*http.ServerMux` \u0026 a special route where it will handle all you functions\n\nThen do whatever else you want with that mux\n```go\nfunc main() {\n\tvar (\n\t\terr error\n\t\tmux *http.ServeMux\n\t)\n\tmux = http.NewServeMux()\n\toptic.SetupService(port, userOpticRoute, encodeErr, decodeErr, mux)\n\n\t// Add other routes not handled by optic, as you would with any net/http service\n\tmux.HandleFunc(\"/health-check/\", func(w http.ResponseWriter, _ *http.Request) {\n\t\tw.WriteHeader(http.StatusOK)\n\t})\n\n    // optic can register middleware for you\n\toptic.RegisterMiddleware(exampleMiddleware)\n    // or you can do it yourself\n    var (\n        handler http.Handler\n    )\n    handler = exampleMiddleware(mux)\n}\n\nfunc exampleMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t// add some middleware (like CORS for example)\n\t\tw.Header().Set(\"Access-Control-Allow-Origin\", \"*\")\n\t\tnext.ServeHTTP(w, r)\n\t})\n}\n```\n\n## Examples\nFor the full example in code see [./examples/main.go](https://github.com/nanvenomous/optic/blob/mainline/example/main.go) \n\nRun the example like so:\n![run example](.rsrc/run-example.gif)\n\n## Community\nI am planning some outreach so I can get feedback from other go developers \u0026 aiming to address major concerns between each post\n\n- [x] [reddit post](https://www.reddit.com/r/golang/comments/14v3936/nethttp_extension_to_exchange_structs/)\n    - [x] Lack of transparency in error handling, poor naming convention `Exception`, removing unessecary generics [resolution commit](https://github.com/nanvenomous/optic/commit/f5bb4ba464351ae9cef5a0d5f5934984350f04a7)\n    - [x] using revive for better code analysis, tightened up module exports - [resolution commit](https://github.com/nanvenomous/optic/commit/cfb8a4121a468c863b5bfa6559005a4d6c4829cc)\n\n## Simplicity\nhttps://github.com/nanvenomous/optic/blob/b8a94eb20e2ae535252c56ea8d283f2b794cffd4/go.mod#L1-L3\n\n\n## Inspiration\nI drew some inspiration from [leptos server functions](https://leptos-rs.github.io/leptos/server/25_server_functions.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnanvenomous%2Foptic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnanvenomous%2Foptic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnanvenomous%2Foptic/lists"}