diff --git a/go.mod b/go.mod index 51aa7a6..ca52f41 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,19 @@ module github.com/loopfz/gadgeto require ( github.com/gin-gonic/gin v1.6.3 github.com/go-gorp/gorp v2.2.0+incompatible + github.com/go-playground/validator/v10 v10.2.0 + github.com/go-sql-driver/mysql v1.5.0 // indirect github.com/golang/protobuf v1.3.5 // indirect github.com/google/uuid v1.1.1 github.com/juju/errors v0.0.0-20200330140219-3fe23663418f + github.com/juju/testing v0.0.0-20210302031854-2c7ee8570c07 // indirect + github.com/lib/pq v1.9.0 // indirect github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect - golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect - gopkg.in/go-playground/validator.v8 v8.18.2 // indirect - gopkg.in/go-playground/validator.v9 v9.31.0 + github.com/pires/go-proxyproto v0.5.0 + github.com/poy/onpar v1.1.2 // indirect + github.com/ziutek/mymysql v1.5.4 // indirect ) go 1.13 diff --git a/go.sum b/go.sum index 0cdbb84..2ff81c2 100644 --- a/go.sum +++ b/go.sum @@ -1,54 +1,139 @@ +cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/a8m/expect v1.0.0/go.mod h1:4IwSCMumY49ScypDnjNbYEjgVeqy1/U2cEs3Lat96eA= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gin-contrib/sse v0.0.0-20190125020943-a7658810eb74 h1:FaI7wNyesdMBSkIRVUuEEYEvmzufs7EqQvRAxfEXGbQ= -github.com/gin-contrib/sse v0.0.0-20190125020943-a7658810eb74/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.3.0 h1:kCmZyPklC0gVdL728E6Aj20uYBJV93nj/TkwBTKhFbs= -github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= -github.com/gin-gonic/gin v1.6.1 h1:o2JrfzL6NvnLVI/h1x4E+E9nocCp66GEKqPfhoCjlTs= -github.com/gin-gonic/gin v1.6.1/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/go-gorp/gorp v1.7.2 h1:C5uGH8zK2qjMJZGC308ZegdGXMrMjYmA++IIMeKSKnc= github.com/go-gorp/gorp v2.2.0+incompatible h1:xAUh4QgEeqPPhK3vxZN+bzrim1z5Av6q837gtjUlshc= github.com/go-gorp/gorp v2.2.0+incompatible/go.mod h1:7IfkAQnO7jfT/9IQ3R9wL1dFhukN6aQxzKTHnkxzA/E= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= -github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/juju/ansiterm v0.0.0-20160907234532-b99631de12cf/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= +github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= +github.com/juju/cmd v0.0.0-20171107070456-e74f39857ca0/go.mod h1:yWJQHl73rdSX4DHVKGqkAip+huBslxRwS8m9CrOLq18= +github.com/juju/collections v0.0.0-20200605021417-0d0ec82b7271/go.mod h1:5XgO71dV1JClcOJE+4dzdn4HrI5LiyKd7PlVG6eZYhY= +github.com/juju/errors v0.0.0-20150916125642-1b5e39b83d18/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= github.com/juju/errors v0.0.0-20200330140219-3fe23663418f h1:MCOvExGLpaSIzLYB4iQXEHP4jYVU6vmzLNQPdMVrxnM= github.com/juju/errors v0.0.0-20200330140219-3fe23663418f/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= -github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= -github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= +github.com/juju/httpprof v0.0.0-20141217160036-14bf14c30767/go.mod h1:+MaLYz4PumRkkyHYeXJ2G5g5cIW0sli2bOfpmbaMV/g= +github.com/juju/loggo v0.0.0-20170605014607-8232ab8918d9/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/loggo v0.0.0-20200526014432-9ce3a2e09b5e h1:FdDd7bdI6cjq5vaoYlK1mfQYfF9sF2VZw8VEZMsl5t8= +github.com/juju/loggo v0.0.0-20200526014432-9ce3a2e09b5e/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/mgo/v2 v2.0.0-20210302023703-70d5d206e208 h1:/WiCm+Vpj87e4QWuWwPD/bNE9kDrWCLvPBHOQNcG2+A= +github.com/juju/mgo/v2 v2.0.0-20210302023703-70d5d206e208/go.mod h1:0OChplkvPTZ174D2FYZXg4IB9hbEwyHkD+zT+/eK+Fg= +github.com/juju/mutex v0.0.0-20171110020013-1fe2a4bf0a3a/go.mod h1:Y3oOzHH8CQ0Ppt0oCKJ2JFO81/EsWenH5AEqigLH+yY= +github.com/juju/retry v0.0.0-20151029024821-62c620325291/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= +github.com/juju/retry v0.0.0-20180821225755-9058e192b216/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= +github.com/juju/testing v0.0.0-20180402130637-44801989f0f7/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/juju/testing v0.0.0-20210302031854-2c7ee8570c07 h1:6QA3rIUc3TBPbv8zWa2KQ2TWn6gsn1EU0UhwRi6kOhA= +github.com/juju/testing v0.0.0-20210302031854-2c7ee8570c07/go.mod h1:7lxZW0B50+xdGFkvhAb8bwAGt6IU87JB1H9w4t8MNVM= +github.com/juju/utils v0.0.0-20180424094159-2000ea4ff043/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= +github.com/juju/utils v0.0.0-20200116185830-d40c2fe10647/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= +github.com/juju/utils/v2 v2.0.0-20200923005554-4646bfea2ef1/go.mod h1:fdlDtQlzundleLLz/ggoYinEt/LmnrpNKcNTABQATNI= +github.com/juju/version v0.0.0-20161031051906-1f41e27e54f2/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= +github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= +github.com/juju/version v0.0.0-20191219164919-81c1be00b9a6/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= +github.com/julienschmidt/httprouter v1.1.1-0.20151013225520-77a895ad01eb/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lunixbochs/vtclean v0.0.0-20160125035106-4fbf7632a2c6/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/masterzen/azure-sdk-for-go v3.2.0-beta.0.20161014135628-ee4f0065d00c+incompatible/go.mod h1:mf8fjOu33zCqxUjuiU3I8S1lJMyEAlH+0F2+M5xl3hE= +github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= +github.com/masterzen/winrm v0.0.0-20161014151040-7a535cd943fc/go.mod h1:CfZSN7zwz5gJiFhZJz49Uzk7mEBHIceWmbFmYx7Hf7E= +github.com/masterzen/xmlpath v0.0.0-20140218185901-13f4951698ad/go.mod h1:A0zPC53iKKKcXYxr4ROjpQRQ5FgJXtelNdSmHHuq/tY= +github.com/mattn/go-colorable v0.0.6/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-sqlite3 v1.13.0 h1:LnJI81JidiW9r7pS/hXe6cFeO5EXNq7KbfvoJLRI69c= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -57,31 +142,143 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nelsam/hel/v2 v2.3.2 h1:tXRsJBqRxj4ISSPCrXhbqF8sT+BXA/UaIvjhYjP5Bhk= +github.com/nelsam/hel/v2 v2.3.2/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= +github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pires/go-proxyproto v0.5.0 h1:A4Jv4ZCaV3AFJeGh5mGwkz4iuWUYMlQ7IoO/GTuSuLo= +github.com/pires/go-proxyproto v0.5.0/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/poy/onpar v0.0.0-20200406201722-06f95a1c68e8/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= +github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= +github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= -github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v0.0.0-20190128213124-ee1426cffec0 h1:Q3Bh5Dwzek5LreV9l86IftyLaexgU1mag9WNntbAW9c= -github.com/ugorji/go/codec v0.0.0-20190128213124-ee1426cffec0/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180214000028-650f4a345ab4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200313205530-4303120df7d8/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= -gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= -gopkg.in/go-playground/validator.v9 v9.26.0 h1:2NPPsBpD0ZoxshmLWewQru8rWmbT5JqSzz9D1ZrAjYQ= -gopkg.in/go-playground/validator.v9 v9.26.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= -gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M= -gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v1 v1.0.0-20161222125816-442357a80af5/go.mod h1:u0ALmqvLRxLI95fkdCEWrE6mhWYZW1aMOJHp5YXLHTg= +gopkg.in/httprequest.v1 v1.1.1/go.mod h1:/CkavNL+g3qLOrpFHVrEx4NKepeqR4XTZWNj4sGGjz0= +gopkg.in/mgo.v2 v2.0.0-20160818015218-f2b6f6c918c4/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637/go.mod h1:BHsqpu/nsuzkT5BpiH1EMZPLyqSMM8JbIavyFACoFNk= +gopkg.in/yaml.v2 v2.0.0-20170712054546-1be3d31502d6/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= +launchpad.net/xmlpath v0.0.0-20130614043138-000000000004/go.mod h1:vqyExLOM3qBx7mvYRkoxjSCF945s0mbe7YynlKYXtsA= diff --git a/tonic/README b/tonic/README index a5d0d4d..860f82f 100644 --- a/tonic/README +++ b/tonic/README @@ -114,22 +114,4 @@ Example of the same application as before, using juju errors: } -You can also easily serve auto-generated (using tonic data) swagger documentation: - - import ( - "fmt" - - "github.com/gin-gonic/gin" - "github.com/juju/errors" - "github.com/loopfz/gadgeto/tonic" - "github.com/loopfz/gadgeto/tonic/utils/jujerr" - "github.com/loopfz/gadgeto/tonic/utils/swag" - ) - - func main() { - tonic.SetErrorHook(jujerr.ErrHook) - r := gin.Default() - r.GET("/hello/:name", tonic.Handler(GreetUser, 200)) - r.GET("/swagger.json", swag.Swagger(r, "MyAPI", swag.Version("v1.0"), swag.BasePath("/foo/bar"))) - r.Run(":8080") - } +You can also easily serve auto-generated swagger documentation (using tonic data) with https://github.com/wi2l/fizz diff --git a/tonic/handler.go b/tonic/handler.go index 064c9a7..54be1d5 100644 --- a/tonic/handler.go +++ b/tonic/handler.go @@ -9,8 +9,8 @@ import ( "sync" "github.com/gin-gonic/gin" + validator "github.com/go-playground/validator/v10" "github.com/google/uuid" - validator "gopkg.in/go-playground/validator.v9" ) var ( diff --git a/tonic/listen.go b/tonic/listen.go index 7b4ad03..7af42d6 100644 --- a/tonic/listen.go +++ b/tonic/listen.go @@ -2,6 +2,7 @@ package tonic import ( "context" + "net" "net/http" "os" "os/signal" @@ -20,9 +21,12 @@ var defaultOpts = []ListenOptFunc{ func ListenAndServe(handler http.Handler, errorHandler func(error), opt ...ListenOptFunc) { + listener := struct { + net.Listener + }{} srv := &http.Server{Handler: handler} - listenOpt := &ListenOpt{Server: srv} + listenOpt := &ListenOpt{Listener: &listener, Server: srv} for _, o := range defaultOpts { err := o(listenOpt) @@ -48,11 +52,19 @@ func ListenAndServe(handler http.Handler, errorHandler func(error), opt ...Liste go func() { var err error - if srv.TLSConfig != nil && len(srv.TLSConfig.Certificates) > 0 { - // ListenAndServeTLS without cert files lets listenOpts set srv.TLSConfig.Certificates - err = srv.ListenAndServeTLS("", "") - } else { - err = srv.ListenAndServe() + var ln net.Listener + + ln, err = net.Listen("tcp", listenOpt.Server.Addr) + if err == nil { + // delayed listen, store it in the original listener object so any wrapping listener from listenOpt + // will have a correct reference + listener.Listener = ln + if srv.TLSConfig != nil && len(srv.TLSConfig.Certificates) > 0 { + // ServeTLS without cert files lets listenOpts set srv.TLSConfig.Certificates + err = listenOpt.Server.ServeTLS(listenOpt.Listener, "", "") + } else { + err = listenOpt.Server.Serve(listenOpt.Listener) + } } if err != nil && err != http.ErrServerClosed && errorHandler != nil { errorHandler(err) @@ -82,7 +94,10 @@ func ListenAndServe(handler http.Handler, errorHandler func(error), opt ...Liste } } +// ListenOpt exposes the Server object so you may change its configuration +// e.g. TLSConfig, and a Listener so that you may wrap it e.g. proxyprotocol type ListenOpt struct { + Listener net.Listener Server *http.Server Signals []os.Signal ShutdownTimeout time.Duration diff --git a/tonic/tonic.go b/tonic/tonic.go index 717dcc8..8bc9290 100644 --- a/tonic/tonic.go +++ b/tonic/tonic.go @@ -14,7 +14,7 @@ import ( "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" - validator "gopkg.in/go-playground/validator.v9" + validator "github.com/go-playground/validator/v10" ) // DefaultMaxBodyBytes is the maximum allowed size of a request body in bytes. diff --git a/tonic/utils/bootstrap/bootstrap.go b/tonic/utils/bootstrap/bootstrap.go deleted file mode 100644 index d19a991..0000000 --- a/tonic/utils/bootstrap/bootstrap.go +++ /dev/null @@ -1,57 +0,0 @@ -package bootstrap - -import ( - "net/http" - - "github.com/gin-gonic/gin" - "github.com/loopfz/gadgeto/tonic" -) - -// Bootstrap bootstraps tonic with gin engine. -// This must be called after ALL tonic-enabled handlers have been -// added to the gin engine. -// -// This retrieves the routes from gin engine and populates tonic handler -// with route information (method, path). -func Bootstrap(e *gin.Engine) { - defer tonic.SetExecHook(tonic.GetExecHook()) - - // Define an exec hook that populates our tonic handler - // with route information (method, path). - tonic.SetExecHook(func(c *gin.Context, _ gin.HandlerFunc, fname string) { - if r, ok := tonic.GetRoutes()[fname]; ok { - r.Path = c.Request.URL.Path - r.Method = c.Request.Method - } - }) - - // Call each route defined in gin - for _, r := range e.Routes() { - req, err := http.NewRequest(r.Method, r.Path, nil) - if err != nil { - panic(err) - } - e.ServeHTTP(newDummyResponseWriter(), req) - } -} - -// DummyResponseWriter is a dummy http.ResponseWriter implementation. -type DummyResponseWriter struct{} - -// Header makes DummyResponseWriter implement http.ResponseWriter. -func (d *DummyResponseWriter) Header() http.Header { - h := make(map[string][]string) - return h -} - -// Write makes DummyResponseWriter implement http.ResponseWriter. -func (d *DummyResponseWriter) Write([]byte) (int, error) { - return 0, nil -} - -// WriteHeader makes DummyResponseWriter implement http.ResponseWriter. -func (d *DummyResponseWriter) WriteHeader(int) {} - -func newDummyResponseWriter() *DummyResponseWriter { - return &DummyResponseWriter{} -} diff --git a/tonic/utils/eis/eis.go b/tonic/utils/eis/eis.go deleted file mode 100644 index 4ffefbe..0000000 --- a/tonic/utils/eis/eis.go +++ /dev/null @@ -1,29 +0,0 @@ -package eis - -import "github.com/gin-gonic/gin" - -var ( - enabler = func() {} -) - -// BEWARE: THIS IS _NOT_ CONCURRENT SAFE -// Make sure your calls to Freeze() and Melt() happen in the same goroutine - -// eis lets you setup gin middlewares -// and activate them later -// this is useful for weird init routines (e.g. swagger generation in tonic) - -func Freeze(h gin.HandlerFunc) gin.HandlerFunc { - f := noopMiddleware - currentEnabler := enabler - enabler = func() { currentEnabler(); f = h } - return func(c *gin.Context) { f(c) } -} - -func Melt() { - enabler() -} - -func noopMiddleware(c *gin.Context) { - c.Next() -} diff --git a/tonic/utils/listenproxyproto/listener.go b/tonic/utils/listenproxyproto/listener.go new file mode 100644 index 0000000..6d487f9 --- /dev/null +++ b/tonic/utils/listenproxyproto/listener.go @@ -0,0 +1,11 @@ +package listenproxyproto + +import ( + "github.com/loopfz/gadgeto/tonic" + "github.com/pires/go-proxyproto" +) + +func ListenProxyProtocol(o *tonic.ListenOpt) error { + o.Listener = &proxyproto.Listener{Listener: o.Listener} + return nil +} diff --git a/tonic/utils/swag/doc/doc.go b/tonic/utils/swag/doc/doc.go deleted file mode 100644 index e5959ca..0000000 --- a/tonic/utils/swag/doc/doc.go +++ /dev/null @@ -1,144 +0,0 @@ -package doc - -/* -This package uses "go/doc" to extract documentation for packages -Used by swagger to put comments on types, operation and determine which types are enums -*/ - -import ( - "go/ast" - "go/doc" - "go/parser" - "go/token" - "os" - "strings" -) - -type constantInfo struct { - ListC []string - Imprt string -} - -// Infos structure contains extrax -type Infos struct { - FunctionsDoc map[string]string - TypesDoc map[string]string - StructFieldsDoc map[string]map[string]string - Constants map[string]constantInfo -} - -// handy interface to loop untill self feeding generation is over -type stopper func() bool - -var gopath string - -func init() { - gopath = os.Getenv("GOPATH") -} - -func GenerateDoc(directory string) *Infos { - - docInfos := &Infos{ - FunctionsDoc: map[string]string{}, - TypesDoc: map[string]string{}, - Constants: map[string]constantInfo{}, - StructFieldsDoc: map[string]map[string]string{}, - } - - if gopath != "" && directory != "" { - var sourceDirs = map[string]bool{ - directory: false, - } - - var allDone stopper = func() bool { - for _, treated := range sourceDirs { - if !treated { - return false - } - } - return true - } - - for !allDone() { - for dir := range sourceDirs { - if sourceDirs[dir] { - continue - } - treatSourcedir(dir, docInfos, sourceDirs) - sourceDirs[dir] = true - } - } - } - - return docInfos -} - -func treatSourcedir(dir string, docInfos *Infos, sourceDirs map[string]bool) { - - fset := token.NewFileSet() - pkgs, err := parser.ParseDir(fset, dir, nil, parser.ParseComments) - if err != nil { - panic(err) - } - for _, pkg := range pkgs { - importpath := dir + "/" + pkg.Name - d := doc.New(pkg, importpath, doc.AllDecls) - for _, imp := range d.Imports { - if !sourceDirs[imp] { - if _, err := os.Stat(gopath + "/src/" + imp); err == nil { - sourceDirs[imp] = true - // if you want to load all docs from all packages, you can uncomment next line - // then maybe we would need to prefix everything with pkg - sourceDirs[gopath+"/src/"+imp] = false - } - } - } - - for _, astFunc := range d.Funcs { - docInfos.FunctionsDoc[pkg.Name+"."+astFunc.Name] = strings.Replace(astFunc.Doc, "\n", ". ", -1) - } - for _, astTypes := range d.Types { - - a := astTypes.Decl - for _, tspec := range a.Specs { - switch tspec.(type) { - case *ast.TypeSpec: - - switch tspec.(*ast.TypeSpec).Type.(type) { - case *ast.StructType: - ss := tspec.(*ast.TypeSpec).Type.(*ast.StructType) - for _, f := range ss.Fields.List { - name := "" - for _, i := range f.Names { - name += i.Name - } - if docInfos.StructFieldsDoc[astTypes.Name] == nil { - docInfos.StructFieldsDoc[astTypes.Name] = map[string]string{} - } - docInfos.StructFieldsDoc[astTypes.Name][name] = f.Doc.Text() - // could have picked f.Comment.Text() too - } - default: - continue - } - default: - continue - } - } - - docInfos.TypesDoc[astTypes.Name] = strings.Replace(astTypes.Doc, "\n", ". ", -1) - if len(astTypes.Consts) > 0 { - var c1 constantInfo - pkg := strings.Split(d.ImportPath, "/") - p := strings.Replace(d.ImportPath, "/"+pkg[len(pkg)-1], "", 1) - c1.Imprt = strings.Replace(p, gopath, "", 0) - for _, v := range astTypes.Consts { - c1.ListC = append(c1.ListC, v.Names...) - } - docInfos.Constants[d.Name+"."+astTypes.Name] = c1 - } - - } - } - -} diff --git a/tonic/utils/swag/doc/tonicdocgenerator/main.go b/tonic/utils/swag/doc/tonicdocgenerator/main.go deleted file mode 100644 index a6f20c3..0000000 --- a/tonic/utils/swag/doc/tonicdocgenerator/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "encoding/json" - "flag" - "fmt" - "strings" - - "github.com/loopfz/gadgeto/tonic/utils/swag/doc" -) - -/* - Run this script to generate swagger schema + sdks -*/ - -var directory = flag.String("directory", "", "root directory from which godoc will be generated") - -func main() { - flag.Parse() - - if directory == nil { - fmt.Println("Missing directory param") - return - } - - godoc := doc.GenerateDoc(*directory) - b, err := json.MarshalIndent(godoc, "", " ") - if err != nil { - panic(err) - } - godocStr := strings.Replace(string(b), "`", "'", -1) - fmt.Println(godocStr) - -} diff --git a/tonic/utils/swag/generator.go b/tonic/utils/swag/generator.go deleted file mode 100644 index aa85c89..0000000 --- a/tonic/utils/swag/generator.go +++ /dev/null @@ -1,472 +0,0 @@ -package swag - -import ( - "fmt" - "os" - "reflect" - "strings" - - "github.com/loopfz/gadgeto/tonic" - "github.com/loopfz/gadgeto/tonic/utils/swag/doc" - "github.com/loopfz/gadgeto/tonic/utils/swag/swagger" -) - -// GENERATOR - -// SchemaGenerator is the object users have to manipulate, it internally collects data about packages used by handlers -// and so on -type SchemaGenerator struct { - apiDeclaration *swagger.ApiDeclaration - - swaggedTypesMap map[reflect.Type]*swagger.Model - generatedTypes map[reflect.Type]string - - genesisDefer map[reflect.Type][]nameSetter - genesis map[reflect.Type]bool - - docInfos *doc.Infos -} - -// NewSchemaGenerator bootstraps a generator, don't instantiate SchemaGenerator yourself -func NewSchemaGenerator() *SchemaGenerator { - s := &SchemaGenerator{} - s.swaggedTypesMap = map[reflect.Type]*swagger.Model{} - s.generatedTypes = map[reflect.Type]string{} - s.genesisDefer = map[reflect.Type][]nameSetter{} - s.genesis = map[reflect.Type]bool{} - - return s -} - -// GenerateSwagDeclaration parses all routes (handlers, structs) and returns ready to serialize/use ApiDeclaration -func (s *SchemaGenerator) GenerateSwagDeclaration(routes map[string]*tonic.Route, basePath, version string, godoc *doc.Infos) error { - - s.docInfos = godoc - s.apiDeclaration = swagger.NewApiDeclaration(version, basePath) - - // create Operation for each route, creating models as we go - for _, route := range routes { - if err := s.addOperation(route); err != nil { - return err - } - } - - for t, list := range s.genesisDefer { - for _, ns := range list { - if ns == nil { - if reflect.Ptr != t.Kind() { - //fmt.Println("incomplete generator: missing defered setter somewhere. FYI type was: " + t.Name() + " / " + t.Kind().String()) - } - } else { - ns(s.generatedTypes[t]) - } - } - } - - return nil -} - -func (s *SchemaGenerator) generateModels(routes map[string]*tonic.Route) error { - for _, route := range routes { - s.generateSwagModel(route.InputType(), nil) - s.generateSwagModel(route.OutputType(), nil) - } - - return nil -} - -func (s *SchemaGenerator) addOperation(route *tonic.Route) error { - - op, err := s.generateOperation(route) - if err != nil { - return err - } - - path := cleanPath(route.GetPath()) - if _, ok := s.apiDeclaration.Paths[path]; !ok { - s.apiDeclaration.Paths[path] = make(map[string]swagger.Operation) - } - s.apiDeclaration.Paths[path][strings.ToLower(op.HttpMethod)] = *op - - return nil -} - -func (s *SchemaGenerator) generateOperation(route *tonic.Route) (*swagger.Operation, error) { - - in := route.InputType() - out := route.OutputType() - - desc := s.docInfos.FunctionsDoc[route.HandlerNameWithPackage()] - if desc == "" { - desc = route.GetDescription() - } - - op := swagger.NewOperation( - route.GetVerb(), - route.HandlerName(), - route.GetSummary(), - s.generateSwagModel(out, nil), - desc, - route.GetDeprecated(), - ) - - if err := s.setOperationParams(&op, in); err != nil { - return nil, err - } - if err := s.setOperationResponse(&op, out, route.GetDefaultStatusCode()); err != nil { - return nil, err - } - - op.Tags = route.GetTags() - - return &op, nil -} - -// sometimes recursive types can only be fully determined -// after full analysis, we use this interface to do so -type nameSetter func(string) - -// ################################### - -func (s *SchemaGenerator) setOperationResponse(op *swagger.Operation, t reflect.Type, retcode int) error { - - //Just give every method a 200 response for now - //This could be improved given for example 201 for post - //methods etc - schema := swagger.Schema{} - schemaType := s.generateSwagModel(t, nil) - if strings.Contains(schemaType, "#/") { - if t.Kind() == reflect.Slice { - schema.Type = "array" - if schema.Items == nil { - schema.Items = make(map[string]string) - } - schema.Items["$ref"] = schemaType - } else { - schema.Ref = schemaType - } - } else { - schema.Type = schemaType - } - - response := swagger.Response{} - if schema.Type != "void" { - //For void params swagger def can't be "void" - //No schema at all is fine - response.Schema = &schema - } - - op.Responses = map[string]swagger.Response{ - fmt.Sprintf("%d", retcode): response, - } - - return nil -} - -func (s *SchemaGenerator) setOperationParams(op *swagger.Operation, in reflect.Type) error { - - if in == nil || in.Kind() != reflect.Struct { - return nil - } - - var body *swagger.Model - - for i := 0; i < in.NumField(); i++ { - // Embedded field found, extract its fields - // as top-level parameters. - if in.Field(i).Anonymous { - // Recursively add fields of the embedded field - // to the operation params. - s.setOperationParams(op, in.Field(i).Type) - } else { - p := s.newParamFromStructField(in.Field(i), &body) - if p != nil { - if doc := s.docInfos.StructFieldsDoc[in.Name()]; doc != nil { - if fieldDoc := doc[in.Field(i).Name]; fieldDoc != "" { - p.Description = strings.TrimSuffix(fieldDoc, "\n") - } - } - op.AddParameter(*p) - } - } - } - if body != nil { - body.Id = "Input" + op.Nickname + "In" - s.apiDeclaration.AddModel(*body) - bodyParam := swagger.NewParameter("body", "body", "body request", true, false, "", "", "") - bodyParam.Schema.Ref = "#/definitions/" + body.Id - op.AddParameter(bodyParam) - } - - return nil - -} - -func (s *SchemaGenerator) newParamFromStructField(f reflect.StructField, bodyModel **swagger.Model) *swagger.Parameter { - - s.generateSwagModel(f.Type, nil) - - name := paramName(f) - paramType := paramType(f) - - if paramType == "body" { - if *bodyModel == nil { - m := swagger.NewModel("Input") - *bodyModel = &m - } - (*bodyModel).Properties[name] = s.fieldToModelProperty(f) - return nil - } - - _, allowMultiple := paramTargetTypeAllowMultiple(f) - format, dataType, refId := paramFormatDataTypeRefId(f) - - p := swagger.NewParameter( - paramType, - name, - paramDescription(f), - paramRequired(f), - allowMultiple, - dataType, - format, - refId, - ) - - if tag := f.Tag.Get(enumTag); tag != "" { - p.Enum = strings.Split(tag, ",") - } - p.Default = paramsDefault(f) - - // extra swagger specific tags. - p.CollectionFormat = f.Tag.Get("swagger-collection-format") - - return &p -} - -func (s *SchemaGenerator) generateSwagModel(t reflect.Type, ns nameSetter) string { - // nothing to generate - if t == nil { - s.generatedTypes[t] = "void" - return "void" - } - - //Check if we alredy seen this type - if finalName, ok := s.generatedTypes[t]; ok { - return finalName - } - - if s.genesis[t] { - if s.genesisDefer[t] == nil { - s.genesisDefer[t] = []nameSetter{ns} - } else { - s.genesisDefer[t] = append(s.genesisDefer[t], ns) - } - return "defered" - } - - s.genesis[t] = true - defer func() { s.genesis[t] = false }() - - if "Time" == t.Name() && t.PkgPath() == "time" { - s.generatedTypes[t] = "dateTime (sdk borken)" - return "dateTime (sdk borken)" //TODO: this is wrong, if a function has to return time we would need type + format - } - - // let's treat pointed type - if t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice || t.Kind() == reflect.Array { - return s.generateSwagModel(t.Elem(), ns) - } - - // we have either a simple type or a constant/aliased one - if t.Kind() != reflect.Struct { - if t.Kind().String() != t.Name() { - return t.Kind().String() - } - typeName, _, _ := swagger.GoTypeToSwagger(t) - s.generatedTypes[t] = typeName - return typeName - } - - modelName := swagger.ModelName(t) - if modelName == "" { // Bozo : I can't find the guilty type coming in, probably wosk.Null but ... - s.generatedTypes[t] = "void" - return "void" - } - - if _, ok := s.swaggedTypesMap[t]; ok { - s.generatedTypes[t] = modelName - return modelName - } - - m := swagger.NewModel(modelName) - if t.Kind() == reflect.Struct { - structFields := s.getStructFields(t, ns) - if len(structFields) > 0 { - for name, property := range structFields { - m.Properties[name] = property - } - s.apiDeclaration.AddModel(m) - } - } - - s.swaggedTypesMap[t] = &m - s.generatedTypes[t] = "#/definitions/" + m.Id - - return "#/definitions/" + m.Id -} - -func (s *SchemaGenerator) getStructFields(t reflect.Type, ns nameSetter) map[string]*swagger.ModelProperty { - structFields := make(map[string]*swagger.ModelProperty) - - for i := 0; i < t.NumField(); i++ { - if t.Field(i).Type.Kind() == reflect.Func { - //Ignore functions - continue - } - - name := getFieldName(t.Field(i)) - if name == nil { - continue - } - - if t.Field(i).Anonymous { - //For anonymous (embedded) fields, we flatten their structure, ie, we add the fields - //to the parent model. - typeToUse := t.Field(i).Type - if typeToUse.Kind() == reflect.Ptr { - typeToUse = t.Field(i).Type.Elem() - } - if typeToUse.Kind() == reflect.Struct { - dbModelFields := s.getStructFields(typeToUse, ns) - for fieldName, property := range dbModelFields { - structFields[fieldName] = property - } - } else { - s.generateSwagModel(t.Field(i).Type, ns) - property := s.fieldToModelProperty(t.Field(i)) - structFields[*name] = property - } - - } else { - // for fields that are not of simple types, we "program" generation - s.generateSwagModel(t.Field(i).Type, ns) - property := s.fieldToModelProperty(t.Field(i)) - structFields[*name] = property - } - - } - - return structFields -} - -func (s *SchemaGenerator) getNestedItemType(t reflect.Type, p *swagger.ModelProperty) *swagger.NestedItems { - arrayItems := &swagger.NestedItems{} - - if t.Kind() == reflect.Struct { - arrayItems.RefId = s.generateSwagModel(t, func(a string) { arrayItems.RefId = a }) - } else if t.Kind() == reflect.Map { - arrayItems.AdditionalProperties = s.getNestedItemType(t.Elem(), p) - arrayItems.Type = "object" - } else if t.Kind() == reflect.Slice || t.Kind() == reflect.Array { - arrayItems.Items = s.getNestedItemType(t.Elem(), p) - arrayItems.Type = "array" - } else { - arrayItems.Type = s.generateSwagModel(t, nil) - } - return arrayItems -} - -// Turns a field of a struct to a model property -func (s *SchemaGenerator) fieldToModelProperty(f reflect.StructField) *swagger.ModelProperty { - // TODO we should know whether struct is inbound or outbound - p := &swagger.ModelProperty{Required: true} - if f.Tag.Get("wosk") != "" { - if strings.Index(f.Tag.Get("wosk"), "required=false") != -1 { - p.Required = false - } - } - - if description := paramDescription(f); description != "" { - p.Description = description - } - - if tagValue := f.Tag.Get(swaggerTypeTag); tagValue != "" { - //Swagger type defined on the original struct, no need to infer it - //format is: swagger-type:type[,format] - tagTypes := strings.Split(tagValue, ",") - switch len(tagTypes) { - case 1: - p.Type = tagTypes[0] - case 2: - p.Type = tagTypes[0] - p.Format = tagTypes[1] - default: - panic(fmt.Sprintf("Error: bad %s definition on %s (%s)", swaggerTypeTag, f.Name, tagValue)) - } - } else { - - if f.Type.Kind() == reflect.Slice || f.Type.Kind() == reflect.Array { - p.Type = "array" - targetType := f.Type.Elem() - if targetType.Kind() == reflect.Ptr { - targetType = targetType.Elem() - } - if targetType.Kind() == reflect.Map { - p.Items = &swagger.NestedItems{} - nestedItem := s.getNestedItemType(targetType.Elem(), p) - p.Items.AdditionalProperties = nestedItem - p.Items.Type = "object" - - } else { - p.Items = s.getNestedItemType(targetType, p) - } - } else if f.Type.Kind() == reflect.Map { - if f.Type.Key().Kind() != reflect.String { - fmt.Fprintln(os.Stderr, "Type not supported, only map with string keys, got: ", f.Type.Key()) - } - p.Type = "object" - p.AdditionalProperties = &swagger.NestedItems{} - targetType := f.Type.Elem() - if targetType.Kind() == reflect.Ptr { - targetType = targetType.Elem() - } - typ := s.generateSwagModel(targetType, nil) - if targetType.Kind() == reflect.Struct { - p.AdditionalProperties.RefId = typ - } else if targetType.Kind() == reflect.Slice || targetType.Kind() == reflect.Array { - nestedItem := s.getNestedItemType(targetType.Elem(), p) - p.AdditionalProperties.Items = nestedItem - p.AdditionalProperties.Type = "array" - } else { - p.AdditionalProperties.Type = typ - } - - } else { - t := f.Type - if t.Kind() == reflect.Ptr { - t = t.Elem() - } - if "Time" == t.Name() && t.PkgPath() == "time" { - p.Type = "string" - p.Format = "dateTime" - } else if t.Kind() == reflect.Struct { - p.RefId = s.generateSwagModel(t, func(a string) { p.RefId = a }) - } else { // if it's a constant, maybe it's an enum - s.generateSwagModel(t, nil) - if list, ok := s.docInfos.Constants[t.String()]; ok { - values := []string{} - for _, co := range list.ListC { - // TODO this is WRONG ! - // TODO I only copy names of constants, we'd need to actually evaluate value - // I can only think of generating a script, go run it to get values :( - values = append(values, co) - } - p.Enum = values - p.Description = "WARNING: constants are constants names, they should be values (swagger generator incomplete)" - } - p.Type = s.generateSwagModel(t, func(n string) { p.Type = n }) - } - } - } - return p -} diff --git a/tonic/utils/swag/helpers.go b/tonic/utils/swag/helpers.go deleted file mode 100644 index 49d0874..0000000 --- a/tonic/utils/swag/helpers.go +++ /dev/null @@ -1,158 +0,0 @@ -package swag - -import ( - "fmt" - "reflect" - "regexp" - "strings" - - "github.com/loopfz/gadgeto/tonic" - "github.com/loopfz/gadgeto/tonic/utils/swag/swagger" -) - -const ( - queryTag = tonic.QueryTag - pathTag = tonic.PathTag - validateTag = tonic.ValidationTag - defaultTag = tonic.DefaultTag - enumTag = tonic.EnumTag - jsonTag = "json" - descriptionTag = "description" - swaggerTypeTag = "swagger-type" - requiredTag = tonic.RequiredTag -) - -func getFieldName(field reflect.StructField) *string { - name := paramName(field) - if name == "-" { - return nil - } - if name == "" { - return &field.Name - } - return &name -} - -func paramName(f reflect.StructField) string { - var tag string - qTag := f.Tag.Get(queryTag) - if qTag != "" { - tag = qTag - } - pTag := f.Tag.Get(pathTag) - if pTag != "" { - tag = pTag - } - jTag := f.Tag.Get(jsonTag) - if jTag != "" { - tag = jTag - } - var name string - parts := strings.Split(tag, ",") - if len(parts) > 0 { - name = parts[0] - } - if name == "" { - return f.Name - } - return name -} - -func paramDescription(f reflect.StructField) string { - return f.Tag.Get(descriptionTag) -} - -func paramRequired(f reflect.StructField) bool { - var tag string - qTag := f.Tag.Get(queryTag) - if qTag != "" { - tag = qTag - } - pTag := f.Tag.Get(pathTag) - if pTag != "" { - tag = pTag - } - vTag := f.Tag.Get(validateTag) - if vTag != "" { - tag = vTag - } - return strings.Index(tag, requiredTag) != -1 -} - -func paramType(f reflect.StructField) string { - qTag := f.Tag.Get(queryTag) - if qTag != "" { - return queryTag - } - pTag := f.Tag.Get(pathTag) - if pTag != "" { - return pathTag - } - return "body" -} - -func paramsDefault(f reflect.StructField) string { - var tag string - if dTag, ok := f.Tag.Lookup(defaultTag); ok { - return dTag - } - qTag := f.Tag.Get(queryTag) - if qTag != "" { - tag = qTag - } - pTag := f.Tag.Get(pathTag) - if pTag != "" { - tag = pTag - } - parts := strings.Split(tag, ",") - if len(parts) > 0 { - options := parts[1:] - for _, o := range options { - o = strings.TrimSpace(o) - if strings.HasPrefix(o, fmt.Sprintf("%s=", defaultTag)) { - o = strings.TrimPrefix(o, fmt.Sprintf("%s=", defaultTag)) - return o - } - } - } - return "" -} - -func paramTargetTypeAllowMultiple(f reflect.StructField) (reflect.Type, bool) { - targetType := f.Type - allowMultiple := false - if f.Type.Kind() == reflect.Slice || f.Type.Kind() == reflect.Array { - targetType = f.Type.Elem() - allowMultiple = true - } - return targetType, allowMultiple -} - -func paramFormatDataTypeRefId(f reflect.StructField) (string, string, string) { - var format, dataType, refId string - if f.Tag.Get(swaggerTypeTag) != "" { - //Swagger type defined on the original struct, no need to infer it - //format is: swagger-type:type[,format] - tagValue := f.Tag.Get(swaggerTypeTag) - tagTypes := strings.Split(tagValue, ",") - switch len(tagTypes) { - case 1: - dataType = tagTypes[0] - case 2: - dataType = tagTypes[0] - format = tagTypes[1] - default: - panic(fmt.Sprintf("Error: bad %s definition on %s (%s)", swaggerTypeTag, f.Name, tagValue)) - } - } else { - targetType, _ := paramTargetTypeAllowMultiple(f) - dataType, format, refId = swagger.GoTypeToSwagger(targetType) - } - return format, dataType, refId -} - -var ginPathParamRe = regexp.MustCompile(`\/:([^\/]*)`) - -func cleanPath(ginPath string) string { - return ginPathParamRe.ReplaceAllString(ginPath, "/{$1}") -} diff --git a/tonic/utils/swag/swagger/README.md b/tonic/utils/swag/swagger/README.md deleted file mode 100644 index e29dca3..0000000 --- a/tonic/utils/swag/swagger/README.md +++ /dev/null @@ -1,12 +0,0 @@ -swagger -======= - -Go package to export API doc for swagger-ui -Copied from https://github.com/proullon/swagger, we may do a pull request later -if we polish code - - -What is swagger ? -================= - -Check out [Swagger-ui](https://github.com/wordnik/swagger-ui) diff --git a/tonic/utils/swag/swagger/apideclaration.go b/tonic/utils/swag/swagger/apideclaration.go deleted file mode 100644 index ca4bc48..0000000 --- a/tonic/utils/swag/swagger/apideclaration.go +++ /dev/null @@ -1,67 +0,0 @@ -package swagger - -import ( - "encoding/json" -) - -type SwaggerApiInfo struct { - Title string `json:"title"` - Version string `json:"version"` - Description string `json:"description"` -} - -// ApiDeclaration is https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md#52-api-declaration -type ApiDeclaration struct { - SwaggerApiInfo SwaggerApiInfo `json:"info"` - Swagger string `json:"swagger"` - BasePath string `json:"basePath,omitempty"` - Paths map[string]map[string]Operation `json:"paths"` - Definitions map[string]Model `json:"definitions"` -} - -// NewApiDeclaration returns a bootstrapedApiDeclaration -func NewApiDeclaration(version string, basePath string) *ApiDeclaration { - - decl := &ApiDeclaration{} - - apiInfo := SwaggerApiInfo{} - apiInfo.Version = version - apiInfo.Title = "Swagger API" - decl.SwaggerApiInfo = apiInfo - - decl.Swagger = swaggerVersion - decl.BasePath = basePath - decl.Definitions = map[string]Model{} - decl.Paths = map[string]map[string]Operation{} - - return decl -} - -// AddModel does just what it says -func (decl *ApiDeclaration) AddModel(m Model) { - decl.Definitions[m.Id] = m -} - -//ToJSON is a shortcut to json.MarshalIndent -func (decl *ApiDeclaration) ToJSON() string { - b, _ := json.MarshalIndent(decl, "", " ") - return string(b) -} - -//GetSDKPaths filters out non relevant paths/operations for the SDKS -// at the moment just skips Operation marked as IsMonitoring -func (decl *ApiDeclaration) GetSDKPaths() map[string]map[string]Operation { - sdksPaths := make(map[string]map[string]Operation) - - for route, ops := range decl.Paths { - sdkOps := make(map[string]Operation) - for method, op := range ops { - if op.IsMonitoring { - continue - } - sdkOps[method] = op - } - sdksPaths[route] = sdkOps - } - return sdksPaths -} diff --git a/tonic/utils/swag/swagger/model.go b/tonic/utils/swag/swagger/model.go deleted file mode 100644 index 8e311ca..0000000 --- a/tonic/utils/swag/swagger/model.go +++ /dev/null @@ -1,39 +0,0 @@ -package swagger - -//Model is https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md#527-model-object -type Model struct { - Id string `json:"-"` - Description string `json:"description,omitempty"` - Required []string `json:"required,omitempty"` - Properties map[string]*ModelProperty `json:"properties"` -} - -// TODO Unify this struct and swagger.Schema in a common struct to accomodate model, params, response types -type NestedItems struct { - Type string `json:"type,omitempty"` - RefId string `json:"$ref,omitempty"` - Items *NestedItems `json:"items,omitempty"` - AdditionalProperties *NestedItems `json:"additionalProperties,omitempty"` -} - -// ModelProperty is https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md#528-properties-object -type ModelProperty struct { - Type string `json:"type,omitempty"` - RefId string `json:"$ref,omitempty"` - Format string `json:"format,omitempty"` - Description string `json:"description,omitempty"` - Items *NestedItems `json:"items,omitempty"` - AdditionalProperties *NestedItems `json:"additionalProperties,omitempty"` - Enum []string `json:"enum,omitempty"` - Required bool `json:"-"` - HideOnListing bool `json:"-"` //Hide this property on listing methods, activated with the swag omitinlisting -} - -//NewModel bootstraps a model ... -func NewModel(id string) Model { - m := Model{Id: id} - m.Required = []string{} - m.Properties = map[string]*ModelProperty{} - - return m -} diff --git a/tonic/utils/swag/swagger/operation.go b/tonic/utils/swag/swagger/operation.go deleted file mode 100644 index 8fa6b57..0000000 --- a/tonic/utils/swag/swagger/operation.go +++ /dev/null @@ -1,59 +0,0 @@ -package swagger - -type Schema struct { - Type string `json:"type,omitempty"` - Items map[string]string `json:"items,omitempty"` - Ref string `json:"$ref,omitempty"` -} - -type Response struct { - Description string `json:"description"` - Schema *Schema `json:"schema,omitempty"` -} - -type Operation struct { - HttpMethod string `json:"-"` - Nickname string `json:"-"` - Items map[string]string `json:"items,omitempty"` - Type string `json:"-"` - Summary string `json:"summary,omitempty"` - Description string `json:"description,omitempty"` - Parameters []Parameter `json:"parameters,omitempty"` - ResponseMessages []ResponseMessage `json:"responseMessages,omitempty"` // optional - Consumes []string `json:"consumes,omitempty"` - Produces []string `json:"produces,omitempty"` - Authorizations []Authorization `json:"authorizations,omitempty"` - Responses map[string]Response `json:"responses"` - Tags []string `json:"tags,omitempty"` - IsMonitoring bool `json:"-"` - Deprecated bool `json:"deprecated"` -} - -//NewOperation returns an op -func NewOperation(httpMethod, nickname, summary, typ, description string, deprecated bool) (op Operation) { - - op.HttpMethod = httpMethod - op.Nickname = nickname - op.Summary = summary - op.Description = description - op.Summary = summary - op.Deprecated = deprecated - op.Type = typ - if op.Type == "" { - op.Type = "void" - } - return -} - -//AddParameter adds a param to operation -func (op *Operation) AddParameter(param Parameter) { - - params := make([]Parameter, len(op.Parameters)+1) - - for i := range op.Parameters { - params[i] = op.Parameters[i] - } - params[len(op.Parameters)] = param - - op.Parameters = params -} diff --git a/tonic/utils/swag/swagger/parameter.go b/tonic/utils/swag/swagger/parameter.go deleted file mode 100644 index d67f527..0000000 --- a/tonic/utils/swag/swagger/parameter.go +++ /dev/null @@ -1,80 +0,0 @@ -package swagger - -import ( - "errors" - "reflect" -) - -type Parameter struct { - ParamType string `json:"in"` // path,query,body,header,form - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required"` - AllowMultiple bool `json:"-"` // then it's an array - - Type string `json:"type,omitempty"` // integer - Format string `json:"format,omitempty"` // int64 - Enum []string `json:"enum,omitempty"` - CollectionFormat string `json:"collectionFormat,omitempty"` // csv/ssv/tsv/pipe/multi, defaults to csv on swagger spec - RefId string `json:"$ref,omitempty"` - Minimum int `json:"minimum,omitempty"` - Maximum int `json:"maximum,omitempty"` - Default string `json:"default,omitempty"` - - Items map[string]string `json:"items,omitempty"` - Schema *Schema `json:"schema,omitempty"` -} - -func NewParameter(paramType string, name string, description string, required bool, allowMultiple bool, dataType, format, refId string) (param Parameter) { - - param.ParamType = paramType - param.Name = name - param.Description = description - param.Required = required - param.AllowMultiple = allowMultiple - param.Format = format - param.Type = dataType - param.RefId = refId - - if allowMultiple { - param.Type = "array" - param.Items = make(map[string]string) - param.Items["type"] = dataType - - if paramType == "query" { - param.CollectionFormat = "multi" - } - } - - if paramType == "body" { - schema := Schema{} - schema.Type = dataType - param.Schema = &schema - } - - return -} - -func (p Parameter) setTypeAndFormat(kind reflect.Kind) error { - switch kind { - case reflect.Int64: - p.Type = "integer" - p.Format = "int64" - return nil - case reflect.Int, reflect.Int32, reflect.Uint32: - p.Type = "integer" - p.Format = "int32" - return nil - case reflect.Float64: - p.Type = "number" - p.Format = "float" - return nil - case reflect.Bool: - p.Type = "boolean" - return nil - case reflect.String: - p.Type = "string" - return nil - } - return errors.New("unhandled type patch me") -} diff --git a/tonic/utils/swag/swagger/swagger.go b/tonic/utils/swag/swagger/swagger.go deleted file mode 100644 index b5a1dec..0000000 --- a/tonic/utils/swag/swagger/swagger.go +++ /dev/null @@ -1,63 +0,0 @@ -package swagger - -const swaggerVersion = "2.0" - -// ResourceListing is https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md#51-resource-listing -type ResourceListing struct { - ApiVersion string `json:"apiVersion"` - SwaggerVersion string `json:"swaggerVersion"` // e.g 1.2 -} - -//Swagger Path https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#pathItemObject -type Path struct { - Path string `json:"-"` - Operations map[string]Operation -} - -//Api is https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md#522-api-object -type Api struct { - Operations []Operation `json:"operations,omitempty"` - Models map[string]Model `json:"models,omitempty"` -} - -//ResponseMessage is https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md#525-response-message-object -type ResponseMessage struct { - Code int `json:"code"` - Message string `json:"message"` - ResponseModel string `json:"responseModel"` -} - -// Authorization is https://github.com/wordnik/swagger-core/wiki/authorizations -type Authorization struct { - LocalOAuth OAuth `json:"local-oauth"` - ApiKey ApiKey `json:"apiKey"` -} - -//OAuth is https://github.com/wordnik/swagger-core/wiki/authorizations -type OAuth struct { - Type string `json:"type"` // e.g. oauth2 - Scopes []string `json:"scopes"` // e.g. PUBLIC - GrantTypes map[string]GrantType `json:"grantTypes"` -} - -//GrantType is https://github.com/wordnik/swagger-core/wiki/authorizations -type GrantType struct { - LoginEndpoint Endpoint `json:"loginEndpoint"` - TokenName string `json:"tokenName"` // e.g. access_code - TokenRequestEndpoint Endpoint `json:"tokenRequestEndpoint"` - TokenEndpoint Endpoint `json:"tokenEndpoint"` -} - -//Endpoint is https://github.com/wordnik/swagger-core/wiki/authorizations -type Endpoint struct { - Url string `json:"url"` - ClientIdName string `json:"clientIdName"` - ClientSecretName string `json:"clientSecretName"` - TokenName string `json:"tokenName"` -} - -//ApiKey is https://github.com/wordnik/swagger-core/wiki/authorizations -type ApiKey struct { - Type string `json:"type"` // e.g. apiKey - PassAs string `json:"passAs"` // e.g. header -} diff --git a/tonic/utils/swag/swagger/type.go b/tonic/utils/swag/swagger/type.go deleted file mode 100644 index c66bbd7..0000000 --- a/tonic/utils/swag/swagger/type.go +++ /dev/null @@ -1,66 +0,0 @@ -package swagger - -import ( - "fmt" - "os" - "reflect" - "strings" - "unicode" - "unicode/utf8" -) - -// Transforms a go type to swagger type/format -// it is incomplete for now -func GoTypeToSwagger(t reflect.Type) (string, string, string) { - if t.Kind() == reflect.Ptr { - t = t.Elem() - } - if t.Kind() == reflect.Struct { - - if "Time" == t.Name() && t.PkgPath() == "time" { - return "string", "dateTime", "" - } - - return "", "", ModelName(t) - } - - switch t.Kind() { - case reflect.Int64, reflect.Uint64: - return "integer", "int64", "" - case reflect.Int, reflect.Int32, reflect.Uint32, reflect.Uint8, reflect.Uint16: - return "integer", "int32", "" - case reflect.Float64: - return "number", "float", "" - case reflect.Bool: - return "boolean", "", "" - case reflect.String: - return "string", "", "" - } - fmt.Fprintf(os.Stderr, "unhandled type: patch me -> %+v\n", t) - return "", "", "" -} - -func ModelName(t reflect.Type) string { - // ucFirst to make types public in go, could be handled another way - modelName := ucFirst(t.Name()) - - // we need to avoid collisions, but as we can't afford to break existing code when we detect one - // we'll always prefix types... - - pkg := "" - tmpSplit := strings.Split(t.PkgPath(), "/") - pkg = tmpSplit[len(tmpSplit)-1] - - if strings.ToLower(pkg) != strings.ToLower(modelName) && pkg != "handler" && strings.Index(strings.ToLower(modelName), strings.ToLower(pkg)) != 0 { - modelName = ucFirst(pkg) + modelName - } - return modelName -} - -func ucFirst(s string) string { - if s == "" { - return "" - } - r, n := utf8.DecodeRuneInString(strings.ToLower(s)) - return string(unicode.ToUpper(r)) + s[n:] -} diff --git a/tonic/utils/swag/tonic_swagger.go b/tonic/utils/swag/tonic_swagger.go deleted file mode 100644 index b7d7b2d..0000000 --- a/tonic/utils/swag/tonic_swagger.go +++ /dev/null @@ -1,52 +0,0 @@ -package swag - -import ( - "github.com/gin-gonic/gin" - "github.com/loopfz/gadgeto/tonic" - "github.com/loopfz/gadgeto/tonic/utils/bootstrap" - "github.com/loopfz/gadgeto/tonic/utils/swag/doc" - "github.com/loopfz/gadgeto/tonic/utils/swag/swagger" -) - -var ( - api *swagger.ApiDeclaration // singleton api declaration, generated once -) - -func Swagger(e *gin.Engine, title string, options ...func(*swagger.ApiDeclaration)) gin.HandlerFunc { - if api == nil { - bootstrap.Bootstrap(e) - - // generate Api Declaration - gen := NewSchemaGenerator() - if err := gen.GenerateSwagDeclaration(tonic.GetRoutes(), "", "", &doc.Infos{}); err != nil { - panic(err) - } - api = gen.apiDeclaration - - api.SwaggerApiInfo.Title = title - for _, opt := range options { - opt(api) - } - } - return func(c *gin.Context) { - c.JSON(200, api) - } -} - -func Version(version string) func(*swagger.ApiDeclaration) { - return func(a *swagger.ApiDeclaration) { - a.SwaggerApiInfo.Version = version - } -} - -func BasePath(path string) func(*swagger.ApiDeclaration) { - return func(a *swagger.ApiDeclaration) { - a.BasePath = path - } -} - -func Description(desc string) func(*swagger.ApiDeclaration) { - return func(a *swagger.ApiDeclaration) { - a.SwaggerApiInfo.Description = desc - } -}