{"id":23122850,"url":"https://github.com/wissance/gwuu","last_synced_at":"2025-10-14T05:22:44.323Z","repository":{"id":57571558,"uuid":"337394798","full_name":"Wissance/gwuu","owner":"Wissance","description":"Go web development extension over gorilla/mux and gorm","archived":false,"fork":false,"pushed_at":"2024-01-17T06:55:49.000Z","size":127,"stargazers_count":3,"open_issues_count":6,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-06-20T00:29:37.321Z","etag":null,"topics":["cors","db","go","golang","gorilla-mux","gorm","gorm-utils","preflight","testing","web"],"latest_commit_sha":null,"homepage":"https://wissance.github.io/gwuu/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Wissance.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-09T12:18:11.000Z","updated_at":"2022-06-29T18:43:05.000Z","dependencies_parsed_at":"2023-02-13T20:46:59.092Z","dependency_job_id":"9bfcfb0c-77a9-4186-96d6-b88b326d10bb","html_url":"https://github.com/Wissance/gwuu","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wissance%2Fgwuu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wissance%2Fgwuu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wissance%2Fgwuu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wissance%2Fgwuu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Wissance","download_url":"https://codeload.github.com/Wissance/gwuu/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230080775,"owners_count":18169619,"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":["cors","db","go","golang","gorilla-mux","gorm","gorm-utils","preflight","testing","web"],"created_at":"2024-12-17T07:31:03.340Z","updated_at":"2025-10-14T05:22:44.226Z","avatar_url":"https://github.com/Wissance.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gwuu (go web ultimate utils)\nThis is a set of ***ultimate utils*** (useful methods) when using `GO` programming language to develop a web applications.\n\nContains following tools:\n* `gorm` - set of functions to extend gorm features:\n    - build connection string (`Postgres`, `Mssql`, `Mysql`)\n    - create database (`Postgres`, `Mssql`, `Mysql`)\n    - drop database  (`Postgres`, `Mssql`, `Mysql`)\n    - get next identifier (sometimes `GORM` is unable to create entities with auto-generated identifiers therefore i have to gen it manually)\n    - get portion of data (data paging)\n\n* `testingutils` - a set of utils that makes unit testing easily\n* `api/rest` - a set of extensions for `github.comgorilla/mux` and `gin-gonic.gin`\n    - easy register `HandlerFunc` and you  get auto Preflight handler register too (response on `OPTION` resource) so that you API automatically support `CORS` now.\n\n## 1. Gorm\nAs were mentioned above we could make connection to any database (``MySql`, `MsSql` or `Postgres`) with creation specified database before, drop database. This functionality is especially useful in unit tests. I.e. see unit tests for more details. There are \n\n```go\nfunc TestPostgresOpenDbWithCreate(t *testing.T) {\n    // Create Db when open\n\tcfg := gorm.Config{}\n\tconnStr := BuildConnectionString(Postgres, \"127.0.0.1\", 5432, \"gwuu_examples\", dbUser, dbPassword, \"disable\")\n\ttestOpenDbWithCreateAndCheck(t, connStr, Postgres, \u0026cfg)\n}\n\nfunc TestMysqlOpenDbWithCreate(t *testing.T) {\n\tcfg := gorm.Config{}\n\tconnStr := BuildConnectionString(Mysql, \"127.0.0.1\", 3306, \"gwuu_examples\", dbUser, dbPassword, \"\")\n\ttestOpenDbWithCreateAndCheck(t, connStr, Mysql, \u0026cfg)\n}\n\nfunc TestMssqlOpenDbWithCreate(t *testing.T) {\n\tcfg := gorm.Config{}\n\tconnStr := BuildConnectionString(Mssql, \"localhost\", 1433, \"GwuuExamples\", dbUser, dbPassword, \"\")\n\ttestOpenDbWithCreateAndCheck(t, connStr, Mssql, \u0026cfg)\n}\n\nfunc testOpenDbWithCreateAndCheck(t *testing.T, connStr string, dialect SqlDialect, options *gorm.Config) {\n\tdb := OpenDb2(dialect, connStr, true, true, options)\n\tassert.NotNil(t, db)\n\t// Close\n\tCloseDb(db)\n\t// Drop\n\tDropDb(dialect, connStr)\n\t// Check\n\tcheckResult := CheckDb(dialect, connStr)\n\tassert.Equal(t, false, checkResult)\n}\n```\n\nWe could omit check parameter in that case Open database or Open database with create takes less time.\nWe are also could use function `CreateRandomDb` to get new database with random name.\n\n## 2. Testingutils\n\nContains following features:\n* a set of CheckType functions that allow to compare **ARRAYS** of primitive types i.e. CheckStrings, CheckFloats64, CheckComplexes \u0026 others for comparison \n  all following primitive types:\n    - `[]int`\n    - `[]int32`\n    - `[]uint32`\n    - `[]int64`\n    - `[]uint64`\n    - `[]float32`\n    - `[]float64`\n    - `[]complex64`\n    - `[]complex128`\n\nAll ***arrays could be compared with ORDER or WITHOUT it*** (for more details please see checkers_test). And one more thing that should be noted - all Check functions contains assertErr parameter which means if it was set to True error will be asserted via `assert.Equal` or `assert.True` function\n\n`floats and complex types could be compared with tollerance` i.e.:\n```go\nfunc TestCheckFloat64SuccessfulWithOrder(t *testing.T) {\n\tarr1 := make([]float64, 3)\n\tarr1[0] = 10.55\n\tarr1[1] = 99\n\tarr1[2] = 55.9\n\n\tarr2 := make([]float64, 3)\n\tarr2[0] = 11.01\n\tarr2[1] = 99\n\tarr2[2] = 55.6\n\n\tcheckResult, err := CheckFloats64(t, arr1, arr2, 0.5, true, true)\n\tassert.True(t, checkResult)\n\tassert.Empty(t, err)\n}\n\nfunc TestCheckComplex64SuccessfulWithOrder(t *testing.T) {\n\tarr1 := make([]complex64, 3)\n\tarr1[0] = complex(10.55, 9.12)\n\tarr1[1] = complex(99, 101)\n\tarr1[2] = complex(55.9, 67.23)\n\n\tarr2 := make([]complex64, 3)\n\tarr2[0] = complex(11.01, 9.49)\n\tarr2[1] = complex(99, 100.91)\n\tarr2[2] = complex(55.6, 66.88)\n\n\tcheckResult, err := CheckComplexes(t, arr1, arr2, 0.5, true, true)\n\tassert.True(t, checkResult)\n\tassert.Empty(t, err)\n}\n```\n\n## 3. Api/rest\nThis package is a extension for ***gorilla/mux*** and ***gin-gonic/gin***. In our lib we are having `HandleFunc` function which signature is almost equals to `mux.Router.HandleFunc`. Using `HandleFunc` from ***gwuu*** you will forget about Preflight Handlers register (OPTIONS method), they registers automatically and no more additional HandlerFunc anymore for OPTIONS method handling! Gin gonic extension has same `GET`, ``POST`, `PUT`, ``PATCH` and `DELETE` methods \n\n### 3.1 Gorilla/mux examples\n\n```go\nhandler := NewMuxBasedWebApiHandler(true, AnyOrigin)\n\t// Get only method\n\trealmResource := \"/api/realm/\"\n\thandler.HandleFunc(handler.Router, realmResource, func(writer http.ResponseWriter, request *http.Request) {\n\n\t}, \"GET\")\n\t// full crud\n\tuserResourceRoot := \"/api/user/\"\n\thandler.HandleFunc(handler.Router, userResourceRoot, func(writer http.ResponseWriter, request *http.Request) {\n\n\t}, \"GET\")\n\thandler.HandleFunc(handler.Router, userResourceRoot, func(writer http.ResponseWriter, request *http.Request) {\n\n\t}, \"POST\")\n\tuserResourceById := \"/api/user/{id:[0-9]+}/\"\n\thandler.HandleFunc(handler.Router, userResourceById, func(writer http.ResponseWriter, request *http.Request) {\n\n\t}, \"GET\")\n\thandler.HandleFunc(handler.Router, userResourceById, func(writer http.ResponseWriter, request *http.Request) {\n\n\t}, \"PUT\")\n\thandler.HandleFunc(handler.Router, userResourceById, func(writer http.ResponseWriter, request *http.Request) {\n\n\t}, \"DELETE\")\n```\n\nConsider above example you also get 3 additional automatically `OPTIONS` method handlers for:\n* `OPTIONS /api/realm/`\n* `OPTIONS /api/user/`\n* `OPTIONS /api/user/{id}/`\n\nUsing our HandlerFunc you **won't ever get CORS Error in JS frameworks/Web Browser**.\n\n### 3.2 gin-gonic/gin examples\n\nGin utilities **to auto handle Preflight requests** were also tested in the same manner as `gorilla/mux`:\n```go\nhandler := NewGinBasedWebApiHandler(true, AnyOrigin)\n\thandler.Router.RedirectTrailingSlash = true\n\n\trealmResource := \"/api/realm\"\n\trealmRoutes := handler.Router.Group(realmResource)\n\thandler.GET(realmRoutes, \"/\", func(ctx *gin.Context) {})\n\n\tuserResource := \"/api/user\"\n\tuserResourceByIdPath := \"/:id/\"\n\tuserRoutes := handler.Router.Group(userResource)\n\thandler.GET(userRoutes, \"/\", func(ctx *gin.Context) {})\n\thandler.POST(userRoutes, \"/\", func(ctx *gin.Context) {})\n\n\thandler.GET(userRoutes, userResourceByIdPath, func(ctx *gin.Context) {})\n\thandler.PUT(userRoutes, userResourceByIdPath, func(ctx *gin.Context) {})\n\thandler.DELETE(userRoutes, userResourceByIdPath, func(ctx *gin.Context) {})\n\n\t// Requests with trailing slashes ...\n\tcheckGinOptionRouteCors(t, handler.Router, realmResource+\"/\", AnyOrigin, \"*\", \"OPTIONS,GET\")\n\tcheckGinOptionRouteCors(t, handler.Router, userResource+\"/\", AnyOrigin, \"*\", \"OPTIONS,GET,POST\")\n\n\tcheckGinRouteCors(t, handler.Router, \"GET\", realmResource+\"/\", AnyOrigin)\n\n\tcheckGinRouteCors(t, handler.Router, \"GET\", userResource+\"/\", AnyOrigin)\n\tcheckGinRouteCors(t, handler.Router, \"POST\", userResource+\"/\", AnyOrigin)\n\n\tuserById := \"/api/user/123/\"\n\tcheckGinOptionRouteCors(t, handler.Router, userById, AnyOrigin, \"*\", \"OPTIONS,GET,PUT,DELETE\")\n\n\tcheckGinRouteCors(t, handler.Router, \"GET\", userById, AnyOrigin)\n\tcheckGinRouteCors(t, handler.Router, \"PUT\", userById, AnyOrigin)\n\tcheckGinRouteCors(t, handler.Router, \"DELETE\", userById, AnyOrigin)\n```\n\n# Useful materials\n* our article on medium about how to work with https://m-ushakov.medium.com/intricacies-of-working-with-gorm-3d336f310\n* our Yandex Zen article: https://zen.yandex.ru/media/id/5f9bbb6eb5987b74e7014a6f/osobennosti-raboty-s-gorm-605234513eb679416826d74c\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwissance%2Fgwuu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwissance%2Fgwuu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwissance%2Fgwuu/lists"}