{"id":19313704,"url":"https://github.com/sang-w0o/gag","last_synced_at":"2025-04-22T16:31:24.837Z","repository":{"id":54335654,"uuid":"521576938","full_name":"sang-w0o/gag","owner":"sang-w0o","description":"Gag is an API Gateway, implemented in Go.","archived":false,"fork":false,"pushed_at":"2022-09-25T06:53:39.000Z","size":15,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-21T03:17:43.526Z","etag":null,"topics":["api-composition","api-gateway","golang","http"],"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/sang-w0o.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":".github/CODEOWNERS","security":null,"support":null}},"created_at":"2022-08-05T09:21:16.000Z","updated_at":"2022-08-17T01:33:58.000Z","dependencies_parsed_at":"2022-08-13T12:20:45.566Z","dependency_job_id":null,"html_url":"https://github.com/sang-w0o/gag","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sang-w0o%2Fgag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sang-w0o%2Fgag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sang-w0o%2Fgag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sang-w0o%2Fgag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sang-w0o","download_url":"https://codeload.github.com/sang-w0o/gag/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223900316,"owners_count":17222028,"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":["api-composition","api-gateway","golang","http"],"created_at":"2024-11-10T00:40:48.707Z","updated_at":"2024-11-10T00:40:49.300Z","avatar_url":"https://github.com/sang-w0o.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Go Reference](https://pkg.go.dev/badge/github.com/sang-w0o/gag.svg)](https://pkg.go.dev/github.com/sang-w0o/gag)\n\n# Gag \n\n- Gag is an HTTP API Gateway, implemented in Go.  \n  Gag provides a declarative interface, and it is highly configurable.\n\n### Supported features\n\n- Handle requests based on path.\n- Handle requests based on HTTP method.\n- Handle requests that have configured header key.\n- Handle requests that have configured header key, along with value.\n- Handle requests with your own handler, which implements [API composition pattern](https://microservices.io/patterns/data/api-composition.html)\n- Route(redirect) requests to different services.\n- Apply middlewares for each request.\n\n### Examples\n\n\u003e You can see more example codes using Gag in [examples](https://github.com/sang-w0o/gag/tree/master/examples).\n\n#### Simple Routing\n\n```go\nfunc main() {\n    g := gag.NewGag(gag.Config{Port: 8080})\n    g.Conditions.\n        Path(\"/foo\").Method(http.MethodGet).Route(\u0026gag.RouteRequest{Url: \"http://some.url/route-to\", HttpMethod: http.MethodGet}, g)\n    err := g.Serve()\n    if err != nil {\n        panic(err)\n    }\n}\n```\n\n- In the above example, only requests that match `/foo` path, has HTTP GET method will be routed to `http://some.url/route-to`.\n\n#### Simple handling\n\n```go\ntype sampleResponse struct {\n    Message string `json:\"message\"`\n}\n\nfunc sampleHandler() http.HandlerFunc {\n    return func(w http.ResponseWriter, r *http.Request) {\n        res, err := json.Marshal(sampleResponse{Message: \"sample handler!\"})\n        if err != nil {\n            w.WriteHeader(http.StatusInternalServerError)\n            w.Write([]byte(\"something went wrong..\"))\n        }\n        w.Header().Add(\"Content-Type\", \"application/json\")\n        w.WriteHeader(http.StatusOK)\n        w.Write(res)\n    }\n}\n\nfunc main() {\n    g := gag.NewGag(gag.Config{Port: 8080})\n    g.Conditions.\n        Path(\"/bar\").Method(http.MethodPost).HandlerFunc(sampleHandler(), g)\n    err := g.Serve()\n    if err != nil {\n        panic(err)\n    }\n}\n```\n\n- In the above example, only requests that match `/bar` path, has HTTP POST method will be handled.\n\n#### Using middlewares\n\n```go\nfunc sampleTimingMiddleware() func(h http.Handler) http.Handler {\n    return func(h http.Handler) http.Handler {\n        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n            start := time.Now()\n            h.ServeHTTP(w, r)\n            end := time.Now()\n            log.Printf(\"request time for %s: %v\", r.URL.Path, end.Sub(start))\n        })\n    }\n}\n\nfunc main() {\n    g := gag.NewGag(gag.Config{Port: 8080})\n\tg.Conditions().\n\t\tPath(\"/some-path\").Middlewares(sampleTimingMiddleware()).HandlerFunc(sampleHandler(), g)\n\terr := g.Serve()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n```\n\n- Since Gag is built on top of [gorilla/mux](https://github.com/gorilla/mux), path supports path variables and much more.   \n  Below is an example code using path variable.\n\n```go\nfunc samplePathVariableHandler() http.HandlerFunc {\n\n\ttype sampleResponse struct {\n\t\tMessage string `json:\"message\"`\n\t}\n\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tvars := gorillaMux.Vars(r)\n\t\tid, ok := vars[\"id\"]\n\t\tif !ok {\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\tw.Write([]byte(\"something went wrong..\"))\n\t\t}\n\t\tres, err := json.Marshal(sampleResponse{Message: fmt.Sprintf(\"id: %s\", id)})\n\t\tif err != nil {\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\tw.Write([]byte(\"something went wrong..\"))\n\t\t}\n\t\tw.Header().Add(\"Content-Type\", \"application/json\")\n\t\tw.WriteHeader(http.StatusOK)\n\t\tw.Write(res)\n\t}\n}\n\nfunc main() {\n    g := gag.NewGag(gag.Config{Port: 8080})\n\tg.Conditions().\n        Path(\"/this-is-path/{id}\").HandlerFunc(samplePathVariableHandler(), g)\n    err := g.Serve()\n    if err != nil {\n        panic(err)\n    }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsang-w0o%2Fgag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsang-w0o%2Fgag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsang-w0o%2Fgag/lists"}