[chore] Bump go swagger (#2871)
* bump go swagger version * bump swagger version
This commit is contained in:
parent
3a369d834a
commit
fd8a724e77
|
@ -80,7 +80,7 @@ steps:
|
||||||
- yarn --cwd ./web/source build
|
- yarn --cwd ./web/source build
|
||||||
|
|
||||||
- name: snapshot
|
- name: snapshot
|
||||||
image: superseriousbusiness/gotosocial-drone-build:0.5.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
|
image: superseriousbusiness/gotosocial-drone-build:0.6.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
|
||||||
volumes:
|
volumes:
|
||||||
- name: go-build-cache
|
- name: go-build-cache
|
||||||
path: /root/.cache/go-build
|
path: /root/.cache/go-build
|
||||||
|
@ -121,7 +121,7 @@ steps:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
- name: release
|
- name: release
|
||||||
image: superseriousbusiness/gotosocial-drone-build:0.5.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
|
image: superseriousbusiness/gotosocial-drone-build:0.6.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
|
||||||
volumes:
|
volumes:
|
||||||
- name: go-build-cache
|
- name: go-build-cache
|
||||||
path: /root/.cache/go-build
|
path: /root/.cache/go-build
|
||||||
|
@ -180,7 +180,7 @@ clone:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: mirror
|
- name: mirror
|
||||||
image: superseriousbusiness/gotosocial-drone-build:0.5.0
|
image: superseriousbusiness/gotosocial-drone-build:0.6.0
|
||||||
environment:
|
environment:
|
||||||
ORIGIN_REPO: https://github.com/superseriousbusiness/gotosocial
|
ORIGIN_REPO: https://github.com/superseriousbusiness/gotosocial
|
||||||
TARGET_REPO: https://codeberg.org/superseriousbusiness/gotosocial
|
TARGET_REPO: https://codeberg.org/superseriousbusiness/gotosocial
|
||||||
|
@ -193,6 +193,6 @@ steps:
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: signature
|
kind: signature
|
||||||
hmac: f7ef1e0d3d4fe0a55d43ba0ab5ed6cb5f5c8bf00791464ce7b251a3cdbfd954a
|
hmac: 643cd740e2b7bcb39d7093d34f04863b5907efb72f2db8912337389df4ad9f0f
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
40
go.mod
40
go.mod
|
@ -34,7 +34,7 @@ require (
|
||||||
github.com/gin-contrib/sessions v1.0.0
|
github.com/gin-contrib/sessions v1.0.0
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/go-playground/form/v4 v4.2.1
|
github.com/go-playground/form/v4 v4.2.1
|
||||||
github.com/go-swagger/go-swagger v0.30.5
|
github.com/go-swagger/go-swagger v0.30.6-0.20240418033037-c46c303aaa02
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/feeds v1.1.2
|
github.com/gorilla/feeds v1.1.2
|
||||||
github.com/gorilla/websocket v1.5.1
|
github.com/gorilla/websocket v1.5.1
|
||||||
|
@ -89,7 +89,7 @@ require (
|
||||||
codeberg.org/gruf/go-mangler v1.3.0 // indirect
|
codeberg.org/gruf/go-mangler v1.3.0 // indirect
|
||||||
codeberg.org/gruf/go-maps v1.0.3 // indirect
|
codeberg.org/gruf/go-maps v1.0.3 // indirect
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
|
@ -111,7 +111,7 @@ require (
|
||||||
github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d // indirect
|
github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d // indirect
|
||||||
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e // indirect
|
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
@ -120,17 +120,17 @@ require (
|
||||||
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
|
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
|
||||||
github.com/go-logr/logr v1.4.1 // indirect
|
github.com/go-logr/logr v1.4.1 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-openapi/analysis v0.21.4 // indirect
|
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||||
github.com/go-openapi/errors v0.20.4 // indirect
|
github.com/go-openapi/errors v0.22.0 // indirect
|
||||||
github.com/go-openapi/inflect v0.19.0 // indirect
|
github.com/go-openapi/inflect v0.21.0 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||||
github.com/go-openapi/loads v0.21.2 // indirect
|
github.com/go-openapi/loads v0.22.0 // indirect
|
||||||
github.com/go-openapi/runtime v0.26.0 // indirect
|
github.com/go-openapi/runtime v0.28.0 // indirect
|
||||||
github.com/go-openapi/spec v0.20.9 // indirect
|
github.com/go-openapi/spec v0.21.0 // indirect
|
||||||
github.com/go-openapi/strfmt v0.21.7 // indirect
|
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||||
github.com/go-openapi/swag v0.22.4 // indirect
|
github.com/go-openapi/swag v0.23.0 // indirect
|
||||||
github.com/go-openapi/validate v0.22.1 // indirect
|
github.com/go-openapi/validate v0.24.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.19.0 // indirect
|
github.com/go-playground/validator/v10 v10.19.0 // indirect
|
||||||
|
@ -141,14 +141,14 @@ require (
|
||||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
||||||
github.com/gorilla/context v1.1.2 // indirect
|
github.com/gorilla/context v1.1.2 // indirect
|
||||||
github.com/gorilla/css v1.0.0 // indirect
|
github.com/gorilla/css v1.0.0 // indirect
|
||||||
github.com/gorilla/handlers v1.5.1 // indirect
|
github.com/gorilla/handlers v1.5.2 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
github.com/gorilla/sessions v1.2.2 // indirect
|
github.com/gorilla/sessions v1.2.2 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/huandu/xstrings v1.3.3 // indirect
|
github.com/huandu/xstrings v1.4.0 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.16 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
|
@ -183,11 +183,11 @@ require (
|
||||||
github.com/prometheus/procfs v0.12.0 // indirect
|
github.com/prometheus/procfs v0.12.0 // indirect
|
||||||
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b // indirect
|
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||||
github.com/rs/xid v1.5.0 // indirect
|
github.com/rs/xid v1.5.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
github.com/shopspring/decimal v1.2.0 // indirect
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
github.com/spf13/afero v1.11.0 // indirect
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
|
@ -209,7 +209,7 @@ require (
|
||||||
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/arch v0.7.0 // indirect
|
golang.org/x/arch v0.7.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
|
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||||
golang.org/x/mod v0.16.0 // indirect
|
golang.org/x/mod v0.16.0 // indirect
|
||||||
golang.org/x/sync v0.6.0 // indirect
|
golang.org/x/sync v0.6.0 // indirect
|
||||||
golang.org/x/sys v0.19.0 // indirect
|
golang.org/x/sys v0.19.0 // indirect
|
||||||
|
|
189
go.sum
189
go.sum
|
@ -85,12 +85,11 @@ github.com/KimMachineGun/automemlimit v0.6.0 h1:p/BXkH+K40Hax+PuWWPQ478hPjsp9h1C
|
||||||
github.com/KimMachineGun/automemlimit v0.6.0/go.mod h1:T7xYht7B8r6AG/AqFcUdc7fzd2bIdBKmepfP2S1svPY=
|
github.com/KimMachineGun/automemlimit v0.6.0/go.mod h1:T7xYht7B8r6AG/AqFcUdc7fzd2bIdBKmepfP2S1svPY=
|
||||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
|
|
||||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||||
|
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||||
|
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
|
||||||
github.com/abema/go-mp4 v1.2.0 h1:gi4X8xg/m179N/J15Fn5ugywN9vtI6PLk6iLldHGLAk=
|
github.com/abema/go-mp4 v1.2.0 h1:gi4X8xg/m179N/J15Fn5ugywN9vtI6PLk6iLldHGLAk=
|
||||||
github.com/abema/go-mp4 v1.2.0/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws=
|
github.com/abema/go-mp4 v1.2.0/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws=
|
||||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||||
|
@ -98,7 +97,6 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY
|
||||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
|
||||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||||
|
@ -176,9 +174,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
@ -218,46 +215,28 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY=
|
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
|
||||||
github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc=
|
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
|
||||||
github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo=
|
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
|
||||||
github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
|
||||||
github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
github.com/go-openapi/inflect v0.21.0 h1:FoBjBTQEcbg2cJUWX6uwL9OyIW8eqc9k4KhN4lfbeYk=
|
||||||
github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
github.com/go-openapi/inflect v0.21.0/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw=
|
||||||
github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M=
|
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||||
github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk=
|
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||||
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
|
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||||
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
|
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
|
||||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
|
||||||
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
|
||||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
|
||||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
|
||||||
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
|
||||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
|
||||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
|
||||||
github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g=
|
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||||
github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro=
|
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||||
github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw=
|
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
|
||||||
github.com/go-openapi/runtime v0.26.0 h1:HYOFtG00FM1UvqrcxbEJg/SwvDRvYLQKGhw2zaQjTcc=
|
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
|
||||||
github.com/go-openapi/runtime v0.26.0/go.mod h1:QgRGeZwrUcSHdeh4Ka9Glvo0ug1LC5WyE+EV88plZrQ=
|
|
||||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
|
||||||
github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
|
||||||
github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
|
|
||||||
github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
|
||||||
github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg=
|
|
||||||
github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
|
|
||||||
github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg=
|
|
||||||
github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k=
|
|
||||||
github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew=
|
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
|
||||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
|
||||||
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
|
||||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
|
||||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
|
||||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
|
||||||
github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU=
|
|
||||||
github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
|
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
@ -270,39 +249,12 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91
|
||||||
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
|
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
|
||||||
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0=
|
github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-swagger/go-swagger v0.30.6-0.20240418033037-c46c303aaa02 h1:J6YiT/eg3gAfKMdVCkWXe6khsO+nxa8W4URZ4AUqzbA=
|
||||||
github.com/go-swagger/go-swagger v0.30.5 h1:SQ2+xSonWjjoEMOV5tcOnZJVlfyUfCBhGQGArS1b9+U=
|
github.com/go-swagger/go-swagger v0.30.6-0.20240418033037-c46c303aaa02/go.mod h1:i1/E+d8iPNReSE7y04FaVu5OPKB3il5cn+T1Egogg3I=
|
||||||
github.com/go-swagger/go-swagger v0.30.5/go.mod h1:cWUhSyCNqV7J1wkkxfr5QmbcnCewetCdvEXqgPvbc/Q=
|
|
||||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0=
|
|
||||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0=
|
|
||||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 h1:PSPmmucxGiFBtbQcttHTUc4LQ3P09AW+ldO2qspyKdY=
|
github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 h1:PSPmmucxGiFBtbQcttHTUc4LQ3P09AW+ldO2qspyKdY=
|
||||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
|
github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
|
||||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
|
||||||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
|
|
||||||
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
|
|
||||||
github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
|
||||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
|
||||||
github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
|
|
||||||
github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
|
||||||
github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
|
||||||
github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
|
|
||||||
github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
|
|
||||||
github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
|
|
||||||
github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
|
|
||||||
github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
|
|
||||||
github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
|
|
||||||
github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
|
|
||||||
github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
|
|
||||||
github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
|
|
||||||
github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
|
||||||
github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
|
||||||
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
|
||||||
github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
|
||||||
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
|
|
||||||
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
|
|
||||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
|
||||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
||||||
|
@ -342,7 +294,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
@ -352,7 +303,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||||
|
@ -386,8 +336,8 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||||
github.com/gorilla/feeds v1.1.2 h1:pxzZ5PD3RJdhFH2FsJJ4x6PqMqbgFk1+Vez4XWBW8Iw=
|
github.com/gorilla/feeds v1.1.2 h1:pxzZ5PD3RJdhFH2FsJJ4x6PqMqbgFk1+Vez4XWBW8Iw=
|
||||||
github.com/gorilla/feeds v1.1.2/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
|
github.com/gorilla/feeds v1.1.2/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
|
||||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
||||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
|
||||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||||
|
@ -406,15 +356,15 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
|
|
||||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
|
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||||
|
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||||
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
|
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
|
||||||
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
@ -430,7 +380,6 @@ github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LF
|
||||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
@ -440,12 +389,9 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||||
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
|
||||||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
|
||||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
@ -453,10 +399,7 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
@ -468,13 +411,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
|
||||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
|
||||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
|
||||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
@ -498,8 +436,6 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1
|
||||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||||
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
|
||||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
|
@ -510,12 +446,10 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
|
||||||
github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
|
github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
|
||||||
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
||||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
|
@ -530,12 +464,9 @@ github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGd
|
||||||
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
|
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
|
||||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
|
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
@ -556,12 +487,10 @@ github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b h1:aUNXCGgukb4gtY
|
||||||
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg=
|
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
|
||||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
@ -572,11 +501,9 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR
|
||||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
|
||||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
|
@ -590,16 +517,13 @@ github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNo
|
||||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
|
||||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
||||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
|
@ -691,11 +615,6 @@ github.com/wagslane/go-password-validator v0.3.0 h1:vfxOPzGHkz5S146HDpavl0cw1DSV
|
||||||
github.com/wagslane/go-password-validator v0.3.0/go.mod h1:TI1XJ6T5fRdRnHqHt14pvy1tNVnrwe7m3/f1f2fDphQ=
|
github.com/wagslane/go-password-validator v0.3.0/go.mod h1:TI1XJ6T5fRdRnHqHt14pvy1tNVnrwe7m3/f1f2fDphQ=
|
||||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
|
||||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
|
||||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
|
||||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
|
||||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||||
|
@ -704,7 +623,6 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
|
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
|
||||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
|
||||||
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
|
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
|
||||||
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
|
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
|
||||||
|
@ -718,9 +636,6 @@ github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U=
|
||||||
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.8-concurrency-workaround h1:ESobxED9bfE0nOQP/WPv9+tMR8oZoDIWRKlNK2Vs4Ms=
|
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.8-concurrency-workaround h1:ESobxED9bfE0nOQP/WPv9+tMR8oZoDIWRKlNK2Vs4Ms=
|
||||||
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.8-concurrency-workaround/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk=
|
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.8-concurrency-workaround/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk=
|
||||||
go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
|
|
||||||
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
|
|
||||||
go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
|
|
||||||
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
||||||
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
@ -757,16 +672,12 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
|
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
|
||||||
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
|
@ -780,8 +691,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
|
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
@ -838,8 +749,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
|
@ -856,27 +765,20 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/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-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/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -903,8 +805,6 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -924,8 +824,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
@ -940,13 +838,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
@ -1071,7 +965,6 @@ google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
@ -1091,9 +984,7 @@ 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 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
@ -5,12 +5,9 @@ linters:
|
||||||
disable-all: true
|
disable-all: true
|
||||||
enable:
|
enable:
|
||||||
- misspell
|
- misspell
|
||||||
- structcheck
|
|
||||||
- govet
|
- govet
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- deadcode
|
|
||||||
- errcheck
|
- errcheck
|
||||||
- varcheck
|
|
||||||
- unparam
|
- unparam
|
||||||
- ineffassign
|
- ineffassign
|
||||||
- nakedret
|
- nakedret
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
GOPATH=$(shell go env GOPATH)
|
GOPATH=$(shell go env GOPATH)
|
||||||
GOLANGCI_LINT=$(GOPATH)/bin/golangci-lint
|
GOLANGCI_LINT=$(GOPATH)/bin/golangci-lint
|
||||||
GOFUZZBUILD = $(GOPATH)/bin/go-fuzz-build
|
|
||||||
GOFUZZ = $(GOPATH)/bin/go-fuzz
|
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: $(GOLANGCI_LINT)
|
lint: $(GOLANGCI_LINT)
|
||||||
|
@ -19,19 +17,14 @@ test-cover:
|
||||||
GO111MODULE=on go test -cover .
|
GO111MODULE=on go test -cover .
|
||||||
|
|
||||||
.PHONY: fuzz
|
.PHONY: fuzz
|
||||||
fuzz: $(GOFUZZBUILD) $(GOFUZZ)
|
fuzz:
|
||||||
@echo "==> Fuzz testing"
|
@echo "==> Running Fuzz Tests"
|
||||||
$(GOFUZZBUILD)
|
go test -fuzz=FuzzNewVersion -fuzztime=15s .
|
||||||
$(GOFUZZ) -workdir=_fuzz
|
go test -fuzz=FuzzStrictNewVersion -fuzztime=15s .
|
||||||
|
go test -fuzz=FuzzNewConstraint -fuzztime=15s .
|
||||||
|
|
||||||
$(GOLANGCI_LINT):
|
$(GOLANGCI_LINT):
|
||||||
# Install golangci-lint. The configuration for it is in the .golangci.yml
|
# Install golangci-lint. The configuration for it is in the .golangci.yml
|
||||||
# file in the root of the repository
|
# file in the root of the repository
|
||||||
echo ${GOPATH}
|
echo ${GOPATH}
|
||||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.17.1
|
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.17.1
|
||||||
|
|
||||||
$(GOFUZZBUILD):
|
|
||||||
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz-build
|
|
||||||
|
|
||||||
$(GOFUZZ):
|
|
||||||
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-dep
|
|
|
@ -18,18 +18,20 @@ If you are looking for a command line tool for version comparisons please see
|
||||||
|
|
||||||
## Package Versions
|
## Package Versions
|
||||||
|
|
||||||
|
Note, import `github.com/github.com/Masterminds/semver/v3` to use the latest version.
|
||||||
|
|
||||||
There are three major versions fo the `semver` package.
|
There are three major versions fo the `semver` package.
|
||||||
|
|
||||||
* 3.x.x is the new stable and active version. This version is focused on constraint
|
* 3.x.x is the stable and active version. This version is focused on constraint
|
||||||
compatibility for range handling in other tools from other languages. It has
|
compatibility for range handling in other tools from other languages. It has
|
||||||
a similar API to the v1 releases. The development of this version is on the master
|
a similar API to the v1 releases. The development of this version is on the master
|
||||||
branch. The documentation for this version is below.
|
branch. The documentation for this version is below.
|
||||||
* 2.x was developed primarily for [dep](https://github.com/golang/dep). There are
|
* 2.x was developed primarily for [dep](https://github.com/golang/dep). There are
|
||||||
no tagged releases and the development was performed by [@sdboyer](https://github.com/sdboyer).
|
no tagged releases and the development was performed by [@sdboyer](https://github.com/sdboyer).
|
||||||
There are API breaking changes from v1. This version lives on the [2.x branch](https://github.com/Masterminds/semver/tree/2.x).
|
There are API breaking changes from v1. This version lives on the [2.x branch](https://github.com/Masterminds/semver/tree/2.x).
|
||||||
* 1.x.x is the most widely used version with numerous tagged releases. This is the
|
* 1.x.x is the original release. It is no longer maintained. You should use the
|
||||||
previous stable and is still maintained for bug fixes. The development, to fix
|
v3 release instead. You can read the documentation for the 1.x.x release
|
||||||
bugs, occurs on the release-1 branch. You can read the documentation [here](https://github.com/Masterminds/semver/blob/release-1/README.md).
|
[here](https://github.com/Masterminds/semver/blob/release-1/README.md).
|
||||||
|
|
||||||
## Parsing Semantic Versions
|
## Parsing Semantic Versions
|
||||||
|
|
||||||
|
@ -242,3 +244,15 @@ for _, m := range msgs {
|
||||||
|
|
||||||
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
|
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
|
||||||
or [create a pull request](https://github.com/Masterminds/semver/pulls).
|
or [create a pull request](https://github.com/Masterminds/semver/pulls).
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Security is an important consideration for this project. The project currently
|
||||||
|
uses the following tools to help discover security issues:
|
||||||
|
|
||||||
|
* [CodeQL](https://github.com/Masterminds/semver)
|
||||||
|
* [gosec](https://github.com/securego/gosec)
|
||||||
|
* Daily Fuzz testing
|
||||||
|
|
||||||
|
If you believe you have found a security vulnerability you can privately disclose
|
||||||
|
it through the [GitHub security page](https://github.com/Masterminds/semver/security).
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
The following versions of semver are currently supported:
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 3.x | :white_check_mark: |
|
||||||
|
| 2.x | :x: |
|
||||||
|
| 1.x | :x: |
|
||||||
|
|
||||||
|
Fixes are only released for the latest minor version in the form of a patch release.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
You can privately disclose a vulnerability through GitHubs
|
||||||
|
[private vulnerability reporting](https://github.com/Masterminds/semver/security/advisories)
|
||||||
|
mechanism.
|
|
@ -586,7 +586,7 @@ func rewriteRange(i string) string {
|
||||||
}
|
}
|
||||||
o := i
|
o := i
|
||||||
for _, v := range m {
|
for _, v := range m {
|
||||||
t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
|
t := fmt.Sprintf(">= %s, <= %s ", v[1], v[11])
|
||||||
o = strings.Replace(o, v[0], t, 1)
|
o = strings.Replace(o, v[0], t, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
// +build gofuzz
|
|
||||||
|
|
||||||
package semver
|
|
||||||
|
|
||||||
func Fuzz(data []byte) int {
|
|
||||||
d := string(data)
|
|
||||||
|
|
||||||
// Test NewVersion
|
|
||||||
_, _ = NewVersion(d)
|
|
||||||
|
|
||||||
// Test StrictNewVersion
|
|
||||||
_, _ = StrictNewVersion(d)
|
|
||||||
|
|
||||||
// Test NewConstraint
|
|
||||||
_, _ = NewConstraint(d)
|
|
||||||
|
|
||||||
// The return value should be 0 normally, 1 if the priority in future tests
|
|
||||||
// should be increased, and -1 if future tests should skip passing in that
|
|
||||||
// data. We do not have a reason to change priority so 0 is always returned.
|
|
||||||
// There are example tests that do this.
|
|
||||||
return 0
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.6
|
|
||||||
- 1.7
|
|
||||||
- 1.8
|
|
|
@ -1,7 +1,7 @@
|
||||||
.PHONY: ci generate clean
|
.PHONY: ci generate clean
|
||||||
|
|
||||||
ci: clean generate
|
ci: clean generate
|
||||||
go test -v ./...
|
go test -race -v ./...
|
||||||
|
|
||||||
generate:
|
generate:
|
||||||
go generate .
|
go generate .
|
||||||
|
|
|
@ -7,8 +7,8 @@ http.Handlers.
|
||||||
Doing this requires non-trivial wrapping of the http.ResponseWriter interface,
|
Doing this requires non-trivial wrapping of the http.ResponseWriter interface,
|
||||||
which is also exposed for users interested in a more low-level API.
|
which is also exposed for users interested in a more low-level API.
|
||||||
|
|
||||||
[![GoDoc](https://godoc.org/github.com/felixge/httpsnoop?status.svg)](https://godoc.org/github.com/felixge/httpsnoop)
|
[![Go Reference](https://pkg.go.dev/badge/github.com/felixge/httpsnoop.svg)](https://pkg.go.dev/github.com/felixge/httpsnoop)
|
||||||
[![Build Status](https://travis-ci.org/felixge/httpsnoop.svg?branch=master)](https://travis-ci.org/felixge/httpsnoop)
|
[![Build Status](https://github.com/felixge/httpsnoop/actions/workflows/main.yaml/badge.svg)](https://github.com/felixge/httpsnoop/actions/workflows/main.yaml)
|
||||||
|
|
||||||
## Usage Example
|
## Usage Example
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ func (m *Metrics) CaptureMetrics(w http.ResponseWriter, fn func(http.ResponseWri
|
||||||
return func(code int) {
|
return func(code int) {
|
||||||
next(code)
|
next(code)
|
||||||
|
|
||||||
if !headerWritten {
|
if !(code >= 100 && code <= 199) && !headerWritten {
|
||||||
m.Code = code
|
m.Code = code
|
||||||
headerWritten = true
|
headerWritten = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// +build go1.8
|
// +build go1.8
|
||||||
// Code generated by "httpsnoop/codegen"; DO NOT EDIT
|
// Code generated by "httpsnoop/codegen"; DO NOT EDIT.
|
||||||
|
|
||||||
package httpsnoop
|
package httpsnoop
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// +build !go1.8
|
// +build !go1.8
|
||||||
// Code generated by "httpsnoop/codegen"; DO NOT EDIT
|
// Code generated by "httpsnoop/codegen"; DO NOT EDIT.
|
||||||
|
|
||||||
package httpsnoop
|
package httpsnoop
|
||||||
|
|
||||||
|
|
|
@ -4,53 +4,58 @@ linters-settings:
|
||||||
golint:
|
golint:
|
||||||
min-confidence: 0
|
min-confidence: 0
|
||||||
gocyclo:
|
gocyclo:
|
||||||
min-complexity: 40
|
min-complexity: 45
|
||||||
gocognit:
|
|
||||||
min-complexity: 40
|
|
||||||
maligned:
|
maligned:
|
||||||
suggest-new: true
|
suggest-new: true
|
||||||
dupl:
|
dupl:
|
||||||
threshold: 150
|
threshold: 200
|
||||||
goconst:
|
goconst:
|
||||||
min-len: 2
|
min-len: 2
|
||||||
min-occurrences: 4
|
min-occurrences: 3
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
disable:
|
disable:
|
||||||
- maligned
|
- maligned
|
||||||
|
- unparam
|
||||||
- lll
|
- lll
|
||||||
- gochecknoglobals
|
|
||||||
- gochecknoinits
|
- gochecknoinits
|
||||||
# scopelint is useful, but also reports false positives
|
- gochecknoglobals
|
||||||
# that unfortunately can't be disabled. So we disable the
|
- funlen
|
||||||
# linter rather than changing code that works.
|
|
||||||
# see: https://github.com/kyoh86/scopelint/issues/4
|
|
||||||
- scopelint
|
|
||||||
- godox
|
- godox
|
||||||
- gocognit
|
- gocognit
|
||||||
#- whitespace
|
- whitespace
|
||||||
- wsl
|
- wsl
|
||||||
- funlen
|
|
||||||
- testpackage
|
|
||||||
- wrapcheck
|
- wrapcheck
|
||||||
#- nlreturn
|
- testpackage
|
||||||
|
- nlreturn
|
||||||
- gomnd
|
- gomnd
|
||||||
- goerr113
|
|
||||||
- exhaustivestruct
|
- exhaustivestruct
|
||||||
#- errorlint
|
- goerr113
|
||||||
#- nestif
|
- errorlint
|
||||||
- gofumpt
|
- nestif
|
||||||
- godot
|
- godot
|
||||||
- gci
|
- gofumpt
|
||||||
- dogsled
|
|
||||||
- paralleltest
|
- paralleltest
|
||||||
- tparallel
|
- tparallel
|
||||||
- thelper
|
- thelper
|
||||||
- ifshort
|
- ifshort
|
||||||
- forbidigo
|
|
||||||
- cyclop
|
|
||||||
- varnamelen
|
|
||||||
- exhaustruct
|
- exhaustruct
|
||||||
|
- varnamelen
|
||||||
|
- gci
|
||||||
|
- depguard
|
||||||
|
- errchkjson
|
||||||
|
- inamedparam
|
||||||
- nonamedreturns
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
|
- ireturn
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
# deprecated linters
|
||||||
|
- deadcode
|
||||||
|
- interfacer
|
||||||
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
- nosnakecase
|
- nosnakecase
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
# OpenAPI initiative analysis
|
# OpenAPI analysis [![Build Status](https://github.com/go-openapi/analysis/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/analysis/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/analysis/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/analysis)
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/go-openapi/analysis.svg?branch=master)](https://travis-ci.org/go-openapi/analysis)
|
|
||||||
[![Build status](https://ci.appveyor.com/api/projects/status/x377t5o9ennm847o/branch/master?svg=true)](https://ci.appveyor.com/project/casualjim/go-openapi/analysis/branch/master)
|
|
||||||
[![codecov](https://codecov.io/gh/go-openapi/analysis/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/analysis)
|
|
||||||
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
||||||
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/analysis/master/LICENSE)
|
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/analysis/master/LICENSE)
|
||||||
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/analysis.svg)](https://pkg.go.dev/github.com/go-openapi/analysis)
|
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/analysis.svg)](https://pkg.go.dev/github.com/go-openapi/analysis)
|
||||||
|
@ -13,12 +10,12 @@ A foundational library to analyze an OAI specification document for easier reaso
|
||||||
|
|
||||||
## What's inside?
|
## What's inside?
|
||||||
|
|
||||||
* A analyzer providing methods to walk the functional content of a specification
|
* An analyzer providing methods to walk the functional content of a specification
|
||||||
* A spec flattener producing a self-contained document bundle, while preserving `$ref`s
|
* A spec flattener producing a self-contained document bundle, while preserving `$ref`s
|
||||||
* A spec merger ("mixin") to merge several spec documents into a primary spec
|
* A spec merger ("mixin") to merge several spec documents into a primary spec
|
||||||
* A spec "fixer" ensuring that response descriptions are non empty
|
* A spec "fixer" ensuring that response descriptions are non empty
|
||||||
|
|
||||||
[Documentation](https://godoc.org/github.com/go-openapi/analysis)
|
[Documentation](https://pkg.go.dev/github.com/go-openapi/analysis)
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
|
@ -28,4 +25,3 @@ A foundational library to analyze an OAI specification document for easier reaso
|
||||||
> This package currently only supports OpenAPI 2.0 (aka Swagger 2.0).
|
> This package currently only supports OpenAPI 2.0 (aka Swagger 2.0).
|
||||||
> There is no plan to make it evolve toward supporting OpenAPI 3.x.
|
> There is no plan to make it evolve toward supporting OpenAPI 3.x.
|
||||||
> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story.
|
> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story.
|
||||||
>
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
version: "0.1.{build}"
|
|
||||||
|
|
||||||
clone_folder: C:\go-openapi\analysis
|
|
||||||
shallow_clone: true # for startup speed
|
|
||||||
pull_requests:
|
|
||||||
do_not_increment_build_number: true
|
|
||||||
|
|
||||||
#skip_tags: true
|
|
||||||
#skip_branch_with_pr: true
|
|
||||||
|
|
||||||
# appveyor.yml
|
|
||||||
build: off
|
|
||||||
|
|
||||||
environment:
|
|
||||||
GOPATH: c:\gopath
|
|
||||||
|
|
||||||
stack: go 1.16
|
|
||||||
|
|
||||||
test_script:
|
|
||||||
- go test -v -timeout 20m ./...
|
|
||||||
|
|
||||||
deploy: off
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
- provider: Slack
|
|
||||||
incoming_webhook: https://hooks.slack.com/services/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
|
|
||||||
auth_token:
|
|
||||||
secure: Sf7kZf7ZGbnwWUMpffHwMu5A0cHkLK2MYY32LNTPj4+/3qC3Ghl7+9v4TSLOqOlCwdRNjOGblAq7s+GDJed6/xgRQl1JtCi1klzZNrYX4q01pgTPvvGcwbBkIYgeMaPeIRcK9OZnud7sRXdttozgTOpytps2U6Js32ip7uj5mHSg2ub0FwoSJwlS6dbezZ8+eDhoha0F/guY99BEwx8Bd+zROrT2TFGsSGOFGN6wFc7moCqTHO/YkWib13a2QNXqOxCCVBy/lt76Wp+JkeFppjHlzs/2lP3EAk13RIUAaesdEUHvIHrzCyNJEd3/+KO2DzsWOYfpktd+KBCvgaYOsoo7ubdT3IROeAegZdCgo/6xgCEsmFc9ZcqCfN5yNx2A+BZ2Vwmpws+bQ1E1+B5HDzzaiLcYfG4X2O210QVGVDLWsv1jqD+uPYeHY2WRfh5ZsIUFvaqgUEnwHwrK44/8REAhQavt1QAj5uJpsRd7CkRVPWRNK+yIky+wgbVUFEchRNmS55E7QWf+W4+4QZkQi7vUTMc9nbTUu2Es9NfvfudOpM2wZbn98fjpb/qq/nRv6Bk+ca+7XD5/IgNLMbWp2ouDdzbiHLCOfDUiHiDJhLfFZx9Bwo7ZwfzeOlbrQX66bx7xRKYmOe4DLrXhNcpbsMa8qbfxlZRCmYbubB/Y8h4=
|
|
||||||
channel: bots
|
|
||||||
on_build_success: false
|
|
||||||
on_build_failure: true
|
|
||||||
on_build_status_changed: true
|
|
|
@ -16,27 +16,27 @@
|
||||||
Package analysis provides methods to work with a Swagger specification document from
|
Package analysis provides methods to work with a Swagger specification document from
|
||||||
package go-openapi/spec.
|
package go-openapi/spec.
|
||||||
|
|
||||||
Analyzing a specification
|
## Analyzing a specification
|
||||||
|
|
||||||
An analysed specification object (type Spec) provides methods to work with swagger definition.
|
An analysed specification object (type Spec) provides methods to work with swagger definition.
|
||||||
|
|
||||||
Flattening or expanding a specification
|
## Flattening or expanding a specification
|
||||||
|
|
||||||
Flattening a specification bundles all remote $ref in the main spec document.
|
Flattening a specification bundles all remote $ref in the main spec document.
|
||||||
Depending on flattening options, additional preprocessing may take place:
|
Depending on flattening options, additional preprocessing may take place:
|
||||||
- full flattening: replacing all inline complex constructs by a named entry in #/definitions
|
- full flattening: replacing all inline complex constructs by a named entry in #/definitions
|
||||||
- expand: replace all $ref's in the document by their expanded content
|
- expand: replace all $ref's in the document by their expanded content
|
||||||
|
|
||||||
Merging several specifications
|
## Merging several specifications
|
||||||
|
|
||||||
Mixin several specifications merges all Swagger constructs, and warns about found conflicts.
|
Mixin several specifications merges all Swagger constructs, and warns about found conflicts.
|
||||||
|
|
||||||
Fixing a specification
|
## Fixing a specification
|
||||||
|
|
||||||
Unmarshalling a specification with golang json unmarshalling may lead to
|
Unmarshalling a specification with golang json unmarshalling may lead to
|
||||||
some unwanted result on present but empty fields.
|
some unwanted result on present but empty fields.
|
||||||
|
|
||||||
Analyzing a Swagger schema
|
## Analyzing a Swagger schema
|
||||||
|
|
||||||
Swagger schemas are analyzed to determine their complexity and qualify their content.
|
Swagger schemas are analyzed to determine their complexity and qualify their content.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -62,28 +62,26 @@ func newContext() *context {
|
||||||
//
|
//
|
||||||
// There is a minimal and a full flattening mode.
|
// There is a minimal and a full flattening mode.
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// Minimally flattening a spec means:
|
// Minimally flattening a spec means:
|
||||||
// - Expanding parameters, responses, path items, parameter items and header items (references to schemas are left
|
// - Expanding parameters, responses, path items, parameter items and header items (references to schemas are left
|
||||||
// unscathed)
|
// unscathed)
|
||||||
// - Importing external (http, file) references so they become internal to the document
|
// - Importing external (http, file) references so they become internal to the document
|
||||||
// - Moving every JSON pointer to a $ref to a named definition (i.e. the reworked spec does not contain pointers
|
// - Moving every JSON pointer to a $ref to a named definition (i.e. the reworked spec does not contain pointers
|
||||||
// like "$ref": "#/definitions/myObject/allOfs/1")
|
// like "$ref": "#/definitions/myObject/allOfs/1")
|
||||||
//
|
//
|
||||||
// A minimally flattened spec thus guarantees the following properties:
|
// A minimally flattened spec thus guarantees the following properties:
|
||||||
// - all $refs point to a local definition (i.e. '#/definitions/...')
|
// - all $refs point to a local definition (i.e. '#/definitions/...')
|
||||||
// - definitions are unique
|
// - definitions are unique
|
||||||
//
|
//
|
||||||
// NOTE: arbitrary JSON pointers (other than $refs to top level definitions) are rewritten as definitions if they
|
// NOTE: arbitrary JSON pointers (other than $refs to top level definitions) are rewritten as definitions if they
|
||||||
// represent a complex schema or express commonality in the spec.
|
// represent a complex schema or express commonality in the spec.
|
||||||
// Otherwise, they are simply expanded.
|
// Otherwise, they are simply expanded.
|
||||||
// Self-referencing JSON pointers cannot resolve to a type and trigger an error.
|
// Self-referencing JSON pointers cannot resolve to a type and trigger an error.
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// Minimal flattening is necessary and sufficient for codegen rendering using go-swagger.
|
// Minimal flattening is necessary and sufficient for codegen rendering using go-swagger.
|
||||||
//
|
//
|
||||||
// Fully flattening a spec means:
|
// Fully flattening a spec means:
|
||||||
// - Moving every complex inline schema to be a definition with an auto-generated name in a depth-first fashion.
|
// - Moving every complex inline schema to be a definition with an auto-generated name in a depth-first fashion.
|
||||||
//
|
//
|
||||||
// By complex, we mean every JSON object with some properties.
|
// By complex, we mean every JSON object with some properties.
|
||||||
// Arrays, when they do not define a tuple,
|
// Arrays, when they do not define a tuple,
|
||||||
|
@ -93,22 +91,21 @@ func newContext() *context {
|
||||||
// have been created.
|
// have been created.
|
||||||
//
|
//
|
||||||
// Available flattening options:
|
// Available flattening options:
|
||||||
// - Minimal: stops flattening after minimal $ref processing, leaving schema constructs untouched
|
// - Minimal: stops flattening after minimal $ref processing, leaving schema constructs untouched
|
||||||
// - Expand: expand all $ref's in the document (inoperant if Minimal set to true)
|
// - Expand: expand all $ref's in the document (inoperant if Minimal set to true)
|
||||||
// - Verbose: croaks about name conflicts detected
|
// - Verbose: croaks about name conflicts detected
|
||||||
// - RemoveUnused: removes unused parameters, responses and definitions after expansion/flattening
|
// - RemoveUnused: removes unused parameters, responses and definitions after expansion/flattening
|
||||||
//
|
//
|
||||||
// NOTE: expansion removes all $ref save circular $ref, which remain in place
|
// NOTE: expansion removes all $ref save circular $ref, which remain in place
|
||||||
//
|
//
|
||||||
// TODO: additional options
|
// TODO: additional options
|
||||||
// - ProgagateNameExtensions: ensure that created entries properly follow naming rules when their parent have set a
|
// - ProgagateNameExtensions: ensure that created entries properly follow naming rules when their parent have set a
|
||||||
// x-go-name extension
|
// x-go-name extension
|
||||||
// - LiftAllOfs:
|
// - LiftAllOfs:
|
||||||
// - limit the flattening of allOf members when simple objects
|
// - limit the flattening of allOf members when simple objects
|
||||||
// - merge allOf with validation only
|
// - merge allOf with validation only
|
||||||
// - merge allOf with extensions only
|
// - merge allOf with extensions only
|
||||||
// - ...
|
// - ...
|
||||||
//
|
|
||||||
func Flatten(opts FlattenOpts) error {
|
func Flatten(opts FlattenOpts) error {
|
||||||
debugLog("FlattenOpts: %#v", opts)
|
debugLog("FlattenOpts: %#v", opts)
|
||||||
|
|
||||||
|
@ -270,6 +267,12 @@ func nameInlinedSchemas(opts *FlattenOpts) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeUnused(opts *FlattenOpts) {
|
func removeUnused(opts *FlattenOpts) {
|
||||||
|
for removeUnusedSinglePass(opts) {
|
||||||
|
// continue until no unused definition remains
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeUnusedSinglePass(opts *FlattenOpts) (hasRemoved bool) {
|
||||||
expected := make(map[string]struct{})
|
expected := make(map[string]struct{})
|
||||||
for k := range opts.Swagger().Definitions {
|
for k := range opts.Swagger().Definitions {
|
||||||
expected[path.Join(definitionsPath, jsonpointer.Escape(k))] = struct{}{}
|
expected[path.Join(definitionsPath, jsonpointer.Escape(k))] = struct{}{}
|
||||||
|
@ -280,6 +283,7 @@ func removeUnused(opts *FlattenOpts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range expected {
|
for k := range expected {
|
||||||
|
hasRemoved = true
|
||||||
debugLog("removing unused definition %s", path.Base(k))
|
debugLog("removing unused definition %s", path.Base(k))
|
||||||
if opts.Verbose {
|
if opts.Verbose {
|
||||||
log.Printf("info: removing unused definition: %s", path.Base(k))
|
log.Printf("info: removing unused definition: %s", path.Base(k))
|
||||||
|
@ -288,6 +292,8 @@ func removeUnused(opts *FlattenOpts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.Spec.reload() // re-analyze
|
opts.Spec.reload() // re-analyze
|
||||||
|
|
||||||
|
return hasRemoved
|
||||||
}
|
}
|
||||||
|
|
||||||
func importKnownRef(entry sortref.RefRevIdx, refStr, newName string, opts *FlattenOpts) error {
|
func importKnownRef(entry sortref.RefRevIdx, refStr, newName string, opts *FlattenOpts) error {
|
||||||
|
@ -334,7 +340,7 @@ func importNewRef(entry sortref.RefRevIdx, refStr string, opts *FlattenOpts) err
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a unique name - isOAIGen means that a naming conflict was resolved by changing the name
|
// generate a unique name - isOAIGen means that a naming conflict was resolved by changing the name
|
||||||
newName, isOAIGen = uniqifyName(opts.Swagger().Definitions, nameFromRef(entry.Ref))
|
newName, isOAIGen = uniqifyName(opts.Swagger().Definitions, nameFromRef(entry.Ref, opts))
|
||||||
debugLog("new name for [%s]: %s - with name conflict:%t", strings.Join(entry.Keys, ", "), newName, isOAIGen)
|
debugLog("new name for [%s]: %s - with name conflict:%t", strings.Join(entry.Keys, ", "), newName, isOAIGen)
|
||||||
|
|
||||||
opts.flattenContext.resolved[refStr] = newName
|
opts.flattenContext.resolved[refStr] = newName
|
||||||
|
@ -488,9 +494,9 @@ func stripPointersAndOAIGen(opts *FlattenOpts) error {
|
||||||
// stripOAIGen strips the spec from unnecessary OAIGen constructs, initially created to dedupe flattened definitions.
|
// stripOAIGen strips the spec from unnecessary OAIGen constructs, initially created to dedupe flattened definitions.
|
||||||
//
|
//
|
||||||
// A dedupe is deemed unnecessary whenever:
|
// A dedupe is deemed unnecessary whenever:
|
||||||
// - the only conflict is with its (single) parent: OAIGen is merged into its parent (reinlining)
|
// - the only conflict is with its (single) parent: OAIGen is merged into its parent (reinlining)
|
||||||
// - there is a conflict with multiple parents: merge OAIGen in first parent, the rewrite other parents to point to
|
// - there is a conflict with multiple parents: merge OAIGen in first parent, the rewrite other parents to point to
|
||||||
// the first parent.
|
// the first parent.
|
||||||
//
|
//
|
||||||
// This function returns true whenever it re-inlined a complex schema, so the caller may chose to iterate
|
// This function returns true whenever it re-inlined a complex schema, so the caller may chose to iterate
|
||||||
// pointer and name resolution again.
|
// pointer and name resolution again.
|
||||||
|
@ -652,6 +658,7 @@ func namePointers(opts *FlattenOpts) error {
|
||||||
|
|
||||||
refsToReplace := make(map[string]SchemaRef, len(opts.Spec.references.schemas))
|
refsToReplace := make(map[string]SchemaRef, len(opts.Spec.references.schemas))
|
||||||
for k, ref := range opts.Spec.references.allRefs {
|
for k, ref := range opts.Spec.references.allRefs {
|
||||||
|
debugLog("name pointers: %q => %#v", k, ref)
|
||||||
if path.Dir(ref.String()) == definitionsPath {
|
if path.Dir(ref.String()) == definitionsPath {
|
||||||
// this a ref to a top-level definition: ok
|
// this a ref to a top-level definition: ok
|
||||||
continue
|
continue
|
||||||
|
@ -769,6 +776,10 @@ func flattenAnonPointer(key string, v SchemaRef, refsToReplace map[string]Schema
|
||||||
|
|
||||||
// identifying edge case when the namer did nothing because we point to a non-schema object
|
// identifying edge case when the namer did nothing because we point to a non-schema object
|
||||||
// no definition is created and we expand the $ref for all callers
|
// no definition is created and we expand the $ref for all callers
|
||||||
|
debugLog("decide what to do with the schema pointed to: asch.IsSimpleSchema=%t, len(callers)=%d, parts.IsSharedParam=%t, parts.IsSharedResponse=%t",
|
||||||
|
asch.IsSimpleSchema, len(callers), parts.IsSharedParam(), parts.IsSharedResponse(),
|
||||||
|
)
|
||||||
|
|
||||||
if (!asch.IsSimpleSchema || len(callers) > 1) && !parts.IsSharedParam() && !parts.IsSharedResponse() {
|
if (!asch.IsSimpleSchema || len(callers) > 1) && !parts.IsSharedParam() && !parts.IsSharedResponse() {
|
||||||
debugLog("replace JSON pointer at [%s] by definition: %s", key, v.Ref.String())
|
debugLog("replace JSON pointer at [%s] by definition: %s", key, v.Ref.String())
|
||||||
if err := namer.Name(v.Ref.String(), v.Schema, asch); err != nil {
|
if err := namer.Name(v.Ref.String(), v.Schema, asch); err != nil {
|
||||||
|
@ -791,6 +802,7 @@ func flattenAnonPointer(key string, v SchemaRef, refsToReplace map[string]Schema
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// everything that is a simple schema and not factorizable is expanded
|
||||||
debugLog("expand JSON pointer for key=%s", key)
|
debugLog("expand JSON pointer for key=%s", key)
|
||||||
|
|
||||||
if err := replace.UpdateRefWithSchema(opts.Swagger(), key, v.Schema); err != nil {
|
if err := replace.UpdateRefWithSchema(opts.Swagger(), key, v.Schema); err != nil {
|
||||||
|
|
|
@ -33,12 +33,14 @@ func (isn *InlineSchemaNamer) Name(key string, schema *spec.Schema, aschema *Ana
|
||||||
}
|
}
|
||||||
|
|
||||||
// create unique name
|
// create unique name
|
||||||
newName, isOAIGen := uniqifyName(isn.Spec.Definitions, swag.ToJSONName(name))
|
mangle := mangler(isn.opts)
|
||||||
|
newName, isOAIGen := uniqifyName(isn.Spec.Definitions, mangle(name))
|
||||||
|
|
||||||
// clone schema
|
// clone schema
|
||||||
sch := schutils.Clone(schema)
|
sch := schutils.Clone(schema)
|
||||||
|
|
||||||
// replace values on schema
|
// replace values on schema
|
||||||
|
debugLog("rewriting schema to ref: key=%s with new name: %s", key, newName)
|
||||||
if err := replace.RewriteSchemaToRef(isn.Spec, key,
|
if err := replace.RewriteSchemaToRef(isn.Spec, key,
|
||||||
spec.MustCreateRef(path.Join(definitionsPath, newName))); err != nil {
|
spec.MustCreateRef(path.Join(definitionsPath, newName))); err != nil {
|
||||||
return fmt.Errorf("error while creating definition %q from inline schema: %w", newName, err)
|
return fmt.Errorf("error while creating definition %q from inline schema: %w", newName, err)
|
||||||
|
@ -149,13 +151,15 @@ func namesFromKey(parts sortref.SplitKey, aschema *AnalyzedSchema, operations ma
|
||||||
startIndex int
|
startIndex int
|
||||||
)
|
)
|
||||||
|
|
||||||
if parts.IsOperation() {
|
switch {
|
||||||
|
case parts.IsOperation():
|
||||||
baseNames, startIndex = namesForOperation(parts, operations)
|
baseNames, startIndex = namesForOperation(parts, operations)
|
||||||
}
|
case parts.IsDefinition():
|
||||||
|
|
||||||
// definitions
|
|
||||||
if parts.IsDefinition() {
|
|
||||||
baseNames, startIndex = namesForDefinition(parts)
|
baseNames, startIndex = namesForDefinition(parts)
|
||||||
|
default:
|
||||||
|
// this a non-standard pointer: build a name by concatenating its parts
|
||||||
|
baseNames = [][]string{parts}
|
||||||
|
startIndex = len(baseNames) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]string, 0, len(baseNames))
|
result := make([]string, 0, len(baseNames))
|
||||||
|
@ -169,6 +173,7 @@ func namesFromKey(parts sortref.SplitKey, aschema *AnalyzedSchema, operations ma
|
||||||
}
|
}
|
||||||
sort.Strings(result)
|
sort.Strings(result)
|
||||||
|
|
||||||
|
debugLog("names from parts: %v => %v", parts, result)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,10 +261,20 @@ func partAdder(aschema *AnalyzedSchema) sortref.PartAdder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nameFromRef(ref spec.Ref) string {
|
func mangler(o *FlattenOpts) func(string) string {
|
||||||
|
if o.KeepNames {
|
||||||
|
return func(in string) string { return in }
|
||||||
|
}
|
||||||
|
|
||||||
|
return swag.ToJSONName
|
||||||
|
}
|
||||||
|
|
||||||
|
func nameFromRef(ref spec.Ref, o *FlattenOpts) string {
|
||||||
|
mangle := mangler(o)
|
||||||
|
|
||||||
u := ref.GetURL()
|
u := ref.GetURL()
|
||||||
if u.Fragment != "" {
|
if u.Fragment != "" {
|
||||||
return swag.ToJSONName(path.Base(u.Fragment))
|
return mangle(path.Base(u.Fragment))
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.Path != "" {
|
if u.Path != "" {
|
||||||
|
@ -267,19 +282,19 @@ func nameFromRef(ref spec.Ref) string {
|
||||||
if bn != "" && bn != "/" {
|
if bn != "" && bn != "/" {
|
||||||
ext := path.Ext(bn)
|
ext := path.Ext(bn)
|
||||||
if ext != "" {
|
if ext != "" {
|
||||||
return swag.ToJSONName(bn[:len(bn)-len(ext)])
|
return mangle(bn[:len(bn)-len(ext)])
|
||||||
}
|
}
|
||||||
|
|
||||||
return swag.ToJSONName(bn)
|
return mangle(bn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return swag.ToJSONName(strings.ReplaceAll(u.Host, ".", " "))
|
return mangle(strings.ReplaceAll(u.Host, ".", " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenLocation indicates from which section of the specification (models or operations) a definition has been created.
|
// GenLocation indicates from which section of the specification (models or operations) a definition has been created.
|
||||||
//
|
//
|
||||||
// This is reflected in the output spec with a "x-go-gen-location" extension. At the moment, this is is provided
|
// This is reflected in the output spec with a "x-go-gen-location" extension. At the moment, this is provided
|
||||||
// for information only.
|
// for information only.
|
||||||
func GenLocation(parts sortref.SplitKey) string {
|
func GenLocation(parts sortref.SplitKey) string {
|
||||||
switch {
|
switch {
|
||||||
|
|
|
@ -26,6 +26,7 @@ type FlattenOpts struct {
|
||||||
Verbose bool // enable some reporting on possible name conflicts detected
|
Verbose bool // enable some reporting on possible name conflicts detected
|
||||||
RemoveUnused bool // When true, remove unused parameters, responses and definitions after expansion/flattening
|
RemoveUnused bool // When true, remove unused parameters, responses and definitions after expansion/flattening
|
||||||
ContinueOnError bool // Continue when spec expansion issues are found
|
ContinueOnError bool // Continue when spec expansion issues are found
|
||||||
|
KeepNames bool // Do not attempt to jsonify names from references when flattening
|
||||||
|
|
||||||
/* Extra keys */
|
/* Extra keys */
|
||||||
_ struct{} // require keys
|
_ struct{} // require keys
|
||||||
|
|
|
@ -29,7 +29,7 @@ var (
|
||||||
// GetLogger provides a prefix debug logger
|
// GetLogger provides a prefix debug logger
|
||||||
func GetLogger(prefix string, debug bool) func(string, ...interface{}) {
|
func GetLogger(prefix string, debug bool) func(string, ...interface{}) {
|
||||||
if debug {
|
if debug {
|
||||||
logger := log.New(output, fmt.Sprintf("%s:", prefix), log.LstdFlags)
|
logger := log.New(output, prefix+":", log.LstdFlags)
|
||||||
|
|
||||||
return func(msg string, args ...interface{}) {
|
return func(msg string, args ...interface{}) {
|
||||||
_, file1, pos1, _ := runtime.Caller(1)
|
_, file1, pos1, _ := runtime.Caller(1)
|
||||||
|
@ -37,5 +37,5 @@ func GetLogger(prefix string, debug bool) func(string, ...interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(msg string, args ...interface{}) {}
|
return func(_ string, _ ...interface{}) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package replace
|
package replace
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
@ -40,6 +41,8 @@ func RewriteSchemaToRef(sp *spec.Swagger, key string, ref spec.Ref) error {
|
||||||
if refable.Schema != nil {
|
if refable.Schema != nil {
|
||||||
refable.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
|
refable.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
|
||||||
}
|
}
|
||||||
|
case map[string]interface{}: // this happens e.g. if a schema points to an extension unmarshaled as map[string]interface{}
|
||||||
|
return rewriteParentRef(sp, key, ref)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("no schema with ref found at %s for %T", key, value)
|
return fmt.Errorf("no schema with ref found at %s for %T", key, value)
|
||||||
}
|
}
|
||||||
|
@ -120,6 +123,9 @@ func rewriteParentRef(sp *spec.Swagger, key string, ref spec.Ref) error {
|
||||||
case spec.SchemaProperties:
|
case spec.SchemaProperties:
|
||||||
container[entry] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
|
container[entry] = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
|
||||||
|
|
||||||
|
case *interface{}:
|
||||||
|
*container = spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}}
|
||||||
|
|
||||||
// NOTE: can't have case *spec.SchemaOrBool = parent in this case is *Schema
|
// NOTE: can't have case *spec.SchemaOrBool = parent in this case is *Schema
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -318,8 +324,8 @@ type DeepestRefResult struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepestRef finds the first definition ref, from a cascade of nested refs which are not definitions.
|
// DeepestRef finds the first definition ref, from a cascade of nested refs which are not definitions.
|
||||||
// - if no definition is found, returns the deepest ref.
|
// - if no definition is found, returns the deepest ref.
|
||||||
// - pointers to external files are expanded
|
// - pointers to external files are expanded
|
||||||
//
|
//
|
||||||
// NOTE: all external $ref's are assumed to be already expanded at this stage.
|
// NOTE: all external $ref's are assumed to be already expanded at this stage.
|
||||||
func DeepestRef(sp *spec.Swagger, opts *spec.ExpandOptions, ref spec.Ref) (*DeepestRefResult, error) {
|
func DeepestRef(sp *spec.Swagger, opts *spec.ExpandOptions, ref spec.Ref) (*DeepestRefResult, error) {
|
||||||
|
@ -385,8 +391,9 @@ DOWNREF:
|
||||||
err := asSchema.UnmarshalJSON(asJSON)
|
err := asSchema.UnmarshalJSON(asJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil,
|
return nil,
|
||||||
fmt.Errorf("invalid type for resolved JSON pointer %s. Expected a schema a, got: %T",
|
fmt.Errorf("invalid type for resolved JSON pointer %s. Expected a schema a, got: %T (%v)",
|
||||||
currentRef.String(), value)
|
currentRef.String(), value, err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
warnings = append(warnings, fmt.Sprintf("found $ref %q (response) interpreted as schema", currentRef.String()))
|
warnings = append(warnings, fmt.Sprintf("found $ref %q (response) interpreted as schema", currentRef.String()))
|
||||||
|
|
||||||
|
@ -402,8 +409,9 @@ DOWNREF:
|
||||||
var asSchema spec.Schema
|
var asSchema spec.Schema
|
||||||
if err := asSchema.UnmarshalJSON(asJSON); err != nil {
|
if err := asSchema.UnmarshalJSON(asJSON); err != nil {
|
||||||
return nil,
|
return nil,
|
||||||
fmt.Errorf("invalid type for resolved JSON pointer %s. Expected a schema a, got: %T",
|
fmt.Errorf("invalid type for resolved JSON pointer %s. Expected a schema a, got: %T (%v)",
|
||||||
currentRef.String(), value)
|
currentRef.String(), value, err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
warnings = append(warnings, fmt.Sprintf("found $ref %q (parameter) interpreted as schema", currentRef.String()))
|
warnings = append(warnings, fmt.Sprintf("found $ref %q (parameter) interpreted as schema", currentRef.String()))
|
||||||
|
@ -414,9 +422,25 @@ DOWNREF:
|
||||||
currentRef = asSchema.Ref
|
currentRef = asSchema.Ref
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil,
|
// fallback: attempts to resolve the pointer as a schema
|
||||||
fmt.Errorf("unhandled type to resolve JSON pointer %s. Expected a Schema, got: %T",
|
if refable == nil {
|
||||||
currentRef.String(), value)
|
break DOWNREF
|
||||||
|
}
|
||||||
|
|
||||||
|
asJSON, _ := json.Marshal(refable)
|
||||||
|
var asSchema spec.Schema
|
||||||
|
if err := asSchema.UnmarshalJSON(asJSON); err != nil {
|
||||||
|
return nil,
|
||||||
|
fmt.Errorf("unhandled type to resolve JSON pointer %s. Expected a Schema, got: %T (%v)",
|
||||||
|
currentRef.String(), value, err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
warnings = append(warnings, fmt.Sprintf("found $ref %q (%T) interpreted as schema", currentRef.String(), refable))
|
||||||
|
|
||||||
|
if asSchema.Ref.String() == "" {
|
||||||
|
break DOWNREF
|
||||||
|
}
|
||||||
|
currentRef = asSchema.Ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ func KeyParts(key string) SplitKey {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// SplitKey holds of the parts of a /-separated key, soi that their location may be determined.
|
// SplitKey holds of the parts of a /-separated key, so that their location may be determined.
|
||||||
type SplitKey []string
|
type SplitKey []string
|
||||||
|
|
||||||
// IsDefinition is true when the split key is in the #/definitions section of a spec
|
// IsDefinition is true when the split key is in the #/definitions section of a spec
|
||||||
|
|
|
@ -53,7 +53,7 @@ import (
|
||||||
// collisions.
|
// collisions.
|
||||||
func Mixin(primary *spec.Swagger, mixins ...*spec.Swagger) []string {
|
func Mixin(primary *spec.Swagger, mixins ...*spec.Swagger) []string {
|
||||||
skipped := make([]string, 0, len(mixins))
|
skipped := make([]string, 0, len(mixins))
|
||||||
opIds := getOpIds(primary)
|
opIDs := getOpIDs(primary)
|
||||||
initPrimary(primary)
|
initPrimary(primary)
|
||||||
|
|
||||||
for i, m := range mixins {
|
for i, m := range mixins {
|
||||||
|
@ -74,7 +74,7 @@ func Mixin(primary *spec.Swagger, mixins ...*spec.Swagger) []string {
|
||||||
skipped = append(skipped, mergeDefinitions(primary, m)...)
|
skipped = append(skipped, mergeDefinitions(primary, m)...)
|
||||||
|
|
||||||
// merging paths requires a map of operationIDs to work with
|
// merging paths requires a map of operationIDs to work with
|
||||||
skipped = append(skipped, mergePaths(primary, m, opIds, i)...)
|
skipped = append(skipped, mergePaths(primary, m, opIDs, i)...)
|
||||||
|
|
||||||
skipped = append(skipped, mergeParameters(primary, m)...)
|
skipped = append(skipped, mergeParameters(primary, m)...)
|
||||||
|
|
||||||
|
@ -84,9 +84,9 @@ func Mixin(primary *spec.Swagger, mixins ...*spec.Swagger) []string {
|
||||||
return skipped
|
return skipped
|
||||||
}
|
}
|
||||||
|
|
||||||
// getOpIds extracts all the paths.<path>.operationIds from the given
|
// getOpIDs extracts all the paths.<path>.operationIds from the given
|
||||||
// spec and returns them as the keys in a map with 'true' values.
|
// spec and returns them as the keys in a map with 'true' values.
|
||||||
func getOpIds(s *spec.Swagger) map[string]bool {
|
func getOpIDs(s *spec.Swagger) map[string]bool {
|
||||||
rv := make(map[string]bool)
|
rv := make(map[string]bool)
|
||||||
if s.Paths == nil {
|
if s.Paths == nil {
|
||||||
return rv
|
return rv
|
||||||
|
@ -179,7 +179,7 @@ func mergeDefinitions(primary *spec.Swagger, m *spec.Swagger) (skipped []string)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func mergePaths(primary *spec.Swagger, m *spec.Swagger, opIds map[string]bool, mixIndex int) (skipped []string) {
|
func mergePaths(primary *spec.Swagger, m *spec.Swagger, opIDs map[string]bool, mixIndex int) (skipped []string) {
|
||||||
if m.Paths != nil {
|
if m.Paths != nil {
|
||||||
for k, v := range m.Paths.Paths {
|
for k, v := range m.Paths.Paths {
|
||||||
if _, exists := primary.Paths.Paths[k]; exists {
|
if _, exists := primary.Paths.Paths[k]; exists {
|
||||||
|
@ -198,10 +198,10 @@ func mergePaths(primary *spec.Swagger, m *spec.Swagger, opIds map[string]bool, m
|
||||||
// all the proivded specs are already unique.
|
// all the proivded specs are already unique.
|
||||||
piops := pathItemOps(v)
|
piops := pathItemOps(v)
|
||||||
for _, piop := range piops {
|
for _, piop := range piops {
|
||||||
if opIds[piop.ID] {
|
if opIDs[piop.ID] {
|
||||||
piop.ID = fmt.Sprintf("%v%v%v", piop.ID, "Mixin", mixIndex)
|
piop.ID = fmt.Sprintf("%v%v%v", piop.ID, "Mixin", mixIndex)
|
||||||
}
|
}
|
||||||
opIds[piop.ID] = true
|
opIDs[piop.ID] = true
|
||||||
}
|
}
|
||||||
primary.Paths.Paths[k] = v
|
primary.Paths.Paths[k] = v
|
||||||
}
|
}
|
||||||
|
@ -367,7 +367,7 @@ func mergeSwaggerProps(primary *spec.Swagger, m *spec.Swagger) []string {
|
||||||
return skipped
|
return skipped
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: unparam
|
//nolint:unparam
|
||||||
func mergeExternalDocs(primary *spec.ExternalDocumentation, m *spec.ExternalDocumentation) []string {
|
func mergeExternalDocs(primary *spec.ExternalDocumentation, m *spec.ExternalDocumentation) []string {
|
||||||
if primary.Description == "" {
|
if primary.Description == "" {
|
||||||
primary.Description = m.Description
|
primary.Description = m.Description
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package analysis
|
package analysis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
|
|
||||||
"github.com/go-openapi/spec"
|
"github.com/go-openapi/spec"
|
||||||
"github.com/go-openapi/strfmt"
|
"github.com/go-openapi/strfmt"
|
||||||
|
@ -19,7 +19,7 @@ type SchemaOpts struct {
|
||||||
// patterns.
|
// patterns.
|
||||||
func Schema(opts SchemaOpts) (*AnalyzedSchema, error) {
|
func Schema(opts SchemaOpts) (*AnalyzedSchema, error) {
|
||||||
if opts.Schema == nil {
|
if opts.Schema == nil {
|
||||||
return nil, fmt.Errorf("no schema to analyze")
|
return nil, errors.New("no schema to analyze")
|
||||||
}
|
}
|
||||||
|
|
||||||
a := &AnalyzedSchema{
|
a := &AnalyzedSchema{
|
||||||
|
@ -247,10 +247,10 @@ func (a *AnalyzedSchema) isArrayType() bool {
|
||||||
// isAnalyzedAsComplex determines if an analyzed schema is eligible to flattening (i.e. it is "complex").
|
// isAnalyzedAsComplex determines if an analyzed schema is eligible to flattening (i.e. it is "complex").
|
||||||
//
|
//
|
||||||
// Complex means the schema is any of:
|
// Complex means the schema is any of:
|
||||||
// - a simple type (primitive)
|
// - a simple type (primitive)
|
||||||
// - an array of something (items are possibly complex ; if this is the case, items will generate a definition)
|
// - an array of something (items are possibly complex ; if this is the case, items will generate a definition)
|
||||||
// - a map of something (additionalProperties are possibly complex ; if this is the case, additionalProperties will
|
// - a map of something (additionalProperties are possibly complex ; if this is the case, additionalProperties will
|
||||||
// generate a definition)
|
// generate a definition)
|
||||||
func (a *AnalyzedSchema) isAnalyzedAsComplex() bool {
|
func (a *AnalyzedSchema) isAnalyzedAsComplex() bool {
|
||||||
return !a.IsSimpleSchema && !a.IsArray && !a.IsMap
|
return !a.IsSimpleSchema && !a.IsArray && !a.IsMap
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,45 +4,59 @@ linters-settings:
|
||||||
golint:
|
golint:
|
||||||
min-confidence: 0
|
min-confidence: 0
|
||||||
gocyclo:
|
gocyclo:
|
||||||
min-complexity: 30
|
min-complexity: 45
|
||||||
maligned:
|
maligned:
|
||||||
suggest-new: true
|
suggest-new: true
|
||||||
dupl:
|
dupl:
|
||||||
threshold: 100
|
threshold: 200
|
||||||
goconst:
|
goconst:
|
||||||
min-len: 2
|
min-len: 2
|
||||||
min-occurrences: 4
|
min-occurrences: 3
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
disable:
|
disable:
|
||||||
|
- errname # this repo doesn't follow the convention advised by this linter
|
||||||
- maligned
|
- maligned
|
||||||
|
- unparam
|
||||||
- lll
|
- lll
|
||||||
|
- gochecknoinits
|
||||||
- gochecknoglobals
|
- gochecknoglobals
|
||||||
|
- funlen
|
||||||
- godox
|
- godox
|
||||||
- gocognit
|
- gocognit
|
||||||
- whitespace
|
- whitespace
|
||||||
- wsl
|
- wsl
|
||||||
- funlen
|
|
||||||
- gochecknoglobals
|
|
||||||
- gochecknoinits
|
|
||||||
- scopelint
|
|
||||||
- wrapcheck
|
- wrapcheck
|
||||||
- exhaustivestruct
|
|
||||||
- exhaustive
|
|
||||||
- nlreturn
|
|
||||||
- testpackage
|
- testpackage
|
||||||
- gci
|
- nlreturn
|
||||||
- gofumpt
|
|
||||||
- goerr113
|
|
||||||
- gomnd
|
- gomnd
|
||||||
- tparallel
|
- exhaustivestruct
|
||||||
|
- goerr113
|
||||||
|
- errorlint
|
||||||
- nestif
|
- nestif
|
||||||
- godot
|
- godot
|
||||||
- errorlint
|
- gofumpt
|
||||||
- paralleltest
|
- paralleltest
|
||||||
- tparallel
|
- tparallel
|
||||||
- cyclop
|
- thelper
|
||||||
- errname
|
- ifshort
|
||||||
- varnamelen
|
|
||||||
- exhaustruct
|
- exhaustruct
|
||||||
- maintidx
|
- varnamelen
|
||||||
|
- gci
|
||||||
|
- depguard
|
||||||
|
- errchkjson
|
||||||
|
- inamedparam
|
||||||
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
|
- ireturn
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
# deprecated linters
|
||||||
|
- deadcode
|
||||||
|
- interfacer
|
||||||
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
|
- nosnakecase
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
# OpenAPI errors
|
# OpenAPI errors [![Build Status](https://github.com/go-openapi/errors/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/errors/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/errors)
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/go-openapi/errors.svg?branch=master)](https://travis-ci.org/go-openapi/errors)
|
|
||||||
[![codecov](https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/errors)
|
|
||||||
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
||||||
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/errors/master/LICENSE)
|
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/errors/master/LICENSE)
|
||||||
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/errors.svg)](https://pkg.go.dev/github.com/go-openapi/errors)
|
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/errors.svg)](https://pkg.go.dev/github.com/go-openapi/errors)
|
||||||
[![GolangCI](https://golangci.com/badges/github.com/go-openapi/errors.svg)](https://golangci.com)
|
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/errors)](https://goreportcard.com/report/github.com/go-openapi/errors)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/errors)](https://goreportcard.com/report/github.com/go-openapi/errors)
|
||||||
|
|
||||||
Shared errors and error interface used throughout the various libraries found in the go-openapi toolkit.
|
Shared errors and error interface used throughout the various libraries found in the go-openapi toolkit.
|
||||||
|
|
|
@ -55,9 +55,15 @@ func (a apiError) MarshalJSON() ([]byte, error) {
|
||||||
// New creates a new API error with a code and a message
|
// New creates a new API error with a code and a message
|
||||||
func New(code int32, message string, args ...interface{}) Error {
|
func New(code int32, message string, args ...interface{}) Error {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
return &apiError{code, fmt.Sprintf(message, args...)}
|
return &apiError{
|
||||||
|
code: code,
|
||||||
|
message: fmt.Sprintf(message, args...),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &apiError{
|
||||||
|
code: code,
|
||||||
|
message: message,
|
||||||
}
|
}
|
||||||
return &apiError{code, message}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotFound creates a new not found error
|
// NotFound creates a new not found error
|
||||||
|
@ -130,10 +136,14 @@ func flattenComposite(errs *CompositeError) *CompositeError {
|
||||||
// MethodNotAllowed creates a new method not allowed error
|
// MethodNotAllowed creates a new method not allowed error
|
||||||
func MethodNotAllowed(requested string, allow []string) Error {
|
func MethodNotAllowed(requested string, allow []string) Error {
|
||||||
msg := fmt.Sprintf("method %s is not allowed, but [%s] are", requested, strings.Join(allow, ","))
|
msg := fmt.Sprintf("method %s is not allowed, but [%s] are", requested, strings.Join(allow, ","))
|
||||||
return &MethodNotAllowedError{code: http.StatusMethodNotAllowed, Allowed: allow, message: msg}
|
return &MethodNotAllowedError{
|
||||||
|
code: http.StatusMethodNotAllowed,
|
||||||
|
Allowed: allow,
|
||||||
|
message: msg,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeError the error handler interface implementation
|
// ServeError implements the http error handler interface
|
||||||
func ServeError(rw http.ResponseWriter, r *http.Request, err error) {
|
func ServeError(rw http.ResponseWriter, r *http.Request, err error) {
|
||||||
rw.Header().Set("Content-Type", "application/json")
|
rw.Header().Set("Content-Type", "application/json")
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
|
|
|
@ -120,6 +120,10 @@ func (c *CompositeError) Error() string {
|
||||||
return c.message
|
return c.message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CompositeError) Unwrap() []error {
|
||||||
|
return c.Errors
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalJSON implements the JSON encoding interface
|
// MarshalJSON implements the JSON encoding interface
|
||||||
func (c CompositeError) MarshalJSON() ([]byte, error) {
|
func (c CompositeError) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(map[string]interface{}{
|
return json.Marshal(map[string]interface{}{
|
||||||
|
@ -133,7 +137,7 @@ func (c CompositeError) MarshalJSON() ([]byte, error) {
|
||||||
func CompositeValidationError(errors ...error) *CompositeError {
|
func CompositeValidationError(errors ...error) *CompositeError {
|
||||||
return &CompositeError{
|
return &CompositeError{
|
||||||
code: CompositeErrorCode,
|
code: CompositeErrorCode,
|
||||||
Errors: append([]error{}, errors...),
|
Errors: append(make([]error, 0, len(errors)), errors...),
|
||||||
message: "validation failure list",
|
message: "validation failure list",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
secrets.yml
|
||||||
|
coverage.out
|
||||||
|
coverage.txt
|
||||||
|
*.cov
|
||||||
|
.idea
|
|
@ -0,0 +1,61 @@
|
||||||
|
linters-settings:
|
||||||
|
govet:
|
||||||
|
check-shadowing: true
|
||||||
|
golint:
|
||||||
|
min-confidence: 0
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 45
|
||||||
|
maligned:
|
||||||
|
suggest-new: true
|
||||||
|
dupl:
|
||||||
|
threshold: 200
|
||||||
|
goconst:
|
||||||
|
min-len: 2
|
||||||
|
min-occurrences: 3
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable-all: true
|
||||||
|
disable:
|
||||||
|
- maligned
|
||||||
|
- unparam
|
||||||
|
- lll
|
||||||
|
- gochecknoinits
|
||||||
|
- gochecknoglobals
|
||||||
|
- funlen
|
||||||
|
- godox
|
||||||
|
- gocognit
|
||||||
|
- whitespace
|
||||||
|
- wsl
|
||||||
|
- wrapcheck
|
||||||
|
- testpackage
|
||||||
|
- nlreturn
|
||||||
|
- gomnd
|
||||||
|
- exhaustivestruct
|
||||||
|
- goerr113
|
||||||
|
- errorlint
|
||||||
|
- nestif
|
||||||
|
- godot
|
||||||
|
- gofumpt
|
||||||
|
- paralleltest
|
||||||
|
- tparallel
|
||||||
|
- thelper
|
||||||
|
- ifshort
|
||||||
|
- exhaustruct
|
||||||
|
- varnamelen
|
||||||
|
- gci
|
||||||
|
- depguard
|
||||||
|
- errchkjson
|
||||||
|
- inamedparam
|
||||||
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
|
- ireturn
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
# deprecated linters
|
||||||
|
- deadcode
|
||||||
|
- interfacer
|
||||||
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
|
- nosnakecase
|
|
@ -1 +0,0 @@
|
||||||
swp$
|
|
|
@ -1,168 +0,0 @@
|
||||||
INSTALLATION
|
|
||||||
|
|
||||||
go get bitbucket.org/pkg/inflect
|
|
||||||
|
|
||||||
PACKAGE
|
|
||||||
|
|
||||||
package inflect
|
|
||||||
|
|
||||||
|
|
||||||
FUNCTIONS
|
|
||||||
|
|
||||||
func AddAcronym(word string)
|
|
||||||
|
|
||||||
func AddHuman(suffix, replacement string)
|
|
||||||
|
|
||||||
func AddIrregular(singular, plural string)
|
|
||||||
|
|
||||||
func AddPlural(suffix, replacement string)
|
|
||||||
|
|
||||||
func AddSingular(suffix, replacement string)
|
|
||||||
|
|
||||||
func AddUncountable(word string)
|
|
||||||
|
|
||||||
func Asciify(word string) string
|
|
||||||
|
|
||||||
func Camelize(word string) string
|
|
||||||
|
|
||||||
func CamelizeDownFirst(word string) string
|
|
||||||
|
|
||||||
func Capitalize(word string) string
|
|
||||||
|
|
||||||
func Dasherize(word string) string
|
|
||||||
|
|
||||||
func ForeignKey(word string) string
|
|
||||||
|
|
||||||
func ForeignKeyCondensed(word string) string
|
|
||||||
|
|
||||||
func Humanize(word string) string
|
|
||||||
|
|
||||||
func Ordinalize(word string) string
|
|
||||||
|
|
||||||
func Parameterize(word string) string
|
|
||||||
|
|
||||||
func ParameterizeJoin(word, sep string) string
|
|
||||||
|
|
||||||
func Pluralize(word string) string
|
|
||||||
|
|
||||||
func Singularize(word string) string
|
|
||||||
|
|
||||||
func Tableize(word string) string
|
|
||||||
|
|
||||||
func Titleize(word string) string
|
|
||||||
|
|
||||||
func Typeify(word string) string
|
|
||||||
|
|
||||||
func Uncountables() map[string]bool
|
|
||||||
|
|
||||||
func Underscore(word string) string
|
|
||||||
|
|
||||||
|
|
||||||
TYPES
|
|
||||||
|
|
||||||
type Rule struct {
|
|
||||||
// contains filtered or unexported fields
|
|
||||||
}
|
|
||||||
used by rulesets
|
|
||||||
|
|
||||||
type Ruleset struct {
|
|
||||||
// contains filtered or unexported fields
|
|
||||||
}
|
|
||||||
a Ruleset is the config of pluralization rules
|
|
||||||
you can extend the rules with the Add* methods
|
|
||||||
|
|
||||||
func NewDefaultRuleset() *Ruleset
|
|
||||||
create a new ruleset and load it with the default
|
|
||||||
set of common English pluralization rules
|
|
||||||
|
|
||||||
func NewRuleset() *Ruleset
|
|
||||||
create a blank ruleset. Unless you are going to
|
|
||||||
build your own rules from scratch you probably
|
|
||||||
won't need this and can just use the defaultRuleset
|
|
||||||
via the global inflect.* methods
|
|
||||||
|
|
||||||
func (rs *Ruleset) AddAcronym(word string)
|
|
||||||
if you use acronym you may need to add them to the ruleset
|
|
||||||
to prevent Underscored words of things like "HTML" coming out
|
|
||||||
as "h_t_m_l"
|
|
||||||
|
|
||||||
func (rs *Ruleset) AddHuman(suffix, replacement string)
|
|
||||||
Human rules are applied by humanize to show more friendly
|
|
||||||
versions of words
|
|
||||||
|
|
||||||
func (rs *Ruleset) AddIrregular(singular, plural string)
|
|
||||||
Add any inconsistant pluralizing/sinularizing rules
|
|
||||||
to the set here.
|
|
||||||
|
|
||||||
func (rs *Ruleset) AddPlural(suffix, replacement string)
|
|
||||||
add a pluralization rule
|
|
||||||
|
|
||||||
func (rs *Ruleset) AddPluralExact(suffix, replacement string, exact bool)
|
|
||||||
add a pluralization rule with full string match
|
|
||||||
|
|
||||||
func (rs *Ruleset) AddSingular(suffix, replacement string)
|
|
||||||
add a singular rule
|
|
||||||
|
|
||||||
func (rs *Ruleset) AddSingularExact(suffix, replacement string, exact bool)
|
|
||||||
same as AddSingular but you can set `exact` to force
|
|
||||||
a full string match
|
|
||||||
|
|
||||||
func (rs *Ruleset) AddUncountable(word string)
|
|
||||||
add a word to this ruleset that has the same singular and plural form
|
|
||||||
for example: "rice"
|
|
||||||
|
|
||||||
func (rs *Ruleset) Asciify(word string) string
|
|
||||||
transforms latin characters like é -> e
|
|
||||||
|
|
||||||
func (rs *Ruleset) Camelize(word string) string
|
|
||||||
"dino_party" -> "DinoParty"
|
|
||||||
|
|
||||||
func (rs *Ruleset) CamelizeDownFirst(word string) string
|
|
||||||
same as Camelcase but with first letter downcased
|
|
||||||
|
|
||||||
func (rs *Ruleset) Capitalize(word string) string
|
|
||||||
uppercase first character
|
|
||||||
|
|
||||||
func (rs *Ruleset) Dasherize(word string) string
|
|
||||||
"SomeText" -> "some-text"
|
|
||||||
|
|
||||||
func (rs *Ruleset) ForeignKey(word string) string
|
|
||||||
an underscored foreign key name "Person" -> "person_id"
|
|
||||||
|
|
||||||
func (rs *Ruleset) ForeignKeyCondensed(word string) string
|
|
||||||
a foreign key (with an underscore) "Person" -> "personid"
|
|
||||||
|
|
||||||
func (rs *Ruleset) Humanize(word string) string
|
|
||||||
First letter of sentance captitilized
|
|
||||||
Uses custom friendly replacements via AddHuman()
|
|
||||||
|
|
||||||
func (rs *Ruleset) Ordinalize(str string) string
|
|
||||||
"1031" -> "1031st"
|
|
||||||
|
|
||||||
func (rs *Ruleset) Parameterize(word string) string
|
|
||||||
param safe dasherized names like "my-param"
|
|
||||||
|
|
||||||
func (rs *Ruleset) ParameterizeJoin(word, sep string) string
|
|
||||||
param safe dasherized names with custom seperator
|
|
||||||
|
|
||||||
func (rs *Ruleset) Pluralize(word string) string
|
|
||||||
returns the plural form of a singular word
|
|
||||||
|
|
||||||
func (rs *Ruleset) Singularize(word string) string
|
|
||||||
returns the singular form of a plural word
|
|
||||||
|
|
||||||
func (rs *Ruleset) Tableize(word string) string
|
|
||||||
Rails style pluralized table names: "SuperPerson" -> "super_people"
|
|
||||||
|
|
||||||
func (rs *Ruleset) Titleize(word string) string
|
|
||||||
Captitilize every word in sentance "hello there" -> "Hello There"
|
|
||||||
|
|
||||||
func (rs *Ruleset) Typeify(word string) string
|
|
||||||
"something_like_this" -> "SomethingLikeThis"
|
|
||||||
|
|
||||||
func (rs *Ruleset) Uncountables() map[string]bool
|
|
||||||
|
|
||||||
func (rs *Ruleset) Underscore(word string) string
|
|
||||||
lowercase underscore version "BigBen" -> "big_ben"
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# inflect [![Build Status](https://github.com/go-openapi/inflect/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/inflect/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/inflect/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/inflect)
|
||||||
|
|
||||||
|
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
||||||
|
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/inflect/master/LICENSE)
|
||||||
|
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/inflect.svg)](https://pkg.go.dev/github.com/go-openapi/inflect)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/inflect)](https://goreportcard.com/report/github.com/go-openapi/inflect)
|
||||||
|
|
||||||
|
A package to pluralize words.
|
||||||
|
|
||||||
|
Originally forked from fork of https://bitbucket.org/pkg/inflect under a MIT License.
|
||||||
|
|
||||||
|
A golang library applying grammar rules to English words.
|
||||||
|
|
||||||
|
> This package provides a basic set of functions applying
|
||||||
|
> grammar rules to inflect English words, modify case style
|
||||||
|
> (Capitalize, camelCase, snake_case, etc.).
|
||||||
|
>
|
||||||
|
> Acronyms are properly handled. A common use case is word pluralization.
|
|
@ -19,12 +19,11 @@ type Rule struct {
|
||||||
// a Ruleset is the config of pluralization rules
|
// a Ruleset is the config of pluralization rules
|
||||||
// you can extend the rules with the Add* methods
|
// you can extend the rules with the Add* methods
|
||||||
type Ruleset struct {
|
type Ruleset struct {
|
||||||
uncountables map[string]bool
|
uncountables map[string]bool
|
||||||
plurals []*Rule
|
plurals []*Rule
|
||||||
singulars []*Rule
|
singulars []*Rule
|
||||||
humans []*Rule
|
humans []*Rule
|
||||||
acronyms []*Rule
|
acronyms []*Rule
|
||||||
acronymMatcher *regexp.Regexp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a blank ruleset. Unless you are going to
|
// create a blank ruleset. Unless you are going to
|
||||||
|
@ -282,7 +281,7 @@ func (rs *Ruleset) AddHuman(suffix, replacement string) {
|
||||||
rs.humans = append([]*Rule{r}, rs.humans...)
|
rs.humans = append([]*Rule{r}, rs.humans...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any inconsistant pluralizing/sinularizing rules
|
// Add any inconsistent pluralizing/sinularizing rules
|
||||||
// to the set here.
|
// to the set here.
|
||||||
func (rs *Ruleset) AddIrregular(singular, plural string) {
|
func (rs *Ruleset) AddIrregular(singular, plural string) {
|
||||||
delete(rs.uncountables, singular)
|
delete(rs.uncountables, singular)
|
||||||
|
@ -387,7 +386,7 @@ func (rs *Ruleset) Titleize(word string) string {
|
||||||
func (rs *Ruleset) safeCaseAcronyms(word string) string {
|
func (rs *Ruleset) safeCaseAcronyms(word string) string {
|
||||||
// convert an acroymn like HTML into Html
|
// convert an acroymn like HTML into Html
|
||||||
for _, rule := range rs.acronyms {
|
for _, rule := range rs.acronyms {
|
||||||
word = strings.Replace(word, rule.suffix, rule.replacement, -1)
|
word = strings.ReplaceAll(word, rule.suffix, rule.replacement)
|
||||||
}
|
}
|
||||||
return word
|
return word
|
||||||
}
|
}
|
||||||
|
@ -409,7 +408,7 @@ func (rs *Ruleset) Humanize(word string) string {
|
||||||
word = replaceLast(word, "_id", "") // strip foreign key kinds
|
word = replaceLast(word, "_id", "") // strip foreign key kinds
|
||||||
// replace and strings in humans list
|
// replace and strings in humans list
|
||||||
for _, rule := range rs.humans {
|
for _, rule := range rs.humans {
|
||||||
word = strings.Replace(word, rule.suffix, rule.replacement, -1)
|
word = strings.ReplaceAll(word, rule.suffix, rule.replacement)
|
||||||
}
|
}
|
||||||
sentance := rs.seperatedWords(word, " ")
|
sentance := rs.seperatedWords(word, " ")
|
||||||
return strings.ToUpper(sentance[:1]) + sentance[1:]
|
return strings.ToUpper(sentance[:1]) + sentance[1:]
|
||||||
|
@ -430,19 +429,19 @@ func (rs *Ruleset) Tableize(word string) string {
|
||||||
return rs.Pluralize(rs.Underscore(rs.Typeify(word)))
|
return rs.Pluralize(rs.Underscore(rs.Typeify(word)))
|
||||||
}
|
}
|
||||||
|
|
||||||
var notUrlSafe *regexp.Regexp = regexp.MustCompile(`[^\w\d\-_ ]`)
|
var notURLSafe = regexp.MustCompile(`[^\w\d\-_ ]`)
|
||||||
|
|
||||||
// param safe dasherized names like "my-param"
|
// param safe dasherized names like "my-param"
|
||||||
func (rs *Ruleset) Parameterize(word string) string {
|
func (rs *Ruleset) Parameterize(word string) string {
|
||||||
return ParameterizeJoin(word, "-")
|
return ParameterizeJoin(word, "-")
|
||||||
}
|
}
|
||||||
|
|
||||||
// param safe dasherized names with custom seperator
|
// param safe dasherized names with custom separator
|
||||||
func (rs *Ruleset) ParameterizeJoin(word, sep string) string {
|
func (rs *Ruleset) ParameterizeJoin(word, sep string) string {
|
||||||
word = strings.ToLower(word)
|
word = strings.ToLower(word)
|
||||||
word = rs.Asciify(word)
|
word = rs.Asciify(word)
|
||||||
word = notUrlSafe.ReplaceAllString(word, "")
|
word = notURLSafe.ReplaceAllString(word, "")
|
||||||
word = strings.Replace(word, " ", sep, -1)
|
word = strings.ReplaceAll(word, " ", sep)
|
||||||
if len(sep) > 0 {
|
if len(sep) > 0 {
|
||||||
squash, err := regexp.Compile(sep + "+")
|
squash, err := regexp.Compile(sep + "+")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -453,7 +452,7 @@ func (rs *Ruleset) ParameterizeJoin(word, sep string) string {
|
||||||
return word
|
return word
|
||||||
}
|
}
|
||||||
|
|
||||||
var lookalikes map[string]*regexp.Regexp = map[string]*regexp.Regexp{
|
var lookalikes = map[string]*regexp.Regexp{
|
||||||
"A": regexp.MustCompile(`À|Á|Â|Ã|Ä|Å`),
|
"A": regexp.MustCompile(`À|Á|Â|Ã|Ä|Å`),
|
||||||
"AE": regexp.MustCompile(`Æ`),
|
"AE": regexp.MustCompile(`Æ`),
|
||||||
"C": regexp.MustCompile(`Ç`),
|
"C": regexp.MustCompile(`Ç`),
|
||||||
|
@ -487,7 +486,7 @@ func (rs *Ruleset) Asciify(word string) string {
|
||||||
return word
|
return word
|
||||||
}
|
}
|
||||||
|
|
||||||
var tablePrefix *regexp.Regexp = regexp.MustCompile(`^[^.]*\.`)
|
var tablePrefix = regexp.MustCompile(`^[^.]*\.`)
|
||||||
|
|
||||||
// "something_like_this" -> "SomethingLikeThis"
|
// "something_like_this" -> "SomethingLikeThis"
|
||||||
func (rs *Ruleset) Typeify(word string) string {
|
func (rs *Ruleset) Typeify(word string) string {
|
||||||
|
@ -642,13 +641,13 @@ func reverse(s string) string {
|
||||||
|
|
||||||
func isSpacerChar(c rune) bool {
|
func isSpacerChar(c rune) bool {
|
||||||
switch {
|
switch {
|
||||||
case c == rune("_"[0]):
|
case c == '_':
|
||||||
return true
|
return true
|
||||||
case c == rune(" "[0]):
|
case c == ':':
|
||||||
return true
|
return true
|
||||||
case c == rune(":"[0]):
|
case c == '-':
|
||||||
return true
|
return true
|
||||||
case c == rune("-"[0]):
|
case unicode.IsSpace(c):
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
linters-settings:
|
||||||
|
govet:
|
||||||
|
check-shadowing: true
|
||||||
|
golint:
|
||||||
|
min-confidence: 0
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 45
|
||||||
|
maligned:
|
||||||
|
suggest-new: true
|
||||||
|
dupl:
|
||||||
|
threshold: 200
|
||||||
|
goconst:
|
||||||
|
min-len: 2
|
||||||
|
min-occurrences: 3
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable-all: true
|
||||||
|
disable:
|
||||||
|
- maligned
|
||||||
|
- unparam
|
||||||
|
- lll
|
||||||
|
- gochecknoinits
|
||||||
|
- gochecknoglobals
|
||||||
|
- funlen
|
||||||
|
- godox
|
||||||
|
- gocognit
|
||||||
|
- whitespace
|
||||||
|
- wsl
|
||||||
|
- wrapcheck
|
||||||
|
- testpackage
|
||||||
|
- nlreturn
|
||||||
|
- gomnd
|
||||||
|
- exhaustivestruct
|
||||||
|
- goerr113
|
||||||
|
- errorlint
|
||||||
|
- nestif
|
||||||
|
- godot
|
||||||
|
- gofumpt
|
||||||
|
- paralleltest
|
||||||
|
- tparallel
|
||||||
|
- thelper
|
||||||
|
- ifshort
|
||||||
|
- exhaustruct
|
||||||
|
- varnamelen
|
||||||
|
- gci
|
||||||
|
- depguard
|
||||||
|
- errchkjson
|
||||||
|
- inamedparam
|
||||||
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
|
- ireturn
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
# deprecated linters
|
||||||
|
- deadcode
|
||||||
|
- interfacer
|
||||||
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
|
- nosnakecase
|
|
@ -1,6 +1,10 @@
|
||||||
# gojsonpointer [![Build Status](https://travis-ci.org/go-openapi/jsonpointer.svg?branch=master)](https://travis-ci.org/go-openapi/jsonpointer) [![codecov](https://codecov.io/gh/go-openapi/jsonpointer/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonpointer) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
# gojsonpointer [![Build Status](https://github.com/go-openapi/jsonpointer/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/jsonpointer/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/jsonpointer/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonpointer)
|
||||||
|
|
||||||
|
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
||||||
|
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonpointer/master/LICENSE)
|
||||||
|
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/jsonpointer.svg)](https://pkg.go.dev/github.com/go-openapi/jsonpointer)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/jsonpointer)](https://goreportcard.com/report/github.com/go-openapi/jsonpointer)
|
||||||
|
|
||||||
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonpointer/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/jsonpointer?status.svg)](http://godoc.org/github.com/go-openapi/jsonpointer)
|
|
||||||
An implementation of JSON Pointer - Go language
|
An implementation of JSON Pointer - Go language
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
package jsonpointer
|
package jsonpointer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -40,6 +41,7 @@ const (
|
||||||
pointerSeparator = `/`
|
pointerSeparator = `/`
|
||||||
|
|
||||||
invalidStart = `JSON pointer must be empty or start with a "` + pointerSeparator
|
invalidStart = `JSON pointer must be empty or start with a "` + pointerSeparator
|
||||||
|
notFound = `Can't find the pointer in the document`
|
||||||
)
|
)
|
||||||
|
|
||||||
var jsonPointableType = reflect.TypeOf(new(JSONPointable)).Elem()
|
var jsonPointableType = reflect.TypeOf(new(JSONPointable)).Elem()
|
||||||
|
@ -48,13 +50,13 @@ var jsonSetableType = reflect.TypeOf(new(JSONSetable)).Elem()
|
||||||
// JSONPointable is an interface for structs to implement when they need to customize the
|
// JSONPointable is an interface for structs to implement when they need to customize the
|
||||||
// json pointer process
|
// json pointer process
|
||||||
type JSONPointable interface {
|
type JSONPointable interface {
|
||||||
JSONLookup(string) (interface{}, error)
|
JSONLookup(string) (any, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONSetable is an interface for structs to implement when they need to customize the
|
// JSONSetable is an interface for structs to implement when they need to customize the
|
||||||
// json pointer process
|
// json pointer process
|
||||||
type JSONSetable interface {
|
type JSONSetable interface {
|
||||||
JSONSet(string, interface{}) error
|
JSONSet(string, any) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new json pointer for the given string
|
// New creates a new json pointer for the given string
|
||||||
|
@ -81,9 +83,7 @@ func (p *Pointer) parse(jsonPointerString string) error {
|
||||||
err = errors.New(invalidStart)
|
err = errors.New(invalidStart)
|
||||||
} else {
|
} else {
|
||||||
referenceTokens := strings.Split(jsonPointerString, pointerSeparator)
|
referenceTokens := strings.Split(jsonPointerString, pointerSeparator)
|
||||||
for _, referenceToken := range referenceTokens[1:] {
|
p.referenceTokens = append(p.referenceTokens, referenceTokens[1:]...)
|
||||||
p.referenceTokens = append(p.referenceTokens, referenceToken)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,38 +91,58 @@ func (p *Pointer) parse(jsonPointerString string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get uses the pointer to retrieve a value from a JSON document
|
// Get uses the pointer to retrieve a value from a JSON document
|
||||||
func (p *Pointer) Get(document interface{}) (interface{}, reflect.Kind, error) {
|
func (p *Pointer) Get(document any) (any, reflect.Kind, error) {
|
||||||
return p.get(document, swag.DefaultJSONNameProvider)
|
return p.get(document, swag.DefaultJSONNameProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set uses the pointer to set a value from a JSON document
|
// Set uses the pointer to set a value from a JSON document
|
||||||
func (p *Pointer) Set(document interface{}, value interface{}) (interface{}, error) {
|
func (p *Pointer) Set(document any, value any) (any, error) {
|
||||||
return document, p.set(document, value, swag.DefaultJSONNameProvider)
|
return document, p.set(document, value, swag.DefaultJSONNameProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetForToken gets a value for a json pointer token 1 level deep
|
// GetForToken gets a value for a json pointer token 1 level deep
|
||||||
func GetForToken(document interface{}, decodedToken string) (interface{}, reflect.Kind, error) {
|
func GetForToken(document any, decodedToken string) (any, reflect.Kind, error) {
|
||||||
return getSingleImpl(document, decodedToken, swag.DefaultJSONNameProvider)
|
return getSingleImpl(document, decodedToken, swag.DefaultJSONNameProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetForToken gets a value for a json pointer token 1 level deep
|
// SetForToken gets a value for a json pointer token 1 level deep
|
||||||
func SetForToken(document interface{}, decodedToken string, value interface{}) (interface{}, error) {
|
func SetForToken(document any, decodedToken string, value any) (any, error) {
|
||||||
return document, setSingleImpl(document, value, decodedToken, swag.DefaultJSONNameProvider)
|
return document, setSingleImpl(document, value, decodedToken, swag.DefaultJSONNameProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSingleImpl(node interface{}, decodedToken string, nameProvider *swag.NameProvider) (interface{}, reflect.Kind, error) {
|
func isNil(input any) bool {
|
||||||
|
if input == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
kind := reflect.TypeOf(input).Kind()
|
||||||
|
switch kind { //nolint:exhaustive
|
||||||
|
case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Chan:
|
||||||
|
return reflect.ValueOf(input).IsNil()
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvider) (any, reflect.Kind, error) {
|
||||||
rValue := reflect.Indirect(reflect.ValueOf(node))
|
rValue := reflect.Indirect(reflect.ValueOf(node))
|
||||||
kind := rValue.Kind()
|
kind := rValue.Kind()
|
||||||
|
if isNil(node) {
|
||||||
|
return nil, kind, fmt.Errorf("nil value has not field %q", decodedToken)
|
||||||
|
}
|
||||||
|
|
||||||
if rValue.Type().Implements(jsonPointableType) {
|
switch typed := node.(type) {
|
||||||
r, err := node.(JSONPointable).JSONLookup(decodedToken)
|
case JSONPointable:
|
||||||
|
r, err := typed.JSONLookup(decodedToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, kind, err
|
return nil, kind, err
|
||||||
}
|
}
|
||||||
return r, kind, nil
|
return r, kind, nil
|
||||||
|
case *any: // case of a pointer to interface, that is not resolved by reflect.Indirect
|
||||||
|
return getSingleImpl(*typed, decodedToken, nameProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch kind {
|
switch kind { //nolint:exhaustive
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
|
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -159,7 +179,7 @@ func getSingleImpl(node interface{}, decodedToken string, nameProvider *swag.Nam
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setSingleImpl(node, data interface{}, decodedToken string, nameProvider *swag.NameProvider) error {
|
func setSingleImpl(node, data any, decodedToken string, nameProvider *swag.NameProvider) error {
|
||||||
rValue := reflect.Indirect(reflect.ValueOf(node))
|
rValue := reflect.Indirect(reflect.ValueOf(node))
|
||||||
|
|
||||||
if ns, ok := node.(JSONSetable); ok { // pointer impl
|
if ns, ok := node.(JSONSetable); ok { // pointer impl
|
||||||
|
@ -170,7 +190,7 @@ func setSingleImpl(node, data interface{}, decodedToken string, nameProvider *sw
|
||||||
return node.(JSONSetable).JSONSet(decodedToken, data)
|
return node.(JSONSetable).JSONSet(decodedToken, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch rValue.Kind() {
|
switch rValue.Kind() { //nolint:exhaustive
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
|
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -210,7 +230,7 @@ func setSingleImpl(node, data interface{}, decodedToken string, nameProvider *sw
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pointer) get(node interface{}, nameProvider *swag.NameProvider) (interface{}, reflect.Kind, error) {
|
func (p *Pointer) get(node any, nameProvider *swag.NameProvider) (any, reflect.Kind, error) {
|
||||||
|
|
||||||
if nameProvider == nil {
|
if nameProvider == nil {
|
||||||
nameProvider = swag.DefaultJSONNameProvider
|
nameProvider = swag.DefaultJSONNameProvider
|
||||||
|
@ -231,8 +251,7 @@ func (p *Pointer) get(node interface{}, nameProvider *swag.NameProvider) (interf
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, knd, err
|
return nil, knd, err
|
||||||
}
|
}
|
||||||
node, kind = r, knd
|
node = r
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rValue := reflect.ValueOf(node)
|
rValue := reflect.ValueOf(node)
|
||||||
|
@ -241,11 +260,11 @@ func (p *Pointer) get(node interface{}, nameProvider *swag.NameProvider) (interf
|
||||||
return node, kind, nil
|
return node, kind, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pointer) set(node, data interface{}, nameProvider *swag.NameProvider) error {
|
func (p *Pointer) set(node, data any, nameProvider *swag.NameProvider) error {
|
||||||
knd := reflect.ValueOf(node).Kind()
|
knd := reflect.ValueOf(node).Kind()
|
||||||
|
|
||||||
if knd != reflect.Ptr && knd != reflect.Struct && knd != reflect.Map && knd != reflect.Slice && knd != reflect.Array {
|
if knd != reflect.Ptr && knd != reflect.Struct && knd != reflect.Map && knd != reflect.Slice && knd != reflect.Array {
|
||||||
return fmt.Errorf("only structs, pointers, maps and slices are supported for setting values")
|
return errors.New("only structs, pointers, maps and slices are supported for setting values")
|
||||||
}
|
}
|
||||||
|
|
||||||
if nameProvider == nil {
|
if nameProvider == nil {
|
||||||
|
@ -284,7 +303,7 @@ func (p *Pointer) set(node, data interface{}, nameProvider *swag.NameProvider) e
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch kind {
|
switch kind { //nolint:exhaustive
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
|
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -363,6 +382,128 @@ func (p *Pointer) String() string {
|
||||||
return pointerString
|
return pointerString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Pointer) Offset(document string) (int64, error) {
|
||||||
|
dec := json.NewDecoder(strings.NewReader(document))
|
||||||
|
var offset int64
|
||||||
|
for _, ttk := range p.DecodedTokens() {
|
||||||
|
tk, err := dec.Token()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
switch tk := tk.(type) {
|
||||||
|
case json.Delim:
|
||||||
|
switch tk {
|
||||||
|
case '{':
|
||||||
|
offset, err = offsetSingleObject(dec, ttk)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
case '[':
|
||||||
|
offset, err = offsetSingleArray(dec, ttk)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("invalid token %#v", tk)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("invalid token %#v", tk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) {
|
||||||
|
for dec.More() {
|
||||||
|
offset := dec.InputOffset()
|
||||||
|
tk, err := dec.Token()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
switch tk := tk.(type) {
|
||||||
|
case json.Delim:
|
||||||
|
switch tk {
|
||||||
|
case '{':
|
||||||
|
if err = drainSingle(dec); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
case '[':
|
||||||
|
if err = drainSingle(dec); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case string:
|
||||||
|
if tk == decodedToken {
|
||||||
|
return offset, nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("invalid token %#v", tk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("token reference %q not found", decodedToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) {
|
||||||
|
idx, err := strconv.Atoi(decodedToken)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("token reference %q is not a number: %v", decodedToken, err)
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
for i = 0; i < idx && dec.More(); i++ {
|
||||||
|
tk, err := dec.Token()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if delim, isDelim := tk.(json.Delim); isDelim {
|
||||||
|
switch delim {
|
||||||
|
case '{':
|
||||||
|
if err = drainSingle(dec); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
case '[':
|
||||||
|
if err = drainSingle(dec); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !dec.More() {
|
||||||
|
return 0, fmt.Errorf("token reference %q not found", decodedToken)
|
||||||
|
}
|
||||||
|
return dec.InputOffset(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// drainSingle drains a single level of object or array.
|
||||||
|
// The decoder has to guarantee the beginning delim (i.e. '{' or '[') has been consumed.
|
||||||
|
func drainSingle(dec *json.Decoder) error {
|
||||||
|
for dec.More() {
|
||||||
|
tk, err := dec.Token()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if delim, isDelim := tk.(json.Delim); isDelim {
|
||||||
|
switch delim {
|
||||||
|
case '{':
|
||||||
|
if err = drainSingle(dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case '[':
|
||||||
|
if err = drainSingle(dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consumes the ending delim
|
||||||
|
if _, err := dec.Token(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Specific JSON pointer encoding here
|
// Specific JSON pointer encoding here
|
||||||
// ~0 => ~
|
// ~0 => ~
|
||||||
// ~1 => /
|
// ~1 => /
|
||||||
|
@ -377,14 +518,14 @@ const (
|
||||||
|
|
||||||
// Unescape unescapes a json pointer reference token string to the original representation
|
// Unescape unescapes a json pointer reference token string to the original representation
|
||||||
func Unescape(token string) string {
|
func Unescape(token string) string {
|
||||||
step1 := strings.Replace(token, encRefTok1, decRefTok1, -1)
|
step1 := strings.ReplaceAll(token, encRefTok1, decRefTok1)
|
||||||
step2 := strings.Replace(step1, encRefTok0, decRefTok0, -1)
|
step2 := strings.ReplaceAll(step1, encRefTok0, decRefTok0)
|
||||||
return step2
|
return step2
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escape escapes a pointer reference token string
|
// Escape escapes a pointer reference token string
|
||||||
func Escape(token string) string {
|
func Escape(token string) string {
|
||||||
step1 := strings.Replace(token, decRefTok0, encRefTok0, -1)
|
step1 := strings.ReplaceAll(token, decRefTok0, encRefTok0)
|
||||||
step2 := strings.Replace(step1, decRefTok1, encRefTok1, -1)
|
step2 := strings.ReplaceAll(step1, decRefTok1, encRefTok1)
|
||||||
return step2
|
return step2
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +1,61 @@
|
||||||
linters-settings:
|
linters-settings:
|
||||||
govet:
|
govet:
|
||||||
check-shadowing: true
|
check-shadowing: true
|
||||||
|
golint:
|
||||||
|
min-confidence: 0
|
||||||
gocyclo:
|
gocyclo:
|
||||||
min-complexity: 30
|
min-complexity: 45
|
||||||
maligned:
|
maligned:
|
||||||
suggest-new: true
|
suggest-new: true
|
||||||
dupl:
|
dupl:
|
||||||
threshold: 100
|
threshold: 200
|
||||||
goconst:
|
goconst:
|
||||||
min-len: 2
|
min-len: 2
|
||||||
min-occurrences: 4
|
min-occurrences: 3
|
||||||
paralleltest:
|
|
||||||
ignore-missing: true
|
|
||||||
linters:
|
linters:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
disable:
|
disable:
|
||||||
- maligned
|
- maligned
|
||||||
|
- unparam
|
||||||
- lll
|
- lll
|
||||||
|
- gochecknoinits
|
||||||
- gochecknoglobals
|
- gochecknoglobals
|
||||||
|
- funlen
|
||||||
- godox
|
- godox
|
||||||
- gocognit
|
- gocognit
|
||||||
- whitespace
|
- whitespace
|
||||||
- wsl
|
- wsl
|
||||||
- funlen
|
|
||||||
- gochecknoglobals
|
|
||||||
- gochecknoinits
|
|
||||||
- scopelint
|
|
||||||
- wrapcheck
|
- wrapcheck
|
||||||
- exhaustivestruct
|
|
||||||
- exhaustive
|
|
||||||
- nlreturn
|
|
||||||
- testpackage
|
- testpackage
|
||||||
- gci
|
- nlreturn
|
||||||
- gofumpt
|
|
||||||
- goerr113
|
|
||||||
- gomnd
|
- gomnd
|
||||||
- tparallel
|
- exhaustivestruct
|
||||||
|
- goerr113
|
||||||
|
- errorlint
|
||||||
- nestif
|
- nestif
|
||||||
- godot
|
- godot
|
||||||
- errorlint
|
- gofumpt
|
||||||
- varcheck
|
- paralleltest
|
||||||
- interfacer
|
- tparallel
|
||||||
- deadcode
|
- thelper
|
||||||
- golint
|
|
||||||
- ifshort
|
- ifshort
|
||||||
- structcheck
|
|
||||||
- nosnakecase
|
|
||||||
- varnamelen
|
|
||||||
- exhaustruct
|
- exhaustruct
|
||||||
|
- varnamelen
|
||||||
|
- gci
|
||||||
|
- depguard
|
||||||
|
- errchkjson
|
||||||
|
- inamedparam
|
||||||
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
|
- ireturn
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
# deprecated linters
|
||||||
|
- deadcode
|
||||||
|
- interfacer
|
||||||
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
|
- nosnakecase
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
# gojsonreference [![Build Status](https://travis-ci.org/go-openapi/jsonreference.svg?branch=master)](https://travis-ci.org/go-openapi/jsonreference) [![codecov](https://codecov.io/gh/go-openapi/jsonreference/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonreference) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
# gojsonreference [![Build Status](https://github.com/go-openapi/jsonreference/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/jsonreference/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/jsonreference/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonreference)
|
||||||
|
|
||||||
|
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
||||||
|
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonreference/master/LICENSE)
|
||||||
|
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/jsonreference.svg)](https://pkg.go.dev/github.com/go-openapi/jsonreference)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/jsonreference)](https://goreportcard.com/report/github.com/go-openapi/jsonreference)
|
||||||
|
|
||||||
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonreference/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/jsonreference?status.svg)](http://godoc.org/github.com/go-openapi/jsonreference)
|
|
||||||
An implementation of JSON Reference - Go language
|
An implementation of JSON Reference - Go language
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
Feature complete. Stable API
|
Feature complete. Stable API
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
https://github.com/go-openapi/jsonpointer
|
* https://github.com/go-openapi/jsonpointer
|
||||||
|
|
||||||
## References
|
## References
|
||||||
http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
|
|
||||||
|
|
||||||
http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
|
* http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
|
||||||
|
* http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
|
||||||
|
|
|
@ -4,41 +4,58 @@ linters-settings:
|
||||||
golint:
|
golint:
|
||||||
min-confidence: 0
|
min-confidence: 0
|
||||||
gocyclo:
|
gocyclo:
|
||||||
min-complexity: 30
|
min-complexity: 45
|
||||||
maligned:
|
maligned:
|
||||||
suggest-new: true
|
suggest-new: true
|
||||||
dupl:
|
dupl:
|
||||||
threshold: 100
|
threshold: 200
|
||||||
goconst:
|
goconst:
|
||||||
min-len: 2
|
min-len: 2
|
||||||
min-occurrences: 4
|
min-occurrences: 3
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
disable:
|
disable:
|
||||||
- maligned
|
- maligned
|
||||||
|
- unparam
|
||||||
- lll
|
- lll
|
||||||
- gochecknoglobals
|
|
||||||
- gochecknoinits
|
- gochecknoinits
|
||||||
|
- gochecknoglobals
|
||||||
|
- funlen
|
||||||
- godox
|
- godox
|
||||||
- gocognit
|
- gocognit
|
||||||
- whitespace
|
- whitespace
|
||||||
- wsl
|
- wsl
|
||||||
- funlen
|
|
||||||
- gochecknoglobals
|
|
||||||
- gochecknoinits
|
|
||||||
- scopelint
|
|
||||||
- wrapcheck
|
- wrapcheck
|
||||||
- exhaustivestruct
|
|
||||||
- exhaustive
|
|
||||||
- nlreturn
|
|
||||||
- testpackage
|
- testpackage
|
||||||
- gci
|
- nlreturn
|
||||||
- gofumpt
|
|
||||||
- goerr113
|
|
||||||
- gomnd
|
- gomnd
|
||||||
- tparallel
|
- exhaustivestruct
|
||||||
|
- goerr113
|
||||||
|
- errorlint
|
||||||
- nestif
|
- nestif
|
||||||
- godot
|
- godot
|
||||||
- errorlint
|
- gofumpt
|
||||||
- paralleltest
|
- paralleltest
|
||||||
|
- tparallel
|
||||||
|
- thelper
|
||||||
|
- ifshort
|
||||||
|
- exhaustruct
|
||||||
|
- varnamelen
|
||||||
|
- gci
|
||||||
|
- depguard
|
||||||
|
- errchkjson
|
||||||
|
- inamedparam
|
||||||
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
|
- ireturn
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
# deprecated linters
|
||||||
|
- deadcode
|
||||||
|
- interfacer
|
||||||
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
|
- nosnakecase
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Loads OAI specs [![Build Status](https://travis-ci.org/go-openapi/loads.svg?branch=master)](https://travis-ci.org/go-openapi/loads) [![codecov](https://codecov.io/gh/go-openapi/loads/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/loads) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) [![Actions/Go Test Status](https://github.com/go-openapi/loads/workflows/Go%20Test/badge.svg)](https://github.com/go-openapi/loads/actions?query=workflow%3A"Go+Test")
|
# Loads OAI specs [![Build Status](https://github.com/go-openapi/loads/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/loads/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/loads/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/loads)
|
||||||
|
|
||||||
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/loads/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/loads?status.svg)](http://godoc.org/github.com/go-openapi/loads)
|
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/loads/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/loads?status.svg)](http://godoc.org/github.com/go-openapi/loads)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/loads)](https://goreportcard.com/report/github.com/go-openapi/loads)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/loads)](https://goreportcard.com/report/github.com/go-openapi/loads)
|
||||||
|
|
|
@ -12,10 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
/*
|
// Package loads provides document loading methods for swagger (OAI) specifications.
|
||||||
Package loads provides document loading methods for swagger (OAI) specifications.
|
//
|
||||||
|
// It is used by other go-openapi packages to load and run analysis on local or remote spec documents.
|
||||||
It is used by other go-openapi packages to load and run analysis on local or remote spec documents.
|
|
||||||
|
|
||||||
*/
|
|
||||||
package loads
|
package loads
|
||||||
|
|
|
@ -21,7 +21,7 @@ var (
|
||||||
func init() {
|
func init() {
|
||||||
jsonLoader := &loader{
|
jsonLoader := &loader{
|
||||||
DocLoaderWithMatch: DocLoaderWithMatch{
|
DocLoaderWithMatch: DocLoaderWithMatch{
|
||||||
Match: func(pth string) bool {
|
Match: func(_ string) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
Fn: JSONDoc,
|
Fn: JSONDoc,
|
||||||
|
@ -86,7 +86,7 @@ func (l *loader) Load(path string) (json.RawMessage, error) {
|
||||||
return nil, erp
|
return nil, erp
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastErr error = errors.New("no loader matched") // default error if no match was found
|
lastErr := errors.New("no loader matched") // default error if no match was found
|
||||||
for ldr := l; ldr != nil; ldr = ldr.Next {
|
for ldr := l; ldr != nil; ldr = ldr.Next {
|
||||||
if ldr.Match != nil && !ldr.Match(path) {
|
if ldr.Match != nil && !ldr.Match(path) {
|
||||||
continue
|
continue
|
||||||
|
@ -118,9 +118,8 @@ func JSONDoc(path string) (json.RawMessage, error) {
|
||||||
// This sets the configuration at the package level.
|
// This sets the configuration at the package level.
|
||||||
//
|
//
|
||||||
// NOTE:
|
// NOTE:
|
||||||
// * this updates the default loader used by github.com/go-openapi/spec
|
// - this updates the default loader used by github.com/go-openapi/spec
|
||||||
// * since this sets package level globals, you shouln't call this concurrently
|
// - since this sets package level globals, you shouln't call this concurrently
|
||||||
//
|
|
||||||
func AddLoader(predicate DocMatcher, load DocLoader) {
|
func AddLoader(predicate DocMatcher, load DocLoader) {
|
||||||
loaders = loaders.WithHead(&loader{
|
loaders = loaders.WithHead(&loader{
|
||||||
DocLoaderWithMatch: DocLoaderWithMatch{
|
DocLoaderWithMatch: DocLoaderWithMatch{
|
||||||
|
|
|
@ -38,8 +38,8 @@ type Document struct {
|
||||||
specFilePath string
|
specFilePath string
|
||||||
origSpec *spec.Swagger
|
origSpec *spec.Swagger
|
||||||
schema *spec.Schema
|
schema *spec.Schema
|
||||||
raw json.RawMessage
|
|
||||||
pathLoader *loader
|
pathLoader *loader
|
||||||
|
raw json.RawMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONSpec loads a spec from a json document
|
// JSONSpec loads a spec from a json document
|
||||||
|
@ -49,7 +49,14 @@ func JSONSpec(path string, options ...LoaderOption) (*Document, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// convert to json
|
// convert to json
|
||||||
return Analyzed(data, "", options...)
|
doc, err := Analyzed(data, "", options...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.specFilePath = path
|
||||||
|
|
||||||
|
return doc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Embedded returns a Document based on embedded specs. No analysis is required
|
// Embedded returns a Document based on embedded specs. No analysis is required
|
||||||
|
@ -71,7 +78,6 @@ func Embedded(orig, flat json.RawMessage, options ...LoaderOption) (*Document, e
|
||||||
|
|
||||||
// Spec loads a new spec document from a local or remote path
|
// Spec loads a new spec document from a local or remote path
|
||||||
func Spec(path string, options ...LoaderOption) (*Document, error) {
|
func Spec(path string, options ...LoaderOption) (*Document, error) {
|
||||||
|
|
||||||
ldr := loaderFromOptions(options)
|
ldr := loaderFromOptions(options)
|
||||||
|
|
||||||
b, err := ldr.Load(path)
|
b, err := ldr.Load(path)
|
||||||
|
@ -84,12 +90,10 @@ func Spec(path string, options ...LoaderOption) (*Document, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if document != nil {
|
document.specFilePath = path
|
||||||
document.specFilePath = path
|
document.pathLoader = ldr
|
||||||
document.pathLoader = ldr
|
|
||||||
}
|
|
||||||
|
|
||||||
return document, err
|
return document, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyzed creates a new analyzed spec document for a root json.RawMessage.
|
// Analyzed creates a new analyzed spec document for a root json.RawMessage.
|
||||||
|
@ -117,7 +121,7 @@ func Analyzed(data json.RawMessage, version string, options ...LoaderOption) (*D
|
||||||
}
|
}
|
||||||
|
|
||||||
d := &Document{
|
d := &Document{
|
||||||
Analyzer: analysis.New(swspec),
|
Analyzer: analysis.New(swspec), // NOTE: at this moment, analysis does not follow $refs to documents outside the root doc
|
||||||
schema: spec.MustLoadSwagger20Schema(),
|
schema: spec.MustLoadSwagger20Schema(),
|
||||||
spec: swspec,
|
spec: swspec,
|
||||||
raw: raw,
|
raw: raw,
|
||||||
|
@ -152,9 +156,8 @@ func trimData(in json.RawMessage) (json.RawMessage, error) {
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expanded expands the ref fields in the spec document and returns a new spec document
|
// Expanded expands the $ref fields in the spec document and returns a new spec document
|
||||||
func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) {
|
func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) {
|
||||||
|
|
||||||
swspec := new(spec.Swagger)
|
swspec := new(spec.Swagger)
|
||||||
if err := json.Unmarshal(d.raw, swspec); err != nil {
|
if err := json.Unmarshal(d.raw, swspec); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -163,6 +166,9 @@ func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) {
|
||||||
var expandOptions *spec.ExpandOptions
|
var expandOptions *spec.ExpandOptions
|
||||||
if len(options) > 0 {
|
if len(options) > 0 {
|
||||||
expandOptions = options[0]
|
expandOptions = options[0]
|
||||||
|
if expandOptions.RelativeBase == "" {
|
||||||
|
expandOptions.RelativeBase = d.specFilePath
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
expandOptions = &spec.ExpandOptions{
|
expandOptions = &spec.ExpandOptions{
|
||||||
RelativeBase: d.specFilePath,
|
RelativeBase: d.specFilePath,
|
||||||
|
@ -194,7 +200,7 @@ func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) {
|
||||||
return dd, nil
|
return dd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BasePath the base path for this spec
|
// BasePath the base path for the API specified by this spec
|
||||||
func (d *Document) BasePath() string {
|
func (d *Document) BasePath() string {
|
||||||
return d.spec.BasePath
|
return d.spec.BasePath
|
||||||
}
|
}
|
||||||
|
@ -242,8 +248,11 @@ func (d *Document) ResetDefinitions() *Document {
|
||||||
|
|
||||||
// Pristine creates a new pristine document instance based on the input data
|
// Pristine creates a new pristine document instance based on the input data
|
||||||
func (d *Document) Pristine() *Document {
|
func (d *Document) Pristine() *Document {
|
||||||
dd, _ := Analyzed(d.Raw(), d.Version())
|
raw, _ := json.Marshal(d.Spec())
|
||||||
|
dd, _ := Analyzed(raw, d.Version())
|
||||||
dd.pathLoader = d.pathLoader
|
dd.pathLoader = d.pathLoader
|
||||||
|
dd.specFilePath = d.specFilePath
|
||||||
|
|
||||||
return dd
|
return dd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,44 +1,62 @@
|
||||||
linters-settings:
|
linters-settings:
|
||||||
govet:
|
govet:
|
||||||
# Using err repeatedly considered as shadowing.
|
check-shadowing: true
|
||||||
check-shadowing: false
|
|
||||||
golint:
|
golint:
|
||||||
min-confidence: 0
|
min-confidence: 0
|
||||||
gocyclo:
|
gocyclo:
|
||||||
min-complexity: 30
|
min-complexity: 45
|
||||||
maligned:
|
maligned:
|
||||||
suggest-new: true
|
suggest-new: true
|
||||||
dupl:
|
dupl:
|
||||||
threshold: 100
|
threshold: 200
|
||||||
goconst:
|
goconst:
|
||||||
min-len: 2
|
min-len: 2
|
||||||
min-occurrences: 4
|
min-occurrences: 3
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
|
enable-all: true
|
||||||
disable:
|
disable:
|
||||||
|
- nilerr # nilerr crashes on this repo
|
||||||
- maligned
|
- maligned
|
||||||
|
- unparam
|
||||||
- lll
|
- lll
|
||||||
|
- gochecknoinits
|
||||||
- gochecknoglobals
|
- gochecknoglobals
|
||||||
|
- funlen
|
||||||
- godox
|
- godox
|
||||||
- gocognit
|
- gocognit
|
||||||
- whitespace
|
- whitespace
|
||||||
- wsl
|
- wsl
|
||||||
- funlen
|
|
||||||
- gochecknoglobals
|
|
||||||
- gochecknoinits
|
|
||||||
- scopelint
|
|
||||||
- wrapcheck
|
- wrapcheck
|
||||||
- exhaustivestruct
|
|
||||||
- exhaustive
|
|
||||||
- nlreturn
|
|
||||||
- testpackage
|
- testpackage
|
||||||
- gci
|
- nlreturn
|
||||||
- gofumpt
|
|
||||||
- goerr113
|
|
||||||
- gomnd
|
- gomnd
|
||||||
- tparallel
|
- exhaustivestruct
|
||||||
|
- goerr113
|
||||||
|
- errorlint
|
||||||
- nestif
|
- nestif
|
||||||
- godot
|
- godot
|
||||||
- errorlint
|
- gofumpt
|
||||||
- noctx
|
- paralleltest
|
||||||
|
- tparallel
|
||||||
|
- thelper
|
||||||
|
- ifshort
|
||||||
|
- exhaustruct
|
||||||
|
- varnamelen
|
||||||
|
- gci
|
||||||
|
- depguard
|
||||||
|
- errchkjson
|
||||||
|
- inamedparam
|
||||||
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
|
- ireturn
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
# deprecated linters
|
||||||
|
- deadcode
|
||||||
- interfacer
|
- interfacer
|
||||||
- nilerr
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
|
- nosnakecase
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
# runtime [![Build Status](https://travis-ci.org/go-openapi/runtime.svg?branch=client-context)](https://travis-ci.org/go-openapi/runtime) [![codecov](https://codecov.io/gh/go-openapi/runtime/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/runtime) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
# runtime [![Build Status](https://github.com/go-openapi/runtime/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/runtime/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/runtime/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/runtime)
|
||||||
|
|
||||||
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/runtime/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/runtime?status.svg)](http://godoc.org/github.com/go-openapi/runtime)
|
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
||||||
|
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/runtime/master/LICENSE)
|
||||||
|
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/runtime.svg)](https://pkg.go.dev/github.com/go-openapi/runtime)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/runtime)](https://goreportcard.com/report/github.com/go-openapi/runtime)
|
||||||
|
|
||||||
# golang Open-API toolkit - runtime
|
# go OpenAPI toolkit runtime
|
||||||
|
|
||||||
The runtime component for use in codegeneration or as untyped usage.
|
The runtime component for use in code generation or as untyped usage.
|
||||||
|
|
|
@ -38,9 +38,16 @@ type byteStreamOpts struct {
|
||||||
Close bool
|
Close bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByteStreamConsumer creates a consumer for byte streams,
|
// ByteStreamConsumer creates a consumer for byte streams.
|
||||||
// takes a Writer/BinaryUnmarshaler interface or binary slice by reference,
|
//
|
||||||
// and reads from the provided reader
|
// The consumer consumes from a provided reader into the data passed by reference.
|
||||||
|
//
|
||||||
|
// Supported output underlying types and interfaces, prioritized in this order:
|
||||||
|
// - io.ReaderFrom (for maximum control)
|
||||||
|
// - io.Writer (performs io.Copy)
|
||||||
|
// - encoding.BinaryUnmarshaler
|
||||||
|
// - *string
|
||||||
|
// - *[]byte
|
||||||
func ByteStreamConsumer(opts ...byteStreamOpt) Consumer {
|
func ByteStreamConsumer(opts ...byteStreamOpt) Consumer {
|
||||||
var vals byteStreamOpts
|
var vals byteStreamOpts
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
|
@ -51,44 +58,70 @@ func ByteStreamConsumer(opts ...byteStreamOpt) Consumer {
|
||||||
if reader == nil {
|
if reader == nil {
|
||||||
return errors.New("ByteStreamConsumer requires a reader") // early exit
|
return errors.New("ByteStreamConsumer requires a reader") // early exit
|
||||||
}
|
}
|
||||||
|
if data == nil {
|
||||||
|
return errors.New("nil destination for ByteStreamConsumer")
|
||||||
|
}
|
||||||
|
|
||||||
close := defaultCloser
|
closer := defaultCloser
|
||||||
if vals.Close {
|
if vals.Close {
|
||||||
if cl, ok := reader.(io.Closer); ok {
|
if cl, isReaderCloser := reader.(io.Closer); isReaderCloser {
|
||||||
close = cl.Close
|
closer = cl.Close
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//nolint:errcheck // closing a reader wouldn't fail.
|
defer func() {
|
||||||
defer close()
|
_ = closer()
|
||||||
|
}()
|
||||||
|
|
||||||
if wrtr, ok := data.(io.Writer); ok {
|
if readerFrom, isReaderFrom := data.(io.ReaderFrom); isReaderFrom {
|
||||||
_, err := io.Copy(wrtr, reader)
|
_, err := readerFrom.ReadFrom(reader)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
if writer, isDataWriter := data.(io.Writer); isDataWriter {
|
||||||
|
_, err := io.Copy(writer, reader)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// buffers input before writing to data
|
||||||
|
var buf bytes.Buffer
|
||||||
_, err := buf.ReadFrom(reader)
|
_, err := buf.ReadFrom(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b := buf.Bytes()
|
b := buf.Bytes()
|
||||||
|
|
||||||
if bu, ok := data.(encoding.BinaryUnmarshaler); ok {
|
switch destinationPointer := data.(type) {
|
||||||
return bu.UnmarshalBinary(b)
|
case encoding.BinaryUnmarshaler:
|
||||||
}
|
return destinationPointer.UnmarshalBinary(b)
|
||||||
|
case *any:
|
||||||
|
switch (*destinationPointer).(type) {
|
||||||
|
case string:
|
||||||
|
*destinationPointer = string(b)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case []byte:
|
||||||
|
*destinationPointer = b
|
||||||
|
|
||||||
if data != nil {
|
|
||||||
if str, ok := data.(*string); ok {
|
|
||||||
*str = string(b)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
default:
|
||||||
|
// check for the underlying type to be pointer to []byte or string,
|
||||||
|
if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Ptr {
|
||||||
|
return errors.New("destination must be a pointer")
|
||||||
|
}
|
||||||
|
|
||||||
if t := reflect.TypeOf(data); data != nil && t.Kind() == reflect.Ptr {
|
|
||||||
v := reflect.Indirect(reflect.ValueOf(data))
|
v := reflect.Indirect(reflect.ValueOf(data))
|
||||||
if t = v.Type(); t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 {
|
t := v.Type()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
|
||||||
v.SetBytes(b)
|
v.SetBytes(b)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
case t.Kind() == reflect.String:
|
||||||
|
v.SetString(string(b))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,67 +130,87 @@ func ByteStreamConsumer(opts ...byteStreamOpt) Consumer {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByteStreamProducer creates a producer for byte streams,
|
// ByteStreamProducer creates a producer for byte streams.
|
||||||
// takes a Reader/BinaryMarshaler interface or binary slice,
|
//
|
||||||
// and writes to a writer (essentially a pipe)
|
// The producer takes input data then writes to an output writer (essentially as a pipe).
|
||||||
|
//
|
||||||
|
// Supported input underlying types and interfaces, prioritized in this order:
|
||||||
|
// - io.WriterTo (for maximum control)
|
||||||
|
// - io.Reader (performs io.Copy). A ReadCloser is closed before exiting.
|
||||||
|
// - encoding.BinaryMarshaler
|
||||||
|
// - error (writes as a string)
|
||||||
|
// - []byte
|
||||||
|
// - string
|
||||||
|
// - struct, other slices: writes as JSON
|
||||||
func ByteStreamProducer(opts ...byteStreamOpt) Producer {
|
func ByteStreamProducer(opts ...byteStreamOpt) Producer {
|
||||||
var vals byteStreamOpts
|
var vals byteStreamOpts
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(&vals)
|
opt(&vals)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ProducerFunc(func(writer io.Writer, data interface{}) error {
|
return ProducerFunc(func(writer io.Writer, data interface{}) error {
|
||||||
if writer == nil {
|
if writer == nil {
|
||||||
return errors.New("ByteStreamProducer requires a writer") // early exit
|
return errors.New("ByteStreamProducer requires a writer") // early exit
|
||||||
}
|
}
|
||||||
close := defaultCloser
|
if data == nil {
|
||||||
|
return errors.New("nil data for ByteStreamProducer")
|
||||||
|
}
|
||||||
|
|
||||||
|
closer := defaultCloser
|
||||||
if vals.Close {
|
if vals.Close {
|
||||||
if cl, ok := writer.(io.Closer); ok {
|
if cl, isWriterCloser := writer.(io.Closer); isWriterCloser {
|
||||||
close = cl.Close
|
closer = cl.Close
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//nolint:errcheck // TODO: closing a writer would fail.
|
defer func() {
|
||||||
defer close()
|
_ = closer()
|
||||||
|
}()
|
||||||
|
|
||||||
if rc, ok := data.(io.ReadCloser); ok {
|
if rc, isDataCloser := data.(io.ReadCloser); isDataCloser {
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if rdr, ok := data.(io.Reader); ok {
|
switch origin := data.(type) {
|
||||||
_, err := io.Copy(writer, rdr)
|
case io.WriterTo:
|
||||||
|
_, err := origin.WriteTo(writer)
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
if bm, ok := data.(encoding.BinaryMarshaler); ok {
|
case io.Reader:
|
||||||
bytes, err := bm.MarshalBinary()
|
_, err := io.Copy(writer, origin)
|
||||||
|
return err
|
||||||
|
|
||||||
|
case encoding.BinaryMarshaler:
|
||||||
|
bytes, err := origin.MarshalBinary()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = writer.Write(bytes)
|
_, err = writer.Write(bytes)
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
if data != nil {
|
case error:
|
||||||
if str, ok := data.(string); ok {
|
_, err := writer.Write([]byte(origin.Error()))
|
||||||
_, err := writer.Write([]byte(str))
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if e, ok := data.(error); ok {
|
|
||||||
_, err := writer.Write([]byte(e.Error()))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
default:
|
||||||
v := reflect.Indirect(reflect.ValueOf(data))
|
v := reflect.Indirect(reflect.ValueOf(data))
|
||||||
if t := v.Type(); t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 {
|
t := v.Type()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
|
||||||
_, err := writer.Write(v.Bytes())
|
_, err := writer.Write(v.Bytes())
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
if t := v.Type(); t.Kind() == reflect.Struct || t.Kind() == reflect.Slice {
|
case t.Kind() == reflect.String:
|
||||||
|
_, err := writer.Write([]byte(v.String()))
|
||||||
|
return err
|
||||||
|
|
||||||
|
case t.Kind() == reflect.Struct || t.Kind() == reflect.Slice:
|
||||||
b, err := swag.WriteJSON(data)
|
b, err := swag.WriteJSON(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = writer.Write(b)
|
_, err = writer.Write(b)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,12 @@ type ClientOperation struct {
|
||||||
AuthInfo ClientAuthInfoWriter
|
AuthInfo ClientAuthInfoWriter
|
||||||
Params ClientRequestWriter
|
Params ClientRequestWriter
|
||||||
Reader ClientResponseReader
|
Reader ClientResponseReader
|
||||||
Context context.Context
|
Context context.Context //nolint:containedctx // we precisely want this type to contain the request context
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// A ClientTransport implementor knows how to submit Request objects to some destination
|
// A ClientTransport implementor knows how to submit Request objects to some destination
|
||||||
type ClientTransport interface {
|
type ClientTransport interface {
|
||||||
//Submit(string, RequestWriter, ResponseReader, AuthInfoWriter) (interface{}, error)
|
// Submit(string, RequestWriter, ResponseReader, AuthInfoWriter) (interface{}, error)
|
||||||
Submit(*ClientOperation) (interface{}, error)
|
Submit(*ClientOperation) (interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,8 @@ type ClientRequestWriter interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientRequest is an interface for things that know how to
|
// ClientRequest is an interface for things that know how to
|
||||||
// add information to a swagger client request
|
// add information to a swagger client request.
|
||||||
type ClientRequest interface {
|
type ClientRequest interface { //nolint:interfacebloat // a swagger-capable request is quite rich, hence the many getter/setters
|
||||||
SetHeaderParam(string, ...string) error
|
SetHeaderParam(string, ...string) error
|
||||||
|
|
||||||
GetHeaderParams() http.Header
|
GetHeaderParams() http.Header
|
||||||
|
|
|
@ -16,62 +16,335 @@ package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding"
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CSVConsumer creates a new CSV consumer
|
// CSVConsumer creates a new CSV consumer.
|
||||||
func CSVConsumer() Consumer {
|
//
|
||||||
|
// The consumer consumes CSV records from a provided reader into the data passed by reference.
|
||||||
|
//
|
||||||
|
// CSVOpts options may be specified to alter the default CSV behavior on the reader and the writer side (e.g. separator, skip header, ...).
|
||||||
|
// The defaults are those of the standard library's csv.Reader and csv.Writer.
|
||||||
|
//
|
||||||
|
// Supported output underlying types and interfaces, prioritized in this order:
|
||||||
|
// - *csv.Writer
|
||||||
|
// - CSVWriter (writer options are ignored)
|
||||||
|
// - io.Writer (as raw bytes)
|
||||||
|
// - io.ReaderFrom (as raw bytes)
|
||||||
|
// - encoding.BinaryUnmarshaler (as raw bytes)
|
||||||
|
// - *[][]string (as a collection of records)
|
||||||
|
// - *[]byte (as raw bytes)
|
||||||
|
// - *string (a raw bytes)
|
||||||
|
//
|
||||||
|
// The consumer prioritizes situations where buffering the input is not required.
|
||||||
|
func CSVConsumer(opts ...CSVOpt) Consumer {
|
||||||
|
o := csvOptsWithDefaults(opts)
|
||||||
|
|
||||||
return ConsumerFunc(func(reader io.Reader, data interface{}) error {
|
return ConsumerFunc(func(reader io.Reader, data interface{}) error {
|
||||||
if reader == nil {
|
if reader == nil {
|
||||||
return errors.New("CSVConsumer requires a reader")
|
return errors.New("CSVConsumer requires a reader")
|
||||||
}
|
}
|
||||||
|
if data == nil {
|
||||||
|
return errors.New("nil destination for CSVConsumer")
|
||||||
|
}
|
||||||
|
|
||||||
csvReader := csv.NewReader(reader)
|
csvReader := csv.NewReader(reader)
|
||||||
writer, ok := data.(io.Writer)
|
o.applyToReader(csvReader)
|
||||||
if !ok {
|
closer := defaultCloser
|
||||||
return errors.New("data type must be io.Writer")
|
if o.closeStream {
|
||||||
}
|
if cl, isReaderCloser := reader.(io.Closer); isReaderCloser {
|
||||||
csvWriter := csv.NewWriter(writer)
|
closer = cl.Close
|
||||||
records, err := csvReader.ReadAll()
|
}
|
||||||
if err != nil {
|
}
|
||||||
return err
|
defer func() {
|
||||||
}
|
_ = closer()
|
||||||
for _, r := range records {
|
}()
|
||||||
if err := csvWriter.Write(r); err != nil {
|
|
||||||
return err
|
switch destination := data.(type) {
|
||||||
|
case *csv.Writer:
|
||||||
|
csvWriter := destination
|
||||||
|
o.applyToWriter(csvWriter)
|
||||||
|
|
||||||
|
return pipeCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
case CSVWriter:
|
||||||
|
csvWriter := destination
|
||||||
|
// no writer options available
|
||||||
|
|
||||||
|
return pipeCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
case io.Writer:
|
||||||
|
csvWriter := csv.NewWriter(destination)
|
||||||
|
o.applyToWriter(csvWriter)
|
||||||
|
|
||||||
|
return pipeCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
case io.ReaderFrom:
|
||||||
|
var buf bytes.Buffer
|
||||||
|
csvWriter := csv.NewWriter(&buf)
|
||||||
|
o.applyToWriter(csvWriter)
|
||||||
|
if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := destination.ReadFrom(&buf)
|
||||||
|
|
||||||
|
return err
|
||||||
|
|
||||||
|
case encoding.BinaryUnmarshaler:
|
||||||
|
var buf bytes.Buffer
|
||||||
|
csvWriter := csv.NewWriter(&buf)
|
||||||
|
o.applyToWriter(csvWriter)
|
||||||
|
if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return destination.UnmarshalBinary(buf.Bytes())
|
||||||
|
|
||||||
|
default:
|
||||||
|
// support *[][]string, *[]byte, *string
|
||||||
|
if ptr := reflect.TypeOf(data); ptr.Kind() != reflect.Ptr {
|
||||||
|
return errors.New("destination must be a pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
v := reflect.Indirect(reflect.ValueOf(data))
|
||||||
|
t := v.Type()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Slice && t.Elem().Elem().Kind() == reflect.String:
|
||||||
|
csvWriter := &csvRecordsWriter{}
|
||||||
|
// writer options are ignored
|
||||||
|
if err := pipeCSV(csvWriter, csvReader, o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Grow(len(csvWriter.records))
|
||||||
|
v.SetCap(len(csvWriter.records)) // in case Grow was unnessary, trim down the capacity
|
||||||
|
v.SetLen(len(csvWriter.records))
|
||||||
|
reflect.Copy(v, reflect.ValueOf(csvWriter.records))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
|
||||||
|
var buf bytes.Buffer
|
||||||
|
csvWriter := csv.NewWriter(&buf)
|
||||||
|
o.applyToWriter(csvWriter)
|
||||||
|
if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.SetBytes(buf.Bytes())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case t.Kind() == reflect.String:
|
||||||
|
var buf bytes.Buffer
|
||||||
|
csvWriter := csv.NewWriter(&buf)
|
||||||
|
o.applyToWriter(csvWriter)
|
||||||
|
if err := bufferedCSV(csvWriter, csvReader, o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.SetString(buf.String())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%v (%T) is not supported by the CSVConsumer, %s",
|
||||||
|
data, data, "can be resolved by supporting CSVWriter/Writer/BinaryUnmarshaler interface",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
csvWriter.Flush()
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSVProducer creates a new CSV producer
|
// CSVProducer creates a new CSV producer.
|
||||||
func CSVProducer() Producer {
|
//
|
||||||
|
// The producer takes input data then writes as CSV to an output writer (essentially as a pipe).
|
||||||
|
//
|
||||||
|
// Supported input underlying types and interfaces, prioritized in this order:
|
||||||
|
// - *csv.Reader
|
||||||
|
// - CSVReader (reader options are ignored)
|
||||||
|
// - io.Reader
|
||||||
|
// - io.WriterTo
|
||||||
|
// - encoding.BinaryMarshaler
|
||||||
|
// - [][]string
|
||||||
|
// - []byte
|
||||||
|
// - string
|
||||||
|
//
|
||||||
|
// The producer prioritizes situations where buffering the input is not required.
|
||||||
|
func CSVProducer(opts ...CSVOpt) Producer {
|
||||||
|
o := csvOptsWithDefaults(opts)
|
||||||
|
|
||||||
return ProducerFunc(func(writer io.Writer, data interface{}) error {
|
return ProducerFunc(func(writer io.Writer, data interface{}) error {
|
||||||
if writer == nil {
|
if writer == nil {
|
||||||
return errors.New("CSVProducer requires a writer")
|
return errors.New("CSVProducer requires a writer")
|
||||||
}
|
}
|
||||||
|
if data == nil {
|
||||||
dataBytes, ok := data.([]byte)
|
return errors.New("nil data for CSVProducer")
|
||||||
if !ok {
|
|
||||||
return errors.New("data type must be byte array")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
csvReader := csv.NewReader(bytes.NewBuffer(dataBytes))
|
|
||||||
records, err := csvReader.ReadAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
csvWriter := csv.NewWriter(writer)
|
csvWriter := csv.NewWriter(writer)
|
||||||
for _, r := range records {
|
o.applyToWriter(csvWriter)
|
||||||
if err := csvWriter.Write(r); err != nil {
|
closer := defaultCloser
|
||||||
return err
|
if o.closeStream {
|
||||||
|
if cl, isWriterCloser := writer.(io.Closer); isWriterCloser {
|
||||||
|
closer = cl.Close
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = closer()
|
||||||
|
}()
|
||||||
|
|
||||||
|
if rc, isDataCloser := data.(io.ReadCloser); isDataCloser {
|
||||||
|
defer rc.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch origin := data.(type) {
|
||||||
|
case *csv.Reader:
|
||||||
|
csvReader := origin
|
||||||
|
o.applyToReader(csvReader)
|
||||||
|
|
||||||
|
return pipeCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
case CSVReader:
|
||||||
|
csvReader := origin
|
||||||
|
// no reader options available
|
||||||
|
|
||||||
|
return pipeCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
case io.Reader:
|
||||||
|
csvReader := csv.NewReader(origin)
|
||||||
|
o.applyToReader(csvReader)
|
||||||
|
|
||||||
|
return pipeCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
case io.WriterTo:
|
||||||
|
// async piping of the writes performed by WriteTo
|
||||||
|
r, w := io.Pipe()
|
||||||
|
csvReader := csv.NewReader(r)
|
||||||
|
o.applyToReader(csvReader)
|
||||||
|
|
||||||
|
pipe, _ := errgroup.WithContext(context.Background())
|
||||||
|
pipe.Go(func() error {
|
||||||
|
_, err := origin.WriteTo(w)
|
||||||
|
_ = w.Close()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
pipe.Go(func() error {
|
||||||
|
defer func() {
|
||||||
|
_ = r.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return pipeCSV(csvWriter, csvReader, o)
|
||||||
|
})
|
||||||
|
|
||||||
|
return pipe.Wait()
|
||||||
|
|
||||||
|
case encoding.BinaryMarshaler:
|
||||||
|
buf, err := origin.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rdr := bytes.NewBuffer(buf)
|
||||||
|
csvReader := csv.NewReader(rdr)
|
||||||
|
|
||||||
|
return bufferedCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
default:
|
||||||
|
// support [][]string, []byte, string (or pointers to those)
|
||||||
|
v := reflect.Indirect(reflect.ValueOf(data))
|
||||||
|
t := v.Type()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Slice && t.Elem().Elem().Kind() == reflect.String:
|
||||||
|
csvReader := &csvRecordsWriter{
|
||||||
|
records: make([][]string, v.Len()),
|
||||||
|
}
|
||||||
|
reflect.Copy(reflect.ValueOf(csvReader.records), v)
|
||||||
|
|
||||||
|
return pipeCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
case t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8:
|
||||||
|
buf := bytes.NewBuffer(v.Bytes())
|
||||||
|
csvReader := csv.NewReader(buf)
|
||||||
|
o.applyToReader(csvReader)
|
||||||
|
|
||||||
|
return bufferedCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
case t.Kind() == reflect.String:
|
||||||
|
buf := bytes.NewBufferString(v.String())
|
||||||
|
csvReader := csv.NewReader(buf)
|
||||||
|
o.applyToReader(csvReader)
|
||||||
|
|
||||||
|
return bufferedCSV(csvWriter, csvReader, o)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%v (%T) is not supported by the CSVProducer, %s",
|
||||||
|
data, data, "can be resolved by supporting CSVReader/Reader/BinaryMarshaler interface",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
csvWriter.Flush()
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pipeCSV copies CSV records from a CSV reader to a CSV writer
|
||||||
|
func pipeCSV(csvWriter CSVWriter, csvReader CSVReader, opts csvOpts) error {
|
||||||
|
for ; opts.skippedLines > 0; opts.skippedLines-- {
|
||||||
|
_, err := csvReader.Read()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
record, err := csvReader.Read()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := csvWriter.Write(record); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
csvWriter.Flush()
|
||||||
|
|
||||||
|
return csvWriter.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// bufferedCSV copies CSV records from a CSV reader to a CSV writer,
|
||||||
|
// by first reading all records then writing them at once.
|
||||||
|
func bufferedCSV(csvWriter *csv.Writer, csvReader *csv.Reader, opts csvOpts) error {
|
||||||
|
for ; opts.skippedLines > 0; opts.skippedLines-- {
|
||||||
|
_, err := csvReader.Read()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
records, err := csvReader.ReadAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return csvWriter.WriteAll(records)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CSVOpts alter the behavior of the CSV consumer or producer.
|
||||||
|
type CSVOpt func(*csvOpts)
|
||||||
|
|
||||||
|
type csvOpts struct {
|
||||||
|
csvReader csv.Reader
|
||||||
|
csvWriter csv.Writer
|
||||||
|
skippedLines int
|
||||||
|
closeStream bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCSVReaderOpts specifies the options to csv.Reader
|
||||||
|
// when reading CSV.
|
||||||
|
func WithCSVReaderOpts(reader csv.Reader) CSVOpt {
|
||||||
|
return func(o *csvOpts) {
|
||||||
|
o.csvReader = reader
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCSVWriterOpts specifies the options to csv.Writer
|
||||||
|
// when writing CSV.
|
||||||
|
func WithCSVWriterOpts(writer csv.Writer) CSVOpt {
|
||||||
|
return func(o *csvOpts) {
|
||||||
|
o.csvWriter = writer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCSVSkipLines will skip header lines.
|
||||||
|
func WithCSVSkipLines(skipped int) CSVOpt {
|
||||||
|
return func(o *csvOpts) {
|
||||||
|
o.skippedLines = skipped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithCSVClosesStream() CSVOpt {
|
||||||
|
return func(o *csvOpts) {
|
||||||
|
o.closeStream = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o csvOpts) applyToReader(in *csv.Reader) {
|
||||||
|
if o.csvReader.Comma != 0 {
|
||||||
|
in.Comma = o.csvReader.Comma
|
||||||
|
}
|
||||||
|
if o.csvReader.Comment != 0 {
|
||||||
|
in.Comment = o.csvReader.Comment
|
||||||
|
}
|
||||||
|
if o.csvReader.FieldsPerRecord != 0 {
|
||||||
|
in.FieldsPerRecord = o.csvReader.FieldsPerRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
in.LazyQuotes = o.csvReader.LazyQuotes
|
||||||
|
in.TrimLeadingSpace = o.csvReader.TrimLeadingSpace
|
||||||
|
in.ReuseRecord = o.csvReader.ReuseRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o csvOpts) applyToWriter(in *csv.Writer) {
|
||||||
|
if o.csvWriter.Comma != 0 {
|
||||||
|
in.Comma = o.csvWriter.Comma
|
||||||
|
}
|
||||||
|
in.UseCRLF = o.csvWriter.UseCRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func csvOptsWithDefaults(opts []CSVOpt) csvOpts {
|
||||||
|
var o csvOpts
|
||||||
|
for _, apply := range opts {
|
||||||
|
apply(&o)
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
type CSVWriter interface {
|
||||||
|
Write([]string) error
|
||||||
|
Flush()
|
||||||
|
Error() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type CSVReader interface {
|
||||||
|
Read() ([]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ CSVWriter = &csvRecordsWriter{}
|
||||||
|
_ CSVReader = &csvRecordsWriter{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// csvRecordsWriter is an internal container to move CSV records back and forth
|
||||||
|
type csvRecordsWriter struct {
|
||||||
|
i int
|
||||||
|
records [][]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *csvRecordsWriter) Write(record []string) error {
|
||||||
|
w.records = append(w.records, record)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *csvRecordsWriter) Read() ([]string, error) {
|
||||||
|
if w.i >= len(w.records) {
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
w.i++
|
||||||
|
}()
|
||||||
|
|
||||||
|
return w.records[w.i], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *csvRecordsWriter) Flush() {}
|
||||||
|
|
||||||
|
func (w *csvRecordsWriter) Error() error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ Logger = StandardLogger{}
|
||||||
|
|
||||||
type StandardLogger struct{}
|
type StandardLogger struct{}
|
||||||
|
|
||||||
func (StandardLogger) Printf(format string, args ...interface{}) {
|
func (StandardLogger) Printf(format string, args ...interface{}) {
|
||||||
|
|
|
@ -18,6 +18,8 @@ import (
|
||||||
stdContext "context"
|
stdContext "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
@ -35,12 +37,21 @@ import (
|
||||||
|
|
||||||
// Debug when true turns on verbose logging
|
// Debug when true turns on verbose logging
|
||||||
var Debug = logger.DebugEnabled()
|
var Debug = logger.DebugEnabled()
|
||||||
|
|
||||||
|
// Logger is the standard libray logger used for printing debug messages
|
||||||
var Logger logger.Logger = logger.StandardLogger{}
|
var Logger logger.Logger = logger.StandardLogger{}
|
||||||
|
|
||||||
func debugLog(format string, args ...interface{}) {
|
func debugLogfFunc(lg logger.Logger) func(string, ...any) {
|
||||||
if Debug {
|
if logger.DebugEnabled() {
|
||||||
Logger.Printf(format, args...)
|
if lg == nil {
|
||||||
|
return Logger.Debugf
|
||||||
|
}
|
||||||
|
|
||||||
|
return lg.Debugf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// muted logger
|
||||||
|
return func(_ string, _ ...any) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Builder can create middlewares
|
// A Builder can create middlewares
|
||||||
|
@ -73,10 +84,11 @@ func (fn ResponderFunc) WriteResponse(rw http.ResponseWriter, pr runtime.Produce
|
||||||
// used throughout to store request context with the standard context attached
|
// used throughout to store request context with the standard context attached
|
||||||
// to the http.Request
|
// to the http.Request
|
||||||
type Context struct {
|
type Context struct {
|
||||||
spec *loads.Document
|
spec *loads.Document
|
||||||
analyzer *analysis.Spec
|
analyzer *analysis.Spec
|
||||||
api RoutableAPI
|
api RoutableAPI
|
||||||
router Router
|
router Router
|
||||||
|
debugLogf func(string, ...any) // a logging function to debug context and all components using it
|
||||||
}
|
}
|
||||||
|
|
||||||
type routableUntypedAPI struct {
|
type routableUntypedAPI struct {
|
||||||
|
@ -162,7 +174,7 @@ func (r *routableUntypedAPI) HandlerFor(method, path string) (http.Handler, bool
|
||||||
r.hlock.Unlock()
|
r.hlock.Unlock()
|
||||||
return handler, ok
|
return handler, ok
|
||||||
}
|
}
|
||||||
func (r *routableUntypedAPI) ServeErrorFor(operationID string) func(http.ResponseWriter, *http.Request, error) {
|
func (r *routableUntypedAPI) ServeErrorFor(_ string) func(http.ResponseWriter, *http.Request, error) {
|
||||||
return r.api.ServeError
|
return r.api.ServeError
|
||||||
}
|
}
|
||||||
func (r *routableUntypedAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
|
func (r *routableUntypedAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
|
||||||
|
@ -189,7 +201,9 @@ func (r *routableUntypedAPI) DefaultConsumes() string {
|
||||||
return r.defaultConsumes
|
return r.defaultConsumes
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRoutableContext creates a new context for a routable API
|
// NewRoutableContext creates a new context for a routable API.
|
||||||
|
//
|
||||||
|
// If a nil Router is provided, the DefaultRouter (denco-based) will be used.
|
||||||
func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Router) *Context {
|
func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Router) *Context {
|
||||||
var an *analysis.Spec
|
var an *analysis.Spec
|
||||||
if spec != nil {
|
if spec != nil {
|
||||||
|
@ -199,26 +213,40 @@ func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Ro
|
||||||
return NewRoutableContextWithAnalyzedSpec(spec, an, routableAPI, routes)
|
return NewRoutableContextWithAnalyzedSpec(spec, an, routableAPI, routes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRoutableContextWithAnalyzedSpec is like NewRoutableContext but takes in input the analysed spec too
|
// NewRoutableContextWithAnalyzedSpec is like NewRoutableContext but takes as input an already analysed spec.
|
||||||
|
//
|
||||||
|
// If a nil Router is provided, the DefaultRouter (denco-based) will be used.
|
||||||
func NewRoutableContextWithAnalyzedSpec(spec *loads.Document, an *analysis.Spec, routableAPI RoutableAPI, routes Router) *Context {
|
func NewRoutableContextWithAnalyzedSpec(spec *loads.Document, an *analysis.Spec, routableAPI RoutableAPI, routes Router) *Context {
|
||||||
// Either there are no spec doc and analysis, or both of them.
|
// Either there are no spec doc and analysis, or both of them.
|
||||||
if !((spec == nil && an == nil) || (spec != nil && an != nil)) {
|
if !((spec == nil && an == nil) || (spec != nil && an != nil)) {
|
||||||
panic(errors.New(http.StatusInternalServerError, "routable context requires either both spec doc and analysis, or none of them"))
|
panic(errors.New(http.StatusInternalServerError, "routable context requires either both spec doc and analysis, or none of them"))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := &Context{spec: spec, api: routableAPI, analyzer: an, router: routes}
|
return &Context{
|
||||||
return ctx
|
spec: spec,
|
||||||
|
api: routableAPI,
|
||||||
|
analyzer: an,
|
||||||
|
router: routes,
|
||||||
|
debugLogf: debugLogfFunc(nil),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext creates a new context wrapper
|
// NewContext creates a new context wrapper.
|
||||||
|
//
|
||||||
|
// If a nil Router is provided, the DefaultRouter (denco-based) will be used.
|
||||||
func NewContext(spec *loads.Document, api *untyped.API, routes Router) *Context {
|
func NewContext(spec *loads.Document, api *untyped.API, routes Router) *Context {
|
||||||
var an *analysis.Spec
|
var an *analysis.Spec
|
||||||
if spec != nil {
|
if spec != nil {
|
||||||
an = analysis.New(spec.Spec())
|
an = analysis.New(spec.Spec())
|
||||||
}
|
}
|
||||||
ctx := &Context{spec: spec, analyzer: an}
|
ctx := &Context{
|
||||||
|
spec: spec,
|
||||||
|
analyzer: an,
|
||||||
|
router: routes,
|
||||||
|
debugLogf: debugLogfFunc(nil),
|
||||||
|
}
|
||||||
ctx.api = newRoutableUntypedAPI(spec, api, ctx)
|
ctx.api = newRoutableUntypedAPI(spec, api, ctx)
|
||||||
ctx.router = routes
|
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,6 +310,13 @@ func (c *Context) BasePath() string {
|
||||||
return c.spec.BasePath()
|
return c.spec.BasePath()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLogger allows for injecting a logger to catch debug entries.
|
||||||
|
//
|
||||||
|
// The logger is enabled in DEBUG mode only.
|
||||||
|
func (c *Context) SetLogger(lg logger.Logger) {
|
||||||
|
c.debugLogf = debugLogfFunc(lg)
|
||||||
|
}
|
||||||
|
|
||||||
// RequiredProduces returns the accepted content types for responses
|
// RequiredProduces returns the accepted content types for responses
|
||||||
func (c *Context) RequiredProduces() []string {
|
func (c *Context) RequiredProduces() []string {
|
||||||
return c.analyzer.RequiredProduces()
|
return c.analyzer.RequiredProduces()
|
||||||
|
@ -299,6 +334,7 @@ func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
} else {
|
} else {
|
||||||
|
c.debugLogf("validating content type for %q against [%s]", ct, strings.Join(route.Consumes, ", "))
|
||||||
if err := validateContentType(route.Consumes, ct); err != nil {
|
if err := validateContentType(route.Consumes, ct); err != nil {
|
||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
@ -397,16 +433,16 @@ func (c *Context) ResponseFormat(r *http.Request, offers []string) (string, *htt
|
||||||
var rCtx = r.Context()
|
var rCtx = r.Context()
|
||||||
|
|
||||||
if v, ok := rCtx.Value(ctxResponseFormat).(string); ok {
|
if v, ok := rCtx.Value(ctxResponseFormat).(string); ok {
|
||||||
debugLog("[%s %s] found response format %q in context", r.Method, r.URL.Path, v)
|
c.debugLogf("[%s %s] found response format %q in context", r.Method, r.URL.Path, v)
|
||||||
return v, r
|
return v, r
|
||||||
}
|
}
|
||||||
|
|
||||||
format := NegotiateContentType(r, offers, "")
|
format := NegotiateContentType(r, offers, "")
|
||||||
if format != "" {
|
if format != "" {
|
||||||
debugLog("[%s %s] set response format %q in context", r.Method, r.URL.Path, format)
|
c.debugLogf("[%s %s] set response format %q in context", r.Method, r.URL.Path, format)
|
||||||
r = r.WithContext(stdContext.WithValue(rCtx, ctxResponseFormat, format))
|
r = r.WithContext(stdContext.WithValue(rCtx, ctxResponseFormat, format))
|
||||||
}
|
}
|
||||||
debugLog("[%s %s] negotiated response format %q", r.Method, r.URL.Path, format)
|
c.debugLogf("[%s %s] negotiated response format %q", r.Method, r.URL.Path, format)
|
||||||
return format, r
|
return format, r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,7 +505,7 @@ func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute)
|
||||||
var rCtx = request.Context()
|
var rCtx = request.Context()
|
||||||
|
|
||||||
if v, ok := rCtx.Value(ctxBoundParams).(*validation); ok {
|
if v, ok := rCtx.Value(ctxBoundParams).(*validation); ok {
|
||||||
debugLog("got cached validation (valid: %t)", len(v.result) == 0)
|
c.debugLogf("got cached validation (valid: %t)", len(v.result) == 0)
|
||||||
if len(v.result) > 0 {
|
if len(v.result) > 0 {
|
||||||
return v.bound, request, errors.CompositeValidationError(v.result...)
|
return v.bound, request, errors.CompositeValidationError(v.result...)
|
||||||
}
|
}
|
||||||
|
@ -481,7 +517,7 @@ func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute)
|
||||||
if len(result.result) > 0 {
|
if len(result.result) > 0 {
|
||||||
return result.bound, request, errors.CompositeValidationError(result.result...)
|
return result.bound, request, errors.CompositeValidationError(result.result...)
|
||||||
}
|
}
|
||||||
debugLog("no validation errors found")
|
c.debugLogf("no validation errors found")
|
||||||
return result.bound, request, nil
|
return result.bound, request, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,7 +528,7 @@ func (c *Context) NotFound(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// Respond renders the response after doing some content negotiation
|
// Respond renders the response after doing some content negotiation
|
||||||
func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []string, route *MatchedRoute, data interface{}) {
|
func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []string, route *MatchedRoute, data interface{}) {
|
||||||
debugLog("responding to %s %s with produces: %v", r.Method, r.URL.Path, produces)
|
c.debugLogf("responding to %s %s with produces: %v", r.Method, r.URL.Path, produces)
|
||||||
offers := []string{}
|
offers := []string{}
|
||||||
for _, mt := range produces {
|
for _, mt := range produces {
|
||||||
if mt != c.api.DefaultProduces() {
|
if mt != c.api.DefaultProduces() {
|
||||||
|
@ -501,7 +537,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
|
||||||
}
|
}
|
||||||
// the default producer is last so more specific producers take precedence
|
// the default producer is last so more specific producers take precedence
|
||||||
offers = append(offers, c.api.DefaultProduces())
|
offers = append(offers, c.api.DefaultProduces())
|
||||||
debugLog("offers: %v", offers)
|
c.debugLogf("offers: %v", offers)
|
||||||
|
|
||||||
var format string
|
var format string
|
||||||
format, r = c.ResponseFormat(r, offers)
|
format, r = c.ResponseFormat(r, offers)
|
||||||
|
@ -516,7 +552,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
|
||||||
prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()}))
|
prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()}))
|
||||||
pr, ok := prods[c.api.DefaultProduces()]
|
pr, ok := prods[c.api.DefaultProduces()]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
|
panic(errors.New(http.StatusInternalServerError, cantFindProducer(format)))
|
||||||
}
|
}
|
||||||
prod = pr
|
prod = pr
|
||||||
}
|
}
|
||||||
|
@ -542,14 +578,14 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
|
||||||
}
|
}
|
||||||
|
|
||||||
if route == nil || route.Operation == nil {
|
if route == nil || route.Operation == nil {
|
||||||
rw.WriteHeader(200)
|
rw.WriteHeader(http.StatusOK)
|
||||||
if r.Method == "HEAD" {
|
if r.Method == http.MethodHead {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
producers := c.api.ProducersFor(normalizeOffers(offers))
|
producers := c.api.ProducersFor(normalizeOffers(offers))
|
||||||
prod, ok := producers[format]
|
prod, ok := producers[format]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
|
panic(errors.New(http.StatusInternalServerError, cantFindProducer(format)))
|
||||||
}
|
}
|
||||||
if err := prod.Produce(rw, data); err != nil {
|
if err := prod.Produce(rw, data); err != nil {
|
||||||
panic(err) // let the recovery middleware deal with this
|
panic(err) // let the recovery middleware deal with this
|
||||||
|
@ -559,7 +595,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
|
||||||
|
|
||||||
if _, code, ok := route.Operation.SuccessResponse(); ok {
|
if _, code, ok := route.Operation.SuccessResponse(); ok {
|
||||||
rw.WriteHeader(code)
|
rw.WriteHeader(code)
|
||||||
if code == 204 || r.Method == "HEAD" {
|
if code == http.StatusNoContent || r.Method == http.MethodHead {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,7 +606,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
|
||||||
prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()}))
|
prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()}))
|
||||||
pr, ok := prods[c.api.DefaultProduces()]
|
pr, ok := prods[c.api.DefaultProduces()]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format))
|
panic(errors.New(http.StatusInternalServerError, cantFindProducer(format)))
|
||||||
}
|
}
|
||||||
prod = pr
|
prod = pr
|
||||||
}
|
}
|
||||||
|
@ -584,45 +620,92 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st
|
||||||
c.api.ServeErrorFor(route.Operation.ID)(rw, r, errors.New(http.StatusInternalServerError, "can't produce response"))
|
c.api.ServeErrorFor(route.Operation.ID)(rw, r, errors.New(http.StatusInternalServerError, "can't produce response"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) APIHandlerSwaggerUI(builder Builder) http.Handler {
|
// APIHandlerSwaggerUI returns a handler to serve the API.
|
||||||
|
//
|
||||||
|
// This handler includes a swagger spec, router and the contract defined in the swagger spec.
|
||||||
|
//
|
||||||
|
// A spec UI (SwaggerUI) is served at {API base path}/docs and the spec document at /swagger.json
|
||||||
|
// (these can be modified with uiOptions).
|
||||||
|
func (c *Context) APIHandlerSwaggerUI(builder Builder, opts ...UIOption) http.Handler {
|
||||||
b := builder
|
b := builder
|
||||||
if b == nil {
|
if b == nil {
|
||||||
b = PassthroughBuilder
|
b = PassthroughBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
var title string
|
specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
|
||||||
sp := c.spec.Spec()
|
var swaggerUIOpts SwaggerUIOpts
|
||||||
if sp != nil && sp.Info != nil && sp.Info.Title != "" {
|
fromCommonToAnyOptions(uiOpts, &swaggerUIOpts)
|
||||||
title = sp.Info.Title
|
|
||||||
}
|
|
||||||
|
|
||||||
swaggerUIOpts := SwaggerUIOpts{
|
return Spec(specPath, c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b)), specOpts...)
|
||||||
BasePath: c.BasePath(),
|
|
||||||
Title: title,
|
|
||||||
}
|
|
||||||
|
|
||||||
return Spec("", c.spec.Raw(), SwaggerUI(swaggerUIOpts, c.RoutesHandler(b)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIHandler returns a handler to serve the API, this includes a swagger spec, router and the contract defined in the swagger spec
|
// APIHandlerRapiDoc returns a handler to serve the API.
|
||||||
func (c *Context) APIHandler(builder Builder) http.Handler {
|
//
|
||||||
|
// This handler includes a swagger spec, router and the contract defined in the swagger spec.
|
||||||
|
//
|
||||||
|
// A spec UI (RapiDoc) is served at {API base path}/docs and the spec document at /swagger.json
|
||||||
|
// (these can be modified with uiOptions).
|
||||||
|
func (c *Context) APIHandlerRapiDoc(builder Builder, opts ...UIOption) http.Handler {
|
||||||
b := builder
|
b := builder
|
||||||
if b == nil {
|
if b == nil {
|
||||||
b = PassthroughBuilder
|
b = PassthroughBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
|
||||||
|
var rapidocUIOpts RapiDocOpts
|
||||||
|
fromCommonToAnyOptions(uiOpts, &rapidocUIOpts)
|
||||||
|
|
||||||
|
return Spec(specPath, c.spec.Raw(), RapiDoc(rapidocUIOpts, c.RoutesHandler(b)), specOpts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIHandler returns a handler to serve the API.
|
||||||
|
//
|
||||||
|
// This handler includes a swagger spec, router and the contract defined in the swagger spec.
|
||||||
|
//
|
||||||
|
// A spec UI (Redoc) is served at {API base path}/docs and the spec document at /swagger.json
|
||||||
|
// (these can be modified with uiOptions).
|
||||||
|
func (c *Context) APIHandler(builder Builder, opts ...UIOption) http.Handler {
|
||||||
|
b := builder
|
||||||
|
if b == nil {
|
||||||
|
b = PassthroughBuilder
|
||||||
|
}
|
||||||
|
|
||||||
|
specPath, uiOpts, specOpts := c.uiOptionsForHandler(opts)
|
||||||
|
var redocOpts RedocOpts
|
||||||
|
fromCommonToAnyOptions(uiOpts, &redocOpts)
|
||||||
|
|
||||||
|
return Spec(specPath, c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b)), specOpts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Context) uiOptionsForHandler(opts []UIOption) (string, uiOptions, []SpecOption) {
|
||||||
var title string
|
var title string
|
||||||
sp := c.spec.Spec()
|
sp := c.spec.Spec()
|
||||||
if sp != nil && sp.Info != nil && sp.Info.Title != "" {
|
if sp != nil && sp.Info != nil && sp.Info.Title != "" {
|
||||||
title = sp.Info.Title
|
title = sp.Info.Title
|
||||||
}
|
}
|
||||||
|
|
||||||
redocOpts := RedocOpts{
|
// default options (may be overridden)
|
||||||
BasePath: c.BasePath(),
|
optsForContext := []UIOption{
|
||||||
Title: title,
|
WithUIBasePath(c.BasePath()),
|
||||||
|
WithUITitle(title),
|
||||||
|
}
|
||||||
|
optsForContext = append(optsForContext, opts...)
|
||||||
|
uiOpts := uiOptionsWithDefaults(optsForContext)
|
||||||
|
|
||||||
|
// If spec URL is provided, there is a non-default path to serve the spec.
|
||||||
|
// This makes sure that the UI middleware is aligned with the Spec middleware.
|
||||||
|
u, _ := url.Parse(uiOpts.SpecURL)
|
||||||
|
var specPath string
|
||||||
|
if u != nil {
|
||||||
|
specPath = u.Path
|
||||||
}
|
}
|
||||||
|
|
||||||
return Spec("", c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b)))
|
pth, doc := path.Split(specPath)
|
||||||
|
if pth == "." {
|
||||||
|
pth = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return pth, uiOpts, []SpecOption{WithSpecDocument(doc)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec
|
// RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec
|
||||||
|
@ -633,3 +716,7 @@ func (c *Context) RoutesHandler(builder Builder) http.Handler {
|
||||||
}
|
}
|
||||||
return NewRouter(c, b(NewOperationExecutor(c)))
|
return NewRouter(c, b(NewOperationExecutor(c)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cantFindProducer(format string) string {
|
||||||
|
return "can't find a producer for " + format
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
package denco
|
package denco
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -29,13 +30,13 @@ const (
|
||||||
|
|
||||||
// Router represents a URL router.
|
// Router represents a URL router.
|
||||||
type Router struct {
|
type Router struct {
|
||||||
|
param *doubleArray
|
||||||
// SizeHint expects the maximum number of path parameters in records to Build.
|
// SizeHint expects the maximum number of path parameters in records to Build.
|
||||||
// SizeHint will be used to determine the capacity of the memory to allocate.
|
// SizeHint will be used to determine the capacity of the memory to allocate.
|
||||||
// By default, SizeHint will be determined from given records to Build.
|
// By default, SizeHint will be determined from given records to Build.
|
||||||
SizeHint int
|
SizeHint int
|
||||||
|
|
||||||
static map[string]interface{}
|
static map[string]interface{}
|
||||||
param *doubleArray
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Router.
|
// New returns a new Router.
|
||||||
|
@ -51,7 +52,7 @@ func New() *Router {
|
||||||
// params is a slice of the Param that arranged in the order in which parameters appeared.
|
// params is a slice of the Param that arranged in the order in which parameters appeared.
|
||||||
// e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}].
|
// e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}].
|
||||||
func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool) {
|
func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool) {
|
||||||
if data, found := rt.static[path]; found {
|
if data, found = rt.static[path]; found {
|
||||||
return data, nil, true
|
return data, nil, true
|
||||||
}
|
}
|
||||||
if len(rt.param.node) == 1 {
|
if len(rt.param.node) == 1 {
|
||||||
|
@ -71,7 +72,7 @@ func (rt *Router) Lookup(path string) (data interface{}, params Params, found bo
|
||||||
func (rt *Router) Build(records []Record) error {
|
func (rt *Router) Build(records []Record) error {
|
||||||
statics, params := makeRecords(records)
|
statics, params := makeRecords(records)
|
||||||
if len(params) > MaxSize {
|
if len(params) > MaxSize {
|
||||||
return fmt.Errorf("denco: too many records")
|
return errors.New("denco: too many records")
|
||||||
}
|
}
|
||||||
if rt.SizeHint < 0 {
|
if rt.SizeHint < 0 {
|
||||||
rt.SizeHint = 0
|
rt.SizeHint = 0
|
||||||
|
@ -131,7 +132,8 @@ func newDoubleArray() *doubleArray {
|
||||||
// baseCheck contains BASE, CHECK and Extra flags.
|
// baseCheck contains BASE, CHECK and Extra flags.
|
||||||
// From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK.
|
// From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK.
|
||||||
//
|
//
|
||||||
// BASE (22bit) | Extra flags (2bit) | CHECK (8bit)
|
// BASE (22bit) | Extra flags (2bit) | CHECK (8bit)
|
||||||
|
//
|
||||||
// |----------------------|--|--------|
|
// |----------------------|--|--------|
|
||||||
// 32 10 8 0
|
// 32 10 8 0
|
||||||
type baseCheck uint32
|
type baseCheck uint32
|
||||||
|
@ -196,24 +198,29 @@ func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Pa
|
||||||
if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter {
|
if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter {
|
||||||
return da.node[da.bc[next].Base()], params, true
|
return da.node[da.bc[next].Base()], params, true
|
||||||
}
|
}
|
||||||
|
|
||||||
BACKTRACKING:
|
BACKTRACKING:
|
||||||
for j := len(indices) - 1; j >= 0; j-- {
|
for j := len(indices) - 1; j >= 0; j-- {
|
||||||
i, idx := int(indices[j]>>32), int(indices[j]&0xffffffff)
|
i, idx := int(indices[j]>>32), int(indices[j]&0xffffffff)
|
||||||
if da.bc[idx].IsSingleParam() {
|
if da.bc[idx].IsSingleParam() {
|
||||||
idx := nextIndex(da.bc[idx].Base(), ParamCharacter)
|
nextIdx := nextIndex(da.bc[idx].Base(), ParamCharacter)
|
||||||
if idx >= len(da.bc) {
|
if nextIdx >= len(da.bc) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
next := NextSeparator(path, i)
|
next := NextSeparator(path, i)
|
||||||
params := append(params, Param{Value: path[i:next]})
|
nextParams := params
|
||||||
if nd, params, found := da.lookup(path[next:], params, idx); found {
|
nextParams = append(nextParams, Param{Value: path[i:next]})
|
||||||
return nd, params, true
|
if nd, nextNextParams, found := da.lookup(path[next:], nextParams, nextIdx); found {
|
||||||
|
return nd, nextNextParams, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if da.bc[idx].IsWildcardParam() {
|
if da.bc[idx].IsWildcardParam() {
|
||||||
idx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
|
nextIdx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
|
||||||
params := append(params, Param{Value: path[i:]})
|
nextParams := params
|
||||||
return da.node[da.bc[idx].Base()], params, true
|
nextParams = append(nextParams, Param{Value: path[i:]})
|
||||||
|
return da.node[da.bc[nextIdx].Base()], nextParams, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
|
@ -325,7 +332,7 @@ func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[i
|
||||||
}
|
}
|
||||||
base = da.findBase(siblings, idx, usedBase)
|
base = da.findBase(siblings, idx, usedBase)
|
||||||
if base > MaxSize {
|
if base > MaxSize {
|
||||||
return -1, nil, nil, fmt.Errorf("denco: too many elements of internal slice")
|
return -1, nil, nil, errors.New("denco: too many elements of internal slice")
|
||||||
}
|
}
|
||||||
da.setBase(idx, base)
|
da.setBase(idx, base)
|
||||||
return base, siblings, leaf, err
|
return base, siblings, leaf, err
|
||||||
|
@ -386,7 +393,7 @@ func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, er
|
||||||
case pc == c:
|
case pc == c:
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("denco: BUG: routing table hasn't been sorted")
|
return nil, nil, errors.New("denco: BUG: routing table hasn't been sorted")
|
||||||
}
|
}
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
sib[n-1].end = i
|
sib[n-1].end = i
|
||||||
|
@ -431,7 +438,7 @@ func makeRecords(srcs []Record) (statics, params []*record) {
|
||||||
wildcardPrefix := string(SeparatorCharacter) + string(WildcardCharacter)
|
wildcardPrefix := string(SeparatorCharacter) + string(WildcardCharacter)
|
||||||
restconfPrefix := string(PathParamCharacter) + string(ParamCharacter)
|
restconfPrefix := string(PathParamCharacter) + string(ParamCharacter)
|
||||||
for _, r := range srcs {
|
for _, r := range srcs {
|
||||||
if strings.Contains(r.Key, paramPrefix) || strings.Contains(r.Key, wildcardPrefix) ||strings.Contains(r.Key, restconfPrefix){
|
if strings.Contains(r.Key, paramPrefix) || strings.Contains(r.Key, wildcardPrefix) || strings.Contains(r.Key, restconfPrefix) {
|
||||||
r.Key += termChar
|
r.Key += termChar
|
||||||
params = append(params, &record{Record: r})
|
params = append(params, &record{Record: r})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -12,51 +12,52 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
/*Package middleware provides the library with helper functions for serving swagger APIs.
|
/*
|
||||||
|
Package middleware provides the library with helper functions for serving swagger APIs.
|
||||||
|
|
||||||
Pseudo middleware handler
|
Pseudo middleware handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-openapi/errors"
|
"github.com/go-openapi/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newCompleteMiddleware(ctx *Context) http.Handler {
|
func newCompleteMiddleware(ctx *Context) http.Handler {
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
// use context to lookup routes
|
// use context to lookup routes
|
||||||
if matched, ok := ctx.RouteInfo(r); ok {
|
if matched, ok := ctx.RouteInfo(r); ok {
|
||||||
|
|
||||||
if matched.NeedsAuth() {
|
if matched.NeedsAuth() {
|
||||||
if _, err := ctx.Authorize(r, matched); err != nil {
|
if _, err := ctx.Authorize(r, matched); err != nil {
|
||||||
ctx.Respond(rw, r, matched.Produces, matched, err)
|
ctx.Respond(rw, r, matched.Produces, matched, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bound, validation := ctx.BindAndValidate(r, matched)
|
bound, validation := ctx.BindAndValidate(r, matched)
|
||||||
if validation != nil {
|
if validation != nil {
|
||||||
ctx.Respond(rw, r, matched.Produces, matched, validation)
|
ctx.Respond(rw, r, matched.Produces, matched, validation)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := matched.Handler.Handle(bound)
|
result, err := matched.Handler.Handle(bound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Respond(rw, r, matched.Produces, matched, err)
|
ctx.Respond(rw, r, matched.Produces, matched, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Respond(rw, r, matched.Produces, matched, result)
|
ctx.Respond(rw, r, matched.Produces, matched, result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not found, check if it exists in the other methods first
|
// Not found, check if it exists in the other methods first
|
||||||
if others := ctx.AllowedMethods(r); len(others) > 0 {
|
if others := ctx.AllowedMethods(r); len(others) > 0 {
|
||||||
ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
|
ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.Path))
|
ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.Path))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
package middleware
|
package middleware
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
// +build go1.8
|
|
||||||
|
|
||||||
package middleware
|
|
||||||
|
|
||||||
import "net/url"
|
|
||||||
|
|
||||||
func pathUnescape(path string) (string, error) {
|
|
||||||
return url.PathUnescape(path)
|
|
||||||
}
|
|
|
@ -195,7 +195,8 @@ func ParseAccept2(header http.Header, key string) (specs []AcceptSpec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseAccept parses Accept* headers.
|
// ParseAccept parses Accept* headers.
|
||||||
func ParseAccept(header http.Header, key string) (specs []AcceptSpec) {
|
func ParseAccept(header http.Header, key string) []AcceptSpec {
|
||||||
|
var specs []AcceptSpec
|
||||||
loop:
|
loop:
|
||||||
for _, s := range header[key] {
|
for _, s := range header[key] {
|
||||||
for {
|
for {
|
||||||
|
@ -218,6 +219,7 @@ loop:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
specs = append(specs, spec)
|
specs = append(specs, spec)
|
||||||
s = skipSpace(s)
|
s = skipSpace(s)
|
||||||
if !strings.HasPrefix(s, ",") {
|
if !strings.HasPrefix(s, ",") {
|
||||||
|
@ -226,7 +228,8 @@ loop:
|
||||||
s = skipSpace(s[1:])
|
s = skipSpace(s[1:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
|
return specs
|
||||||
}
|
}
|
||||||
|
|
||||||
func skipSpace(s string) (rest string) {
|
func skipSpace(s string) (rest string) {
|
||||||
|
@ -306,7 +309,7 @@ func expectTokenOrQuoted(s string) (value string, rest string) {
|
||||||
p := make([]byte, len(s)-1)
|
p := make([]byte, len(s)-1)
|
||||||
j := copy(p, s[:i])
|
j := copy(p, s[:i])
|
||||||
escape := true
|
escape := true
|
||||||
for i = i + 1; i < len(s); i++ {
|
for i++; i < len(s); i++ {
|
||||||
b := s[i]
|
b := s[i]
|
||||||
switch {
|
switch {
|
||||||
case escape:
|
case escape:
|
||||||
|
|
|
@ -34,6 +34,11 @@ import (
|
||||||
|
|
||||||
const defaultMaxMemory = 32 << 20
|
const defaultMaxMemory = 32 << 20
|
||||||
|
|
||||||
|
const (
|
||||||
|
typeString = "string"
|
||||||
|
typeArray = "array"
|
||||||
|
)
|
||||||
|
|
||||||
var textUnmarshalType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
|
var textUnmarshalType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
|
||||||
|
|
||||||
func newUntypedParamBinder(param spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedParamBinder {
|
func newUntypedParamBinder(param spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedParamBinder {
|
||||||
|
@ -66,7 +71,7 @@ func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return reflect.TypeOf(true)
|
return reflect.TypeOf(true)
|
||||||
|
|
||||||
case "string":
|
case typeString:
|
||||||
if tt, ok := p.formats.GetType(format); ok {
|
if tt, ok := p.formats.GetType(format); ok {
|
||||||
return tt
|
return tt
|
||||||
}
|
}
|
||||||
|
@ -94,7 +99,7 @@ func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items
|
||||||
return reflect.TypeOf(float64(0))
|
return reflect.TypeOf(float64(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
case "array":
|
case typeArray:
|
||||||
if items == nil {
|
if items == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -119,7 +124,7 @@ func (p *untypedParamBinder) allowsMulti() bool {
|
||||||
|
|
||||||
func (p *untypedParamBinder) readValue(values runtime.Gettable, target reflect.Value) ([]string, bool, bool, error) {
|
func (p *untypedParamBinder) readValue(values runtime.Gettable, target reflect.Value) ([]string, bool, bool, error) {
|
||||||
name, in, cf, tpe := p.parameter.Name, p.parameter.In, p.parameter.CollectionFormat, p.parameter.Type
|
name, in, cf, tpe := p.parameter.Name, p.parameter.In, p.parameter.CollectionFormat, p.parameter.Type
|
||||||
if tpe == "array" {
|
if tpe == typeArray {
|
||||||
if cf == "multi" {
|
if cf == "multi" {
|
||||||
if !p.allowsMulti() {
|
if !p.allowsMulti() {
|
||||||
return nil, false, false, errors.InvalidCollectionFormat(name, in, cf)
|
return nil, false, false, errors.InvalidCollectionFormat(name, in, cf)
|
||||||
|
@ -208,10 +213,11 @@ func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams
|
||||||
if ffErr != nil {
|
if ffErr != nil {
|
||||||
if p.parameter.Required {
|
if p.parameter.Required {
|
||||||
return errors.NewParseError(p.Name, p.parameter.In, "", ffErr)
|
return errors.NewParseError(p.Name, p.parameter.In, "", ffErr)
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header}))
|
target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header}))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -263,7 +269,7 @@ func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflect.Value) error {
|
func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflect.Value) error {
|
||||||
if p.parameter.Type == "array" {
|
if p.parameter.Type == typeArray {
|
||||||
return p.setSliceFieldValue(target, p.parameter.Default, data, hasKey)
|
return p.setSliceFieldValue(target, p.parameter.Default, data, hasKey)
|
||||||
}
|
}
|
||||||
var d string
|
var d string
|
||||||
|
@ -273,7 +279,7 @@ func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflec
|
||||||
return p.setFieldValue(target, p.parameter.Default, d, hasKey)
|
return p.setFieldValue(target, p.parameter.Default, d, hasKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue interface{}, data string, hasKey bool) error {
|
func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue interface{}, data string, hasKey bool) error { //nolint:gocyclo
|
||||||
tpe := p.parameter.Type
|
tpe := p.parameter.Type
|
||||||
if p.parameter.Format != "" {
|
if p.parameter.Format != "" {
|
||||||
tpe = p.parameter.Format
|
tpe = p.parameter.Format
|
||||||
|
@ -317,7 +323,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue in
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch target.Kind() {
|
switch target.Kind() { //nolint:exhaustive // we want to check only types that map from a swagger parameter
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
if data == "" {
|
if data == "" {
|
||||||
if target.CanSet() {
|
if target.CanSet() {
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
// +build !go1.8
|
|
||||||
|
|
||||||
package middleware
|
|
||||||
|
|
||||||
import "net/url"
|
|
||||||
|
|
||||||
func pathUnescape(path string) (string, error) {
|
|
||||||
return url.QueryUnescape(path)
|
|
||||||
}
|
|
|
@ -10,67 +10,57 @@ import (
|
||||||
|
|
||||||
// RapiDocOpts configures the RapiDoc middlewares
|
// RapiDocOpts configures the RapiDoc middlewares
|
||||||
type RapiDocOpts struct {
|
type RapiDocOpts struct {
|
||||||
// BasePath for the UI path, defaults to: /
|
// BasePath for the UI, defaults to: /
|
||||||
BasePath string
|
BasePath string
|
||||||
// Path combines with BasePath for the full UI path, defaults to: docs
|
|
||||||
|
// Path combines with BasePath to construct the path to the UI, defaults to: "docs".
|
||||||
Path string
|
Path string
|
||||||
// SpecURL the url to find the spec for
|
|
||||||
|
// SpecURL is the URL of the spec document.
|
||||||
|
//
|
||||||
|
// Defaults to: /swagger.json
|
||||||
SpecURL string
|
SpecURL string
|
||||||
// RapiDocURL for the js that generates the rapidoc site, defaults to: https://cdn.jsdelivr.net/npm/rapidoc/bundles/rapidoc.standalone.js
|
|
||||||
RapiDocURL string
|
|
||||||
// Title for the documentation site, default to: API documentation
|
// Title for the documentation site, default to: API documentation
|
||||||
Title string
|
Title string
|
||||||
|
|
||||||
|
// Template specifies a custom template to serve the UI
|
||||||
|
Template string
|
||||||
|
|
||||||
|
// RapiDocURL points to the js asset that generates the rapidoc site.
|
||||||
|
//
|
||||||
|
// Defaults to https://unpkg.com/rapidoc/dist/rapidoc-min.js
|
||||||
|
RapiDocURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureDefaults in case some options are missing
|
|
||||||
func (r *RapiDocOpts) EnsureDefaults() {
|
func (r *RapiDocOpts) EnsureDefaults() {
|
||||||
if r.BasePath == "" {
|
common := toCommonUIOptions(r)
|
||||||
r.BasePath = "/"
|
common.EnsureDefaults()
|
||||||
}
|
fromCommonToAnyOptions(common, r)
|
||||||
if r.Path == "" {
|
|
||||||
r.Path = "docs"
|
// rapidoc-specifics
|
||||||
}
|
|
||||||
if r.SpecURL == "" {
|
|
||||||
r.SpecURL = "/swagger.json"
|
|
||||||
}
|
|
||||||
if r.RapiDocURL == "" {
|
if r.RapiDocURL == "" {
|
||||||
r.RapiDocURL = rapidocLatest
|
r.RapiDocURL = rapidocLatest
|
||||||
}
|
}
|
||||||
if r.Title == "" {
|
if r.Template == "" {
|
||||||
r.Title = "API documentation"
|
r.Template = rapidocTemplate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RapiDoc creates a middleware to serve a documentation site for a swagger spec.
|
// RapiDoc creates a middleware to serve a documentation site for a swagger spec.
|
||||||
// This allows for altering the spec before starting the http listener.
|
|
||||||
//
|
//
|
||||||
|
// This allows for altering the spec before starting the http listener.
|
||||||
func RapiDoc(opts RapiDocOpts, next http.Handler) http.Handler {
|
func RapiDoc(opts RapiDocOpts, next http.Handler) http.Handler {
|
||||||
opts.EnsureDefaults()
|
opts.EnsureDefaults()
|
||||||
|
|
||||||
pth := path.Join(opts.BasePath, opts.Path)
|
pth := path.Join(opts.BasePath, opts.Path)
|
||||||
tmpl := template.Must(template.New("rapidoc").Parse(rapidocTemplate))
|
tmpl := template.Must(template.New("rapidoc").Parse(opts.Template))
|
||||||
|
assets := bytes.NewBuffer(nil)
|
||||||
|
if err := tmpl.Execute(assets, opts); err != nil {
|
||||||
|
panic(fmt.Errorf("cannot execute template: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(nil)
|
return serveUI(pth, assets.Bytes(), next)
|
||||||
_ = tmpl.Execute(buf, opts)
|
|
||||||
b := buf.Bytes()
|
|
||||||
|
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path == pth {
|
|
||||||
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
rw.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
_, _ = rw.Write(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if next == nil {
|
|
||||||
rw.Header().Set("Content-Type", "text/plain")
|
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
|
||||||
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
next.ServeHTTP(rw, r)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -79,7 +69,7 @@ const (
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>{{ .Title }}</title>
|
<title>{{ .Title }}</title>
|
||||||
<meta charset="utf-8"> <!-- Important: rapi-doc uses utf8 charecters -->
|
<meta charset="utf-8"> <!-- Important: rapi-doc uses utf8 characters -->
|
||||||
<script type="module" src="{{ .RapiDocURL }}"></script>
|
<script type="module" src="{{ .RapiDocURL }}"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -10,67 +10,58 @@ import (
|
||||||
|
|
||||||
// RedocOpts configures the Redoc middlewares
|
// RedocOpts configures the Redoc middlewares
|
||||||
type RedocOpts struct {
|
type RedocOpts struct {
|
||||||
// BasePath for the UI path, defaults to: /
|
// BasePath for the UI, defaults to: /
|
||||||
BasePath string
|
BasePath string
|
||||||
// Path combines with BasePath for the full UI path, defaults to: docs
|
|
||||||
|
// Path combines with BasePath to construct the path to the UI, defaults to: "docs".
|
||||||
Path string
|
Path string
|
||||||
// SpecURL the url to find the spec for
|
|
||||||
|
// SpecURL is the URL of the spec document.
|
||||||
|
//
|
||||||
|
// Defaults to: /swagger.json
|
||||||
SpecURL string
|
SpecURL string
|
||||||
// RedocURL for the js that generates the redoc site, defaults to: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js
|
|
||||||
RedocURL string
|
|
||||||
// Title for the documentation site, default to: API documentation
|
// Title for the documentation site, default to: API documentation
|
||||||
Title string
|
Title string
|
||||||
|
|
||||||
|
// Template specifies a custom template to serve the UI
|
||||||
|
Template string
|
||||||
|
|
||||||
|
// RedocURL points to the js that generates the redoc site.
|
||||||
|
//
|
||||||
|
// Defaults to: https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js
|
||||||
|
RedocURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureDefaults in case some options are missing
|
// EnsureDefaults in case some options are missing
|
||||||
func (r *RedocOpts) EnsureDefaults() {
|
func (r *RedocOpts) EnsureDefaults() {
|
||||||
if r.BasePath == "" {
|
common := toCommonUIOptions(r)
|
||||||
r.BasePath = "/"
|
common.EnsureDefaults()
|
||||||
}
|
fromCommonToAnyOptions(common, r)
|
||||||
if r.Path == "" {
|
|
||||||
r.Path = "docs"
|
// redoc-specifics
|
||||||
}
|
|
||||||
if r.SpecURL == "" {
|
|
||||||
r.SpecURL = "/swagger.json"
|
|
||||||
}
|
|
||||||
if r.RedocURL == "" {
|
if r.RedocURL == "" {
|
||||||
r.RedocURL = redocLatest
|
r.RedocURL = redocLatest
|
||||||
}
|
}
|
||||||
if r.Title == "" {
|
if r.Template == "" {
|
||||||
r.Title = "API documentation"
|
r.Template = redocTemplate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redoc creates a middleware to serve a documentation site for a swagger spec.
|
// Redoc creates a middleware to serve a documentation site for a swagger spec.
|
||||||
// This allows for altering the spec before starting the http listener.
|
|
||||||
//
|
//
|
||||||
|
// This allows for altering the spec before starting the http listener.
|
||||||
func Redoc(opts RedocOpts, next http.Handler) http.Handler {
|
func Redoc(opts RedocOpts, next http.Handler) http.Handler {
|
||||||
opts.EnsureDefaults()
|
opts.EnsureDefaults()
|
||||||
|
|
||||||
pth := path.Join(opts.BasePath, opts.Path)
|
pth := path.Join(opts.BasePath, opts.Path)
|
||||||
tmpl := template.Must(template.New("redoc").Parse(redocTemplate))
|
tmpl := template.Must(template.New("redoc").Parse(opts.Template))
|
||||||
|
assets := bytes.NewBuffer(nil)
|
||||||
|
if err := tmpl.Execute(assets, opts); err != nil {
|
||||||
|
panic(fmt.Errorf("cannot execute template: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(nil)
|
return serveUI(pth, assets.Bytes(), next)
|
||||||
_ = tmpl.Execute(buf, opts)
|
|
||||||
b := buf.Bytes()
|
|
||||||
|
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path == pth {
|
|
||||||
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
rw.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
_, _ = rw.Write(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if next == nil {
|
|
||||||
rw.Header().Set("Content-Type", "text/plain")
|
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
|
||||||
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
next.ServeHTTP(rw, r)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -19,10 +19,10 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/go-openapi/errors"
|
"github.com/go-openapi/errors"
|
||||||
|
"github.com/go-openapi/runtime"
|
||||||
|
"github.com/go-openapi/runtime/logger"
|
||||||
"github.com/go-openapi/spec"
|
"github.com/go-openapi/spec"
|
||||||
"github.com/go-openapi/strfmt"
|
"github.com/go-openapi/strfmt"
|
||||||
|
|
||||||
"github.com/go-openapi/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UntypedRequestBinder binds and validates the data from a http request
|
// UntypedRequestBinder binds and validates the data from a http request
|
||||||
|
@ -31,6 +31,7 @@ type UntypedRequestBinder struct {
|
||||||
Parameters map[string]spec.Parameter
|
Parameters map[string]spec.Parameter
|
||||||
Formats strfmt.Registry
|
Formats strfmt.Registry
|
||||||
paramBinders map[string]*untypedParamBinder
|
paramBinders map[string]*untypedParamBinder
|
||||||
|
debugLogf func(string, ...any) // a logging function to debug context and all components using it
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUntypedRequestBinder creates a new binder for reading a request.
|
// NewUntypedRequestBinder creates a new binder for reading a request.
|
||||||
|
@ -44,6 +45,7 @@ func NewUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Sw
|
||||||
paramBinders: binders,
|
paramBinders: binders,
|
||||||
Spec: spec,
|
Spec: spec,
|
||||||
Formats: formats,
|
Formats: formats,
|
||||||
|
debugLogf: debugLogfFunc(nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +54,10 @@ func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RoutePara
|
||||||
val := reflect.Indirect(reflect.ValueOf(data))
|
val := reflect.Indirect(reflect.ValueOf(data))
|
||||||
isMap := val.Kind() == reflect.Map
|
isMap := val.Kind() == reflect.Map
|
||||||
var result []error
|
var result []error
|
||||||
debugLog("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath())
|
o.debugLogf("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath())
|
||||||
for fieldName, param := range o.Parameters {
|
for fieldName, param := range o.Parameters {
|
||||||
binder := o.paramBinders[fieldName]
|
binder := o.paramBinders[fieldName]
|
||||||
debugLog("binding parameter %s for %s %s", fieldName, request.Method, request.URL.EscapedPath())
|
o.debugLogf("binding parameter %s for %s %s", fieldName, request.Method, request.URL.EscapedPath())
|
||||||
var target reflect.Value
|
var target reflect.Value
|
||||||
if !isMap {
|
if !isMap {
|
||||||
binder.Name = fieldName
|
binder.Name = fieldName
|
||||||
|
@ -65,7 +67,7 @@ func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RoutePara
|
||||||
if isMap {
|
if isMap {
|
||||||
tpe := binder.Type()
|
tpe := binder.Type()
|
||||||
if tpe == nil {
|
if tpe == nil {
|
||||||
if param.Schema.Type.Contains("array") {
|
if param.Schema.Type.Contains(typeArray) {
|
||||||
tpe = reflect.TypeOf([]interface{}{})
|
tpe = reflect.TypeOf([]interface{}{})
|
||||||
} else {
|
} else {
|
||||||
tpe = reflect.TypeOf(map[string]interface{}{})
|
tpe = reflect.TypeOf(map[string]interface{}{})
|
||||||
|
@ -102,3 +104,14 @@ func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RoutePara
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLogger allows for injecting a logger to catch debug entries.
|
||||||
|
//
|
||||||
|
// The logger is enabled in DEBUG mode only.
|
||||||
|
func (o *UntypedRequestBinder) SetLogger(lg logger.Logger) {
|
||||||
|
o.debugLogf = debugLogfFunc(lg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *UntypedRequestBinder) setDebugLogf(fn func(string, ...any)) {
|
||||||
|
o.debugLogf = fn
|
||||||
|
}
|
||||||
|
|
|
@ -17,10 +17,12 @@ package middleware
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
fpath "path"
|
fpath "path"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-openapi/runtime/logger"
|
||||||
"github.com/go-openapi/runtime/security"
|
"github.com/go-openapi/runtime/security"
|
||||||
"github.com/go-openapi/swag"
|
"github.com/go-openapi/swag"
|
||||||
|
|
||||||
|
@ -67,10 +69,10 @@ func (r RouteParams) GetOK(name string) ([]string, bool, bool) {
|
||||||
return nil, false, false
|
return nil, false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRouter creates a new context aware router middleware
|
// NewRouter creates a new context-aware router middleware
|
||||||
func NewRouter(ctx *Context, next http.Handler) http.Handler {
|
func NewRouter(ctx *Context, next http.Handler) http.Handler {
|
||||||
if ctx.router == nil {
|
if ctx.router == nil {
|
||||||
ctx.router = DefaultRouter(ctx.spec, ctx.api)
|
ctx.router = DefaultRouter(ctx.spec, ctx.api, WithDefaultRouterLoggerFunc(ctx.debugLogf))
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -103,41 +105,75 @@ type RoutableAPI interface {
|
||||||
DefaultConsumes() string
|
DefaultConsumes() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Router represents a swagger aware router
|
// Router represents a swagger-aware router
|
||||||
type Router interface {
|
type Router interface {
|
||||||
Lookup(method, path string) (*MatchedRoute, bool)
|
Lookup(method, path string) (*MatchedRoute, bool)
|
||||||
OtherMethods(method, path string) []string
|
OtherMethods(method, path string) []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type defaultRouteBuilder struct {
|
type defaultRouteBuilder struct {
|
||||||
spec *loads.Document
|
spec *loads.Document
|
||||||
analyzer *analysis.Spec
|
analyzer *analysis.Spec
|
||||||
api RoutableAPI
|
api RoutableAPI
|
||||||
records map[string][]denco.Record
|
records map[string][]denco.Record
|
||||||
|
debugLogf func(string, ...any) // a logging function to debug context and all components using it
|
||||||
}
|
}
|
||||||
|
|
||||||
type defaultRouter struct {
|
type defaultRouter struct {
|
||||||
spec *loads.Document
|
spec *loads.Document
|
||||||
routers map[string]*denco.Router
|
routers map[string]*denco.Router
|
||||||
|
debugLogf func(string, ...any) // a logging function to debug context and all components using it
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI) *defaultRouteBuilder {
|
func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI, opts ...DefaultRouterOpt) *defaultRouteBuilder {
|
||||||
|
var o defaultRouterOpts
|
||||||
|
for _, apply := range opts {
|
||||||
|
apply(&o)
|
||||||
|
}
|
||||||
|
if o.debugLogf == nil {
|
||||||
|
o.debugLogf = debugLogfFunc(nil) // defaults to standard logger
|
||||||
|
}
|
||||||
|
|
||||||
return &defaultRouteBuilder{
|
return &defaultRouteBuilder{
|
||||||
spec: spec,
|
spec: spec,
|
||||||
analyzer: analysis.New(spec.Spec()),
|
analyzer: analysis.New(spec.Spec()),
|
||||||
api: api,
|
api: api,
|
||||||
records: make(map[string][]denco.Record),
|
records: make(map[string][]denco.Record),
|
||||||
|
debugLogf: o.debugLogf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultRouter creates a default implemenation of the router
|
// DefaultRouterOpt allows to inject optional behavior to the default router.
|
||||||
func DefaultRouter(spec *loads.Document, api RoutableAPI) Router {
|
type DefaultRouterOpt func(*defaultRouterOpts)
|
||||||
builder := newDefaultRouteBuilder(spec, api)
|
|
||||||
|
type defaultRouterOpts struct {
|
||||||
|
debugLogf func(string, ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDefaultRouterLogger sets the debug logger for the default router.
|
||||||
|
//
|
||||||
|
// This is enabled only in DEBUG mode.
|
||||||
|
func WithDefaultRouterLogger(lg logger.Logger) DefaultRouterOpt {
|
||||||
|
return func(o *defaultRouterOpts) {
|
||||||
|
o.debugLogf = debugLogfFunc(lg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDefaultRouterLoggerFunc sets a logging debug method for the default router.
|
||||||
|
func WithDefaultRouterLoggerFunc(fn func(string, ...any)) DefaultRouterOpt {
|
||||||
|
return func(o *defaultRouterOpts) {
|
||||||
|
o.debugLogf = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultRouter creates a default implementation of the router
|
||||||
|
func DefaultRouter(spec *loads.Document, api RoutableAPI, opts ...DefaultRouterOpt) Router {
|
||||||
|
builder := newDefaultRouteBuilder(spec, api, opts...)
|
||||||
if spec != nil {
|
if spec != nil {
|
||||||
for method, paths := range builder.analyzer.Operations() {
|
for method, paths := range builder.analyzer.Operations() {
|
||||||
for path, operation := range paths {
|
for path, operation := range paths {
|
||||||
fp := fpath.Join(spec.BasePath(), path)
|
fp := fpath.Join(spec.BasePath(), path)
|
||||||
debugLog("adding route %s %s %q", method, fp, operation.ID)
|
builder.debugLogf("adding route %s %s %q", method, fp, operation.ID)
|
||||||
builder.AddRoute(method, fp, operation)
|
builder.AddRoute(method, fp, operation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,24 +355,24 @@ func (m *MatchedRoute) NeedsAuth() bool {
|
||||||
|
|
||||||
func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
|
func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
|
||||||
mth := strings.ToUpper(method)
|
mth := strings.ToUpper(method)
|
||||||
debugLog("looking up route for %s %s", method, path)
|
d.debugLogf("looking up route for %s %s", method, path)
|
||||||
if Debug {
|
if Debug {
|
||||||
if len(d.routers) == 0 {
|
if len(d.routers) == 0 {
|
||||||
debugLog("there are no known routers")
|
d.debugLogf("there are no known routers")
|
||||||
}
|
}
|
||||||
for meth := range d.routers {
|
for meth := range d.routers {
|
||||||
debugLog("got a router for %s", meth)
|
d.debugLogf("got a router for %s", meth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if router, ok := d.routers[mth]; ok {
|
if router, ok := d.routers[mth]; ok {
|
||||||
if m, rp, ok := router.Lookup(fpath.Clean(path)); ok && m != nil {
|
if m, rp, ok := router.Lookup(fpath.Clean(path)); ok && m != nil {
|
||||||
if entry, ok := m.(*routeEntry); ok {
|
if entry, ok := m.(*routeEntry); ok {
|
||||||
debugLog("found a route for %s %s with %d parameters", method, path, len(entry.Parameters))
|
d.debugLogf("found a route for %s %s with %d parameters", method, path, len(entry.Parameters))
|
||||||
var params RouteParams
|
var params RouteParams
|
||||||
for _, p := range rp {
|
for _, p := range rp {
|
||||||
v, err := pathUnescape(p.Value)
|
v, err := url.PathUnescape(p.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debugLog("failed to escape %q: %v", p.Value, err)
|
d.debugLogf("failed to escape %q: %v", p.Value, err)
|
||||||
v = p.Value
|
v = p.Value
|
||||||
}
|
}
|
||||||
// a workaround to handle fragment/composing parameters until they are supported in denco router
|
// a workaround to handle fragment/composing parameters until they are supported in denco router
|
||||||
|
@ -356,10 +392,10 @@ func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) {
|
||||||
return &MatchedRoute{routeEntry: *entry, Params: params}, true
|
return &MatchedRoute{routeEntry: *entry, Params: params}, true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugLog("couldn't find a route by path for %s %s", method, path)
|
d.debugLogf("couldn't find a route by path for %s %s", method, path)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugLog("couldn't find a route by method for %s %s", method, path)
|
d.debugLogf("couldn't find a route by method for %s %s", method, path)
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
@ -378,6 +414,10 @@ func (d *defaultRouter) OtherMethods(method, path string) []string {
|
||||||
return methods
|
return methods
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *defaultRouter) SetLogger(lg logger.Logger) {
|
||||||
|
d.debugLogf = debugLogfFunc(lg)
|
||||||
|
}
|
||||||
|
|
||||||
// convert swagger parameters per path segment into a denco parameter as multiple parameters per segment are not supported in denco
|
// convert swagger parameters per path segment into a denco parameter as multiple parameters per segment are not supported in denco
|
||||||
var pathConverter = regexp.MustCompile(`{(.+?)}([^/]*)`)
|
var pathConverter = regexp.MustCompile(`{(.+?)}([^/]*)`)
|
||||||
|
|
||||||
|
@ -413,7 +453,7 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
|
||||||
bp = bp[:len(bp)-1]
|
bp = bp[:len(bp)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
debugLog("operation: %#v", *operation)
|
d.debugLogf("operation: %#v", *operation)
|
||||||
if handler, ok := d.api.HandlerFor(method, strings.TrimPrefix(path, bp)); ok {
|
if handler, ok := d.api.HandlerFor(method, strings.TrimPrefix(path, bp)); ok {
|
||||||
consumes := d.analyzer.ConsumesFor(operation)
|
consumes := d.analyzer.ConsumesFor(operation)
|
||||||
produces := d.analyzer.ProducesFor(operation)
|
produces := d.analyzer.ProducesFor(operation)
|
||||||
|
@ -428,6 +468,8 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
|
||||||
produces = append(produces, defProduces)
|
produces = append(produces, defProduces)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestBinder := NewUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats())
|
||||||
|
requestBinder.setDebugLogf(d.debugLogf)
|
||||||
record := denco.NewRecord(pathConverter.ReplaceAllString(path, ":$1"), &routeEntry{
|
record := denco.NewRecord(pathConverter.ReplaceAllString(path, ":$1"), &routeEntry{
|
||||||
BasePath: bp,
|
BasePath: bp,
|
||||||
PathPattern: path,
|
PathPattern: path,
|
||||||
|
@ -439,7 +481,7 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
|
||||||
Producers: d.api.ProducersFor(normalizeOffers(produces)),
|
Producers: d.api.ProducersFor(normalizeOffers(produces)),
|
||||||
Parameters: parameters,
|
Parameters: parameters,
|
||||||
Formats: d.api.Formats(),
|
Formats: d.api.Formats(),
|
||||||
Binder: NewUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats()),
|
Binder: requestBinder,
|
||||||
Authenticators: d.buildAuthenticators(operation),
|
Authenticators: d.buildAuthenticators(operation),
|
||||||
Authorizer: d.api.Authorizer(),
|
Authorizer: d.api.Authorizer(),
|
||||||
})
|
})
|
||||||
|
@ -449,11 +491,11 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper
|
||||||
|
|
||||||
func (d *defaultRouteBuilder) buildAuthenticators(operation *spec.Operation) RouteAuthenticators {
|
func (d *defaultRouteBuilder) buildAuthenticators(operation *spec.Operation) RouteAuthenticators {
|
||||||
requirements := d.analyzer.SecurityRequirementsFor(operation)
|
requirements := d.analyzer.SecurityRequirementsFor(operation)
|
||||||
var auths []RouteAuthenticator
|
auths := make([]RouteAuthenticator, 0, len(requirements))
|
||||||
for _, reqs := range requirements {
|
for _, reqs := range requirements {
|
||||||
var schemes []string
|
schemes := make([]string, 0, len(reqs))
|
||||||
scopes := make(map[string][]string, len(reqs))
|
scopes := make(map[string][]string, len(reqs))
|
||||||
var scopeSlices [][]string
|
scopeSlices := make([][]string, 0, len(reqs))
|
||||||
for _, req := range reqs {
|
for _, req := range reqs {
|
||||||
schemes = append(schemes, req.Name)
|
schemes = append(schemes, req.Name)
|
||||||
scopes[req.Name] = req.Scopes
|
scopes[req.Name] = req.Scopes
|
||||||
|
@ -482,7 +524,8 @@ func (d *defaultRouteBuilder) Build() *defaultRouter {
|
||||||
routers[method] = router
|
routers[method] = router
|
||||||
}
|
}
|
||||||
return &defaultRouter{
|
return &defaultRouter{
|
||||||
spec: d.spec,
|
spec: d.spec,
|
||||||
routers: routers,
|
routers: routers,
|
||||||
|
debugLogf: d.debugLogf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,30 +19,84 @@ import (
|
||||||
"path"
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Spec creates a middleware to serve a swagger spec.
|
const (
|
||||||
// This allows for altering the spec before starting the http listener.
|
contentTypeHeader = "Content-Type"
|
||||||
// This can be useful if you want to serve the swagger spec from another path than /swagger.json
|
applicationJSON = "application/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SpecOption can be applied to the Spec serving middleware
|
||||||
|
type SpecOption func(*specOptions)
|
||||||
|
|
||||||
|
var defaultSpecOptions = specOptions{
|
||||||
|
Path: "",
|
||||||
|
Document: "swagger.json",
|
||||||
|
}
|
||||||
|
|
||||||
|
type specOptions struct {
|
||||||
|
Path string
|
||||||
|
Document string
|
||||||
|
}
|
||||||
|
|
||||||
|
func specOptionsWithDefaults(opts []SpecOption) specOptions {
|
||||||
|
o := defaultSpecOptions
|
||||||
|
for _, apply := range opts {
|
||||||
|
apply(&o)
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spec creates a middleware to serve a swagger spec as a JSON document.
|
||||||
//
|
//
|
||||||
func Spec(basePath string, b []byte, next http.Handler) http.Handler {
|
// This allows for altering the spec before starting the http listener.
|
||||||
|
//
|
||||||
|
// The basePath argument indicates the path of the spec document (defaults to "/").
|
||||||
|
// Additional SpecOption can be used to change the name of the document (defaults to "swagger.json").
|
||||||
|
func Spec(basePath string, b []byte, next http.Handler, opts ...SpecOption) http.Handler {
|
||||||
if basePath == "" {
|
if basePath == "" {
|
||||||
basePath = "/"
|
basePath = "/"
|
||||||
}
|
}
|
||||||
pth := path.Join(basePath, "swagger.json")
|
o := specOptionsWithDefaults(opts)
|
||||||
|
pth := path.Join(basePath, o.Path, o.Document)
|
||||||
|
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Path == pth {
|
if path.Clean(r.URL.Path) == pth {
|
||||||
rw.Header().Set("Content-Type", "application/json")
|
rw.Header().Set(contentTypeHeader, applicationJSON)
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
//#nosec
|
|
||||||
_, _ = rw.Write(b)
|
_, _ = rw.Write(b)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if next == nil {
|
if next != nil {
|
||||||
rw.Header().Set("Content-Type", "application/json")
|
next.ServeHTTP(rw, r)
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
next.ServeHTTP(rw, r)
|
|
||||||
|
rw.Header().Set(contentTypeHeader, applicationJSON)
|
||||||
|
rw.WriteHeader(http.StatusNotFound)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithSpecPath sets the path to be joined to the base path of the Spec middleware.
|
||||||
|
//
|
||||||
|
// This is empty by default.
|
||||||
|
func WithSpecPath(pth string) SpecOption {
|
||||||
|
return func(o *specOptions) {
|
||||||
|
o.Path = pth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSpecDocument sets the name of the JSON document served as a spec.
|
||||||
|
//
|
||||||
|
// By default, this is "swagger.json"
|
||||||
|
func WithSpecDocument(doc string) SpecOption {
|
||||||
|
return func(o *specOptions) {
|
||||||
|
if doc == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
o.Document = doc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,40 +8,65 @@ import (
|
||||||
"path"
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SwaggerUIOpts configures the Swaggerui middlewares
|
// SwaggerUIOpts configures the SwaggerUI middleware
|
||||||
type SwaggerUIOpts struct {
|
type SwaggerUIOpts struct {
|
||||||
// BasePath for the UI path, defaults to: /
|
// BasePath for the API, defaults to: /
|
||||||
BasePath string
|
BasePath string
|
||||||
// Path combines with BasePath for the full UI path, defaults to: docs
|
|
||||||
|
// Path combines with BasePath to construct the path to the UI, defaults to: "docs".
|
||||||
Path string
|
Path string
|
||||||
// SpecURL the url to find the spec for
|
|
||||||
|
// SpecURL is the URL of the spec document.
|
||||||
|
//
|
||||||
|
// Defaults to: /swagger.json
|
||||||
SpecURL string
|
SpecURL string
|
||||||
|
|
||||||
|
// Title for the documentation site, default to: API documentation
|
||||||
|
Title string
|
||||||
|
|
||||||
|
// Template specifies a custom template to serve the UI
|
||||||
|
Template string
|
||||||
|
|
||||||
// OAuthCallbackURL the url called after OAuth2 login
|
// OAuthCallbackURL the url called after OAuth2 login
|
||||||
OAuthCallbackURL string
|
OAuthCallbackURL string
|
||||||
|
|
||||||
// The three components needed to embed swagger-ui
|
// The three components needed to embed swagger-ui
|
||||||
SwaggerURL string
|
|
||||||
|
// SwaggerURL points to the js that generates the SwaggerUI site.
|
||||||
|
//
|
||||||
|
// Defaults to: https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js
|
||||||
|
SwaggerURL string
|
||||||
|
|
||||||
SwaggerPresetURL string
|
SwaggerPresetURL string
|
||||||
SwaggerStylesURL string
|
SwaggerStylesURL string
|
||||||
|
|
||||||
Favicon32 string
|
Favicon32 string
|
||||||
Favicon16 string
|
Favicon16 string
|
||||||
|
|
||||||
// Title for the documentation site, default to: API documentation
|
|
||||||
Title string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureDefaults in case some options are missing
|
// EnsureDefaults in case some options are missing
|
||||||
func (r *SwaggerUIOpts) EnsureDefaults() {
|
func (r *SwaggerUIOpts) EnsureDefaults() {
|
||||||
if r.BasePath == "" {
|
r.ensureDefaults()
|
||||||
r.BasePath = "/"
|
|
||||||
|
if r.Template == "" {
|
||||||
|
r.Template = swaggeruiTemplate
|
||||||
}
|
}
|
||||||
if r.Path == "" {
|
}
|
||||||
r.Path = "docs"
|
|
||||||
}
|
func (r *SwaggerUIOpts) EnsureDefaultsOauth2() {
|
||||||
if r.SpecURL == "" {
|
r.ensureDefaults()
|
||||||
r.SpecURL = "/swagger.json"
|
|
||||||
|
if r.Template == "" {
|
||||||
|
r.Template = swaggerOAuthTemplate
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SwaggerUIOpts) ensureDefaults() {
|
||||||
|
common := toCommonUIOptions(r)
|
||||||
|
common.EnsureDefaults()
|
||||||
|
fromCommonToAnyOptions(common, r)
|
||||||
|
|
||||||
|
// swaggerui-specifics
|
||||||
if r.OAuthCallbackURL == "" {
|
if r.OAuthCallbackURL == "" {
|
||||||
r.OAuthCallbackURL = path.Join(r.BasePath, r.Path, "oauth2-callback")
|
r.OAuthCallbackURL = path.Join(r.BasePath, r.Path, "oauth2-callback")
|
||||||
}
|
}
|
||||||
|
@ -60,40 +85,22 @@ func (r *SwaggerUIOpts) EnsureDefaults() {
|
||||||
if r.Favicon32 == "" {
|
if r.Favicon32 == "" {
|
||||||
r.Favicon32 = swaggerFavicon32Latest
|
r.Favicon32 = swaggerFavicon32Latest
|
||||||
}
|
}
|
||||||
if r.Title == "" {
|
|
||||||
r.Title = "API documentation"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SwaggerUI creates a middleware to serve a documentation site for a swagger spec.
|
// SwaggerUI creates a middleware to serve a documentation site for a swagger spec.
|
||||||
|
//
|
||||||
// This allows for altering the spec before starting the http listener.
|
// This allows for altering the spec before starting the http listener.
|
||||||
func SwaggerUI(opts SwaggerUIOpts, next http.Handler) http.Handler {
|
func SwaggerUI(opts SwaggerUIOpts, next http.Handler) http.Handler {
|
||||||
opts.EnsureDefaults()
|
opts.EnsureDefaults()
|
||||||
|
|
||||||
pth := path.Join(opts.BasePath, opts.Path)
|
pth := path.Join(opts.BasePath, opts.Path)
|
||||||
tmpl := template.Must(template.New("swaggerui").Parse(swaggeruiTemplate))
|
tmpl := template.Must(template.New("swaggerui").Parse(opts.Template))
|
||||||
|
assets := bytes.NewBuffer(nil)
|
||||||
|
if err := tmpl.Execute(assets, opts); err != nil {
|
||||||
|
panic(fmt.Errorf("cannot execute template: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(nil)
|
return serveUI(pth, assets.Bytes(), next)
|
||||||
_ = tmpl.Execute(buf, &opts)
|
|
||||||
b := buf.Bytes()
|
|
||||||
|
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
if path.Join(r.URL.Path) == pth {
|
|
||||||
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
rw.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
_, _ = rw.Write(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if next == nil {
|
|
||||||
rw.Header().Set("Content-Type", "text/plain")
|
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
|
||||||
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
next.ServeHTTP(rw, r)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -4,37 +4,20 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SwaggerUIOAuth2Callback(opts SwaggerUIOpts, next http.Handler) http.Handler {
|
func SwaggerUIOAuth2Callback(opts SwaggerUIOpts, next http.Handler) http.Handler {
|
||||||
opts.EnsureDefaults()
|
opts.EnsureDefaultsOauth2()
|
||||||
|
|
||||||
pth := opts.OAuthCallbackURL
|
pth := opts.OAuthCallbackURL
|
||||||
tmpl := template.Must(template.New("swaggeroauth").Parse(swaggerOAuthTemplate))
|
tmpl := template.Must(template.New("swaggeroauth").Parse(opts.Template))
|
||||||
|
assets := bytes.NewBuffer(nil)
|
||||||
|
if err := tmpl.Execute(assets, opts); err != nil {
|
||||||
|
panic(fmt.Errorf("cannot execute template: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(nil)
|
return serveUI(pth, assets.Bytes(), next)
|
||||||
_ = tmpl.Execute(buf, &opts)
|
|
||||||
b := buf.Bytes()
|
|
||||||
|
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
if path.Join(r.URL.Path) == pth {
|
|
||||||
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
rw.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
_, _ = rw.Write(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if next == nil {
|
|
||||||
rw.Header().Set("Content-Type", "text/plain")
|
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
|
||||||
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
next.ServeHTTP(rw, r)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/gob"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// constants that are common to all UI-serving middlewares
|
||||||
|
defaultDocsPath = "docs"
|
||||||
|
defaultDocsURL = "/swagger.json"
|
||||||
|
defaultDocsTitle = "API Documentation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// uiOptions defines common options for UI serving middlewares.
|
||||||
|
type uiOptions struct {
|
||||||
|
// BasePath for the UI, defaults to: /
|
||||||
|
BasePath string
|
||||||
|
|
||||||
|
// Path combines with BasePath to construct the path to the UI, defaults to: "docs".
|
||||||
|
Path string
|
||||||
|
|
||||||
|
// SpecURL is the URL of the spec document.
|
||||||
|
//
|
||||||
|
// Defaults to: /swagger.json
|
||||||
|
SpecURL string
|
||||||
|
|
||||||
|
// Title for the documentation site, default to: API documentation
|
||||||
|
Title string
|
||||||
|
|
||||||
|
// Template specifies a custom template to serve the UI
|
||||||
|
Template string
|
||||||
|
}
|
||||||
|
|
||||||
|
// toCommonUIOptions converts any UI option type to retain the common options.
|
||||||
|
//
|
||||||
|
// This uses gob encoding/decoding to convert common fields from one struct to another.
|
||||||
|
func toCommonUIOptions(opts interface{}) uiOptions {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
enc := gob.NewEncoder(&buf)
|
||||||
|
dec := gob.NewDecoder(&buf)
|
||||||
|
var o uiOptions
|
||||||
|
err := enc.Encode(opts)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dec.Decode(&o)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
func fromCommonToAnyOptions[T any](source uiOptions, target *T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
enc := gob.NewEncoder(&buf)
|
||||||
|
dec := gob.NewDecoder(&buf)
|
||||||
|
err := enc.Encode(source)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dec.Decode(target)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UIOption can be applied to UI serving middleware, such as Context.APIHandler or
|
||||||
|
// Context.APIHandlerSwaggerUI to alter the defaut behavior.
|
||||||
|
type UIOption func(*uiOptions)
|
||||||
|
|
||||||
|
func uiOptionsWithDefaults(opts []UIOption) uiOptions {
|
||||||
|
var o uiOptions
|
||||||
|
for _, apply := range opts {
|
||||||
|
apply(&o)
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithUIBasePath sets the base path from where to serve the UI assets.
|
||||||
|
//
|
||||||
|
// By default, Context middleware sets this value to the API base path.
|
||||||
|
func WithUIBasePath(base string) UIOption {
|
||||||
|
return func(o *uiOptions) {
|
||||||
|
if !strings.HasPrefix(base, "/") {
|
||||||
|
base = "/" + base
|
||||||
|
}
|
||||||
|
o.BasePath = base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithUIPath sets the path from where to serve the UI assets (i.e. /{basepath}/{path}.
|
||||||
|
func WithUIPath(pth string) UIOption {
|
||||||
|
return func(o *uiOptions) {
|
||||||
|
o.Path = pth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithUISpecURL sets the path from where to serve swagger spec document.
|
||||||
|
//
|
||||||
|
// This may be specified as a full URL or a path.
|
||||||
|
//
|
||||||
|
// By default, this is "/swagger.json"
|
||||||
|
func WithUISpecURL(specURL string) UIOption {
|
||||||
|
return func(o *uiOptions) {
|
||||||
|
o.SpecURL = specURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithUITitle sets the title of the UI.
|
||||||
|
//
|
||||||
|
// By default, Context middleware sets this value to the title found in the API spec.
|
||||||
|
func WithUITitle(title string) UIOption {
|
||||||
|
return func(o *uiOptions) {
|
||||||
|
o.Title = title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTemplate allows to set a custom template for the UI.
|
||||||
|
//
|
||||||
|
// UI middleware will panic if the template does not parse or execute properly.
|
||||||
|
func WithTemplate(tpl string) UIOption {
|
||||||
|
return func(o *uiOptions) {
|
||||||
|
o.Template = tpl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnsureDefaults in case some options are missing
|
||||||
|
func (r *uiOptions) EnsureDefaults() {
|
||||||
|
if r.BasePath == "" {
|
||||||
|
r.BasePath = "/"
|
||||||
|
}
|
||||||
|
if r.Path == "" {
|
||||||
|
r.Path = defaultDocsPath
|
||||||
|
}
|
||||||
|
if r.SpecURL == "" {
|
||||||
|
r.SpecURL = defaultDocsURL
|
||||||
|
}
|
||||||
|
if r.Title == "" {
|
||||||
|
r.Title = defaultDocsTitle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// serveUI creates a middleware that serves a templated asset as text/html.
|
||||||
|
func serveUI(pth string, assets []byte, next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
if path.Clean(r.URL.Path) == pth {
|
||||||
|
rw.Header().Set(contentTypeHeader, "text/html; charset=utf-8")
|
||||||
|
rw.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = rw.Write(assets)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if next != nil {
|
||||||
|
next.ServeHTTP(rw, r)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rw.Header().Set(contentTypeHeader, "text/plain")
|
||||||
|
rw.WriteHeader(http.StatusNotFound)
|
||||||
|
_, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth)))
|
||||||
|
})
|
||||||
|
}
|
|
@ -197,30 +197,31 @@ func (d *API) Validate() error {
|
||||||
|
|
||||||
// validateWith validates the registrations in this API against the provided spec analyzer
|
// validateWith validates the registrations in this API against the provided spec analyzer
|
||||||
func (d *API) validate() error {
|
func (d *API) validate() error {
|
||||||
var consumes []string
|
consumes := make([]string, 0, len(d.consumers))
|
||||||
for k := range d.consumers {
|
for k := range d.consumers {
|
||||||
consumes = append(consumes, k)
|
consumes = append(consumes, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
var produces []string
|
produces := make([]string, 0, len(d.producers))
|
||||||
for k := range d.producers {
|
for k := range d.producers {
|
||||||
produces = append(produces, k)
|
produces = append(produces, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
var authenticators []string
|
authenticators := make([]string, 0, len(d.authenticators))
|
||||||
for k := range d.authenticators {
|
for k := range d.authenticators {
|
||||||
authenticators = append(authenticators, k)
|
authenticators = append(authenticators, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
var operations []string
|
operations := make([]string, 0, len(d.operations))
|
||||||
for m, v := range d.operations {
|
for m, v := range d.operations {
|
||||||
for p := range v {
|
for p := range v {
|
||||||
operations = append(operations, fmt.Sprintf("%s %s", strings.ToUpper(m), p))
|
operations = append(operations, fmt.Sprintf("%s %s", strings.ToUpper(m), p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var definedAuths []string
|
secDefinitions := d.spec.Spec().SecurityDefinitions
|
||||||
for k := range d.spec.Spec().SecurityDefinitions {
|
definedAuths := make([]string, 0, len(secDefinitions))
|
||||||
|
for k := range secDefinitions {
|
||||||
definedAuths = append(definedAuths, k)
|
definedAuths = append(definedAuths, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +268,7 @@ func (d *API) verify(name string, registrations []string, expectations []string)
|
||||||
delete(expected, k)
|
delete(expected, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
var unregistered []string
|
unregistered := make([]string, 0, len(expected))
|
||||||
for k := range expected {
|
for k := range expected {
|
||||||
unregistered = append(unregistered, k)
|
unregistered = append(unregistered, k)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ type validation struct {
|
||||||
|
|
||||||
// ContentType validates the content type of a request
|
// ContentType validates the content type of a request
|
||||||
func validateContentType(allowed []string, actual string) error {
|
func validateContentType(allowed []string, actual string) error {
|
||||||
debugLog("validating content type for %q against [%s]", actual, strings.Join(allowed, ", "))
|
|
||||||
if len(allowed) == 0 {
|
if len(allowed) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -57,13 +56,13 @@ func validateContentType(allowed []string, actual string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *validation {
|
func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *validation {
|
||||||
debugLog("validating request %s %s", request.Method, request.URL.EscapedPath())
|
|
||||||
validate := &validation{
|
validate := &validation{
|
||||||
context: ctx,
|
context: ctx,
|
||||||
request: request,
|
request: request,
|
||||||
route: route,
|
route: route,
|
||||||
bound: make(map[string]interface{}),
|
bound: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
|
validate.debugLogf("validating request %s %s", request.Method, request.URL.EscapedPath())
|
||||||
|
|
||||||
validate.contentType()
|
validate.contentType()
|
||||||
if len(validate.result) == 0 {
|
if len(validate.result) == 0 {
|
||||||
|
@ -76,8 +75,12 @@ func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *
|
||||||
return validate
|
return validate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *validation) debugLogf(format string, args ...any) {
|
||||||
|
v.context.debugLogf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
func (v *validation) parameters() {
|
func (v *validation) parameters() {
|
||||||
debugLog("validating request parameters for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
v.debugLogf("validating request parameters for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
||||||
if result := v.route.Binder.Bind(v.request, v.route.Params, v.route.Consumer, v.bound); result != nil {
|
if result := v.route.Binder.Bind(v.request, v.route.Params, v.route.Consumer, v.bound); result != nil {
|
||||||
if result.Error() == "validation failure list" {
|
if result.Error() == "validation failure list" {
|
||||||
for _, e := range result.(*errors.Validation).Value.([]interface{}) {
|
for _, e := range result.(*errors.Validation).Value.([]interface{}) {
|
||||||
|
@ -91,7 +94,7 @@ func (v *validation) parameters() {
|
||||||
|
|
||||||
func (v *validation) contentType() {
|
func (v *validation) contentType() {
|
||||||
if len(v.result) == 0 && runtime.HasBody(v.request) {
|
if len(v.result) == 0 && runtime.HasBody(v.request) {
|
||||||
debugLog("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
v.debugLogf("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath())
|
||||||
ct, _, req, err := v.context.ContentType(v.request)
|
ct, _, req, err := v.context.ContentType(v.request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
v.result = append(v.result, err)
|
v.result = append(v.result, err)
|
||||||
|
@ -100,6 +103,7 @@ func (v *validation) contentType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(v.result) == 0 {
|
if len(v.result) == 0 {
|
||||||
|
v.debugLogf("validating content type for %q against [%s]", ct, strings.Join(v.route.Consumes, ", "))
|
||||||
if err := validateContentType(v.route.Consumes, ct); err != nil {
|
if err := validateContentType(v.route.Consumes, ct); err != nil {
|
||||||
v.result = append(v.result, err)
|
v.result = append(v.result, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -96,10 +98,16 @@ func (p *peekingReader) Read(d []byte) (int, error) {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
|
if p.underlying == nil {
|
||||||
|
return 0, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
return p.underlying.Read(d)
|
return p.underlying.Read(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peekingReader) Close() error {
|
func (p *peekingReader) Close() error {
|
||||||
|
if p.underlying == nil {
|
||||||
|
return errors.New("reader already closed")
|
||||||
|
}
|
||||||
p.underlying = nil
|
p.underlying = nil
|
||||||
if p.orig != nil {
|
if p.orig != nil {
|
||||||
return p.orig.Close()
|
return p.orig.Close()
|
||||||
|
@ -107,9 +115,11 @@ func (p *peekingReader) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONRequest creates a new http request with json headers set
|
// JSONRequest creates a new http request with json headers set.
|
||||||
|
//
|
||||||
|
// It uses context.Background.
|
||||||
func JSONRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
|
func JSONRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
|
||||||
req, err := http.NewRequest(method, urlStr, body)
|
req, err := http.NewRequestWithContext(context.Background(), method, urlStr, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
query = "query"
|
query = "query"
|
||||||
header = "header"
|
header = "header"
|
||||||
|
accessTokenParam = "access_token"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HttpAuthenticator is a function that authenticates a HTTP request
|
// HttpAuthenticator is a function that authenticates a HTTP request
|
||||||
func HttpAuthenticator(handler func(*http.Request) (bool, interface{}, error)) runtime.Authenticator {
|
func HttpAuthenticator(handler func(*http.Request) (bool, interface{}, error)) runtime.Authenticator { //nolint:revive,stylecheck
|
||||||
return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
|
return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
|
||||||
if request, ok := params.(*http.Request); ok {
|
if request, ok := params.(*http.Request); ok {
|
||||||
return handler(request)
|
return handler(request)
|
||||||
|
@ -158,7 +159,7 @@ func APIKeyAuth(name, in string, authenticate TokenAuthentication) runtime.Authe
|
||||||
inl := strings.ToLower(in)
|
inl := strings.ToLower(in)
|
||||||
if inl != query && inl != header {
|
if inl != query && inl != header {
|
||||||
// panic because this is most likely a typo
|
// panic because this is most likely a typo
|
||||||
panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\"."))
|
panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\""))
|
||||||
}
|
}
|
||||||
|
|
||||||
var getToken func(*http.Request) string
|
var getToken func(*http.Request) string
|
||||||
|
@ -186,7 +187,7 @@ func APIKeyAuthCtx(name, in string, authenticate TokenAuthenticationCtx) runtime
|
||||||
inl := strings.ToLower(in)
|
inl := strings.ToLower(in)
|
||||||
if inl != query && inl != header {
|
if inl != query && inl != header {
|
||||||
// panic because this is most likely a typo
|
// panic because this is most likely a typo
|
||||||
panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\"."))
|
panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\""))
|
||||||
}
|
}
|
||||||
|
|
||||||
var getToken func(*http.Request) string
|
var getToken func(*http.Request) string
|
||||||
|
@ -226,12 +227,12 @@ func BearerAuth(name string, authenticate ScopedTokenAuthentication) runtime.Aut
|
||||||
}
|
}
|
||||||
if token == "" {
|
if token == "" {
|
||||||
qs := r.Request.URL.Query()
|
qs := r.Request.URL.Query()
|
||||||
token = qs.Get("access_token")
|
token = qs.Get(accessTokenParam)
|
||||||
}
|
}
|
||||||
//#nosec
|
//#nosec
|
||||||
ct, _, _ := runtime.ContentType(r.Request.Header)
|
ct, _, _ := runtime.ContentType(r.Request.Header)
|
||||||
if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
|
if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
|
||||||
token = r.Request.FormValue("access_token")
|
token = r.Request.FormValue(accessTokenParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
if token == "" {
|
if token == "" {
|
||||||
|
@ -256,12 +257,12 @@ func BearerAuthCtx(name string, authenticate ScopedTokenAuthenticationCtx) runti
|
||||||
}
|
}
|
||||||
if token == "" {
|
if token == "" {
|
||||||
qs := r.Request.URL.Query()
|
qs := r.Request.URL.Query()
|
||||||
token = qs.Get("access_token")
|
token = qs.Get(accessTokenParam)
|
||||||
}
|
}
|
||||||
//#nosec
|
//#nosec
|
||||||
ct, _, _ := runtime.ContentType(r.Request.Header)
|
ct, _, _ := runtime.ContentType(r.Request.Header)
|
||||||
if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
|
if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
|
||||||
token = r.Request.FormValue("access_token")
|
token = r.Request.FormValue(accessTokenParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
if token == "" {
|
if token == "" {
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
secrets.yml
|
*.out
|
||||||
coverage.out
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ linters-settings:
|
||||||
threshold: 200
|
threshold: 200
|
||||||
goconst:
|
goconst:
|
||||||
min-len: 2
|
min-len: 2
|
||||||
min-occurrences: 2
|
min-occurrences: 3
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
|
@ -40,3 +40,22 @@ linters:
|
||||||
- tparallel
|
- tparallel
|
||||||
- thelper
|
- thelper
|
||||||
- ifshort
|
- ifshort
|
||||||
|
- exhaustruct
|
||||||
|
- varnamelen
|
||||||
|
- gci
|
||||||
|
- depguard
|
||||||
|
- errchkjson
|
||||||
|
- inamedparam
|
||||||
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
|
- ireturn
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
# deprecated linters
|
||||||
|
- deadcode
|
||||||
|
- interfacer
|
||||||
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
|
- nosnakecase
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
# OAI object model
|
# OpenAPI v2 object model [![Build Status](https://github.com/go-openapi/spec/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/spec/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/spec/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/spec)
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/go-openapi/spec.svg?branch=master)](https://travis-ci.org/go-openapi/spec)
|
|
||||||
<!-- [![Build status](https://ci.appveyor.com/api/projects/status/x377t5o9ennm847o/branch/master?svg=true)](https://ci.appveyor.com/project/casualjim/go-openapi/spec/branch/master) -->
|
|
||||||
[![codecov](https://codecov.io/gh/go-openapi/spec/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/spec)
|
|
||||||
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
||||||
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/spec/master/LICENSE)
|
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/spec/master/LICENSE)
|
||||||
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/spec.svg)](https://pkg.go.dev/github.com/go-openapi/spec)
|
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/spec.svg)](https://pkg.go.dev/github.com/go-openapi/spec)
|
||||||
|
@ -32,3 +29,26 @@ The object model for OpenAPI specification documents.
|
||||||
> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story.
|
> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story.
|
||||||
>
|
>
|
||||||
> An early attempt to support Swagger 3 may be found at: https://github.com/go-openapi/spec3
|
> An early attempt to support Swagger 3 may be found at: https://github.com/go-openapi/spec3
|
||||||
|
|
||||||
|
* Does the unmarshaling support YAML?
|
||||||
|
|
||||||
|
> Not directly. The exposed types know only how to unmarshal from JSON.
|
||||||
|
>
|
||||||
|
> In order to load a YAML document as a Swagger spec, you need to use the loaders provided by
|
||||||
|
> github.com/go-openapi/loads
|
||||||
|
>
|
||||||
|
> Take a look at the example there: https://pkg.go.dev/github.com/go-openapi/loads#example-Spec
|
||||||
|
>
|
||||||
|
> See also https://github.com/go-openapi/spec/issues/164
|
||||||
|
|
||||||
|
* How can I validate a spec?
|
||||||
|
|
||||||
|
> Validation is provided by [the validate package](http://github.com/go-openapi/validate)
|
||||||
|
|
||||||
|
* Why do we have an `ID` field for `Schema` which is not part of the swagger spec?
|
||||||
|
|
||||||
|
> We found jsonschema compatibility more important: since `id` in jsonschema influences
|
||||||
|
> how `$ref` are resolved.
|
||||||
|
> This `id` does not conflict with any property named `id`.
|
||||||
|
>
|
||||||
|
> See also https://github.com/go-openapi/spec/issues/23
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
version: "0.1.{build}"
|
|
||||||
|
|
||||||
clone_folder: C:\go-openapi\spec
|
|
||||||
shallow_clone: true # for startup speed
|
|
||||||
pull_requests:
|
|
||||||
do_not_increment_build_number: true
|
|
||||||
|
|
||||||
#skip_tags: true
|
|
||||||
#skip_branch_with_pr: true
|
|
||||||
|
|
||||||
# appveyor.yml
|
|
||||||
build: off
|
|
||||||
|
|
||||||
environment:
|
|
||||||
GOPATH: c:\gopath
|
|
||||||
|
|
||||||
stack: go 1.15
|
|
||||||
|
|
||||||
test_script:
|
|
||||||
- go test -v -timeout 20m ./...
|
|
||||||
|
|
||||||
deploy: off
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
- provider: Slack
|
|
||||||
incoming_webhook: https://hooks.slack.com/services/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
|
|
||||||
auth_token:
|
|
||||||
secure: Sf7kZf7ZGbnwWUMpffHwMu5A0cHkLK2MYY32LNTPj4+/3qC3Ghl7+9v4TSLOqOlCwdRNjOGblAq7s+GDJed6/xgRQl1JtCi1klzZNrYX4q01pgTPvvGcwbBkIYgeMaPeIRcK9OZnud7sRXdttozgTOpytps2U6Js32ip7uj5mHSg2ub0FwoSJwlS6dbezZ8+eDhoha0F/guY99BEwx8Bd+zROrT2TFGsSGOFGN6wFc7moCqTHO/YkWib13a2QNXqOxCCVBy/lt76Wp+JkeFppjHlzs/2lP3EAk13RIUAaesdEUHvIHrzCyNJEd3/+KO2DzsWOYfpktd+KBCvgaYOsoo7ubdT3IROeAegZdCgo/6xgCEsmFc9ZcqCfN5yNx2A+BZ2Vwmpws+bQ1E1+B5HDzzaiLcYfG4X2O210QVGVDLWsv1jqD+uPYeHY2WRfh5ZsIUFvaqgUEnwHwrK44/8REAhQavt1QAj5uJpsRd7CkRVPWRNK+yIky+wgbVUFEchRNmS55E7QWf+W4+4QZkQi7vUTMc9nbTUu2Es9NfvfudOpM2wZbn98fjpb/qq/nRv6Bk+ca+7XD5/IgNLMbWp2ouDdzbiHLCOfDUiHiDJhLfFZx9Bwo7ZwfzeOlbrQX66bx7xRKYmOe4DLrXhNcpbsMa8qbfxlZRCmYbubB/Y8h4=
|
|
||||||
channel: bots
|
|
||||||
on_build_success: false
|
|
||||||
on_build_failure: true
|
|
||||||
on_build_status_changed: true
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,17 @@
|
||||||
|
package spec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"path"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed schemas/*.json schemas/*/*.json
|
||||||
|
var assets embed.FS
|
||||||
|
|
||||||
|
func jsonschemaDraft04JSONBytes() ([]byte, error) {
|
||||||
|
return assets.ReadFile(path.Join("schemas", "jsonschema-draft-04.json"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func v2SchemaJSONBytes() ([]byte, error) {
|
||||||
|
return assets.ReadFile(path.Join("schemas", "v2", "schema.json"))
|
||||||
|
}
|
|
@ -27,7 +27,6 @@ import (
|
||||||
// all relative $ref's will be resolved from there.
|
// all relative $ref's will be resolved from there.
|
||||||
//
|
//
|
||||||
// PathLoader injects a document loading method. By default, this resolves to the function provided by the SpecLoader package variable.
|
// PathLoader injects a document loading method. By default, this resolves to the function provided by the SpecLoader package variable.
|
||||||
//
|
|
||||||
type ExpandOptions struct {
|
type ExpandOptions struct {
|
||||||
RelativeBase string // the path to the root document to expand. This is a file, not a directory
|
RelativeBase string // the path to the root document to expand. This is a file, not a directory
|
||||||
SkipSchemas bool // do not expand schemas, just paths, parameters and responses
|
SkipSchemas bool // do not expand schemas, just paths, parameters and responses
|
||||||
|
@ -58,7 +57,7 @@ func ExpandSpec(spec *Swagger, options *ExpandOptions) error {
|
||||||
if !options.SkipSchemas {
|
if !options.SkipSchemas {
|
||||||
for key, definition := range spec.Definitions {
|
for key, definition := range spec.Definitions {
|
||||||
parentRefs := make([]string, 0, 10)
|
parentRefs := make([]string, 0, 10)
|
||||||
parentRefs = append(parentRefs, fmt.Sprintf("#/definitions/%s", key))
|
parentRefs = append(parentRefs, "#/definitions/"+key)
|
||||||
|
|
||||||
def, err := expandSchema(definition, parentRefs, resolver, specBasePath)
|
def, err := expandSchema(definition, parentRefs, resolver, specBasePath)
|
||||||
if resolver.shouldStopOnError(err) {
|
if resolver.shouldStopOnError(err) {
|
||||||
|
@ -103,15 +102,21 @@ const rootBase = ".root"
|
||||||
|
|
||||||
// baseForRoot loads in the cache the root document and produces a fake ".root" base path entry
|
// baseForRoot loads in the cache the root document and produces a fake ".root" base path entry
|
||||||
// for further $ref resolution
|
// for further $ref resolution
|
||||||
//
|
|
||||||
// Setting the cache is optional and this parameter may safely be left to nil.
|
|
||||||
func baseForRoot(root interface{}, cache ResolutionCache) string {
|
func baseForRoot(root interface{}, cache ResolutionCache) string {
|
||||||
if root == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache the root document to resolve $ref's
|
// cache the root document to resolve $ref's
|
||||||
normalizedBase := normalizeBase(rootBase)
|
normalizedBase := normalizeBase(rootBase)
|
||||||
|
|
||||||
|
if root == nil {
|
||||||
|
// ensure that we never leave a nil root: always cache the root base pseudo-document
|
||||||
|
cachedRoot, found := cache.Get(normalizedBase)
|
||||||
|
if found && cachedRoot != nil {
|
||||||
|
// the cache is already preloaded with a root
|
||||||
|
return normalizedBase
|
||||||
|
}
|
||||||
|
|
||||||
|
root = map[string]interface{}{}
|
||||||
|
}
|
||||||
|
|
||||||
cache.Set(normalizedBase, root)
|
cache.Set(normalizedBase, root)
|
||||||
|
|
||||||
return normalizedBase
|
return normalizedBase
|
||||||
|
@ -208,7 +213,19 @@ func expandSchema(target Schema, parentRefs []string, resolver *schemaLoader, ba
|
||||||
}
|
}
|
||||||
|
|
||||||
if target.Ref.String() != "" {
|
if target.Ref.String() != "" {
|
||||||
return expandSchemaRef(target, parentRefs, resolver, basePath)
|
if !resolver.options.SkipSchemas {
|
||||||
|
return expandSchemaRef(target, parentRefs, resolver, basePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// when "expand" with SkipSchema, we just rebase the existing $ref without replacing
|
||||||
|
// the full schema.
|
||||||
|
rebasedRef, err := NewRef(normalizeURI(target.Ref.String(), basePath))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
target.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID)
|
||||||
|
|
||||||
|
return &target, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range target.Definitions {
|
for k := range target.Definitions {
|
||||||
|
@ -520,21 +537,25 @@ func getRefAndSchema(input interface{}) (*Ref, *Schema, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePath string) error {
|
func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePath string) error {
|
||||||
ref, _, err := getRefAndSchema(input)
|
ref, sch, err := getRefAndSchema(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ref == nil {
|
if ref == nil && sch == nil { // nothing to do
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
parentRefs := make([]string, 0, 10)
|
parentRefs := make([]string, 0, 10)
|
||||||
if err = resolver.deref(input, parentRefs, basePath); resolver.shouldStopOnError(err) {
|
if ref != nil {
|
||||||
return err
|
// dereference this $ref
|
||||||
|
if err = resolver.deref(input, parentRefs, basePath); resolver.shouldStopOnError(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ref, sch, _ = getRefAndSchema(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
ref, sch, _ := getRefAndSchema(input)
|
|
||||||
if ref.String() != "" {
|
if ref.String() != "" {
|
||||||
transitiveResolver := resolver.transitiveResolver(basePath, *ref)
|
transitiveResolver := resolver.transitiveResolver(basePath, *ref)
|
||||||
basePath = resolver.updateBasePath(transitiveResolver, basePath)
|
basePath = resolver.updateBasePath(transitiveResolver, basePath)
|
||||||
|
@ -546,6 +567,7 @@ func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePa
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
*ref = Ref{}
|
*ref = Ref{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,38 +577,29 @@ func expandParameterOrResponse(input interface{}, resolver *schemaLoader, basePa
|
||||||
return ern
|
return ern
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
if resolver.isCircular(&rebasedRef, basePath, parentRefs...) {
|
||||||
case resolver.isCircular(&rebasedRef, basePath, parentRefs...):
|
|
||||||
// this is a circular $ref: stop expansion
|
// this is a circular $ref: stop expansion
|
||||||
if !resolver.options.AbsoluteCircularRef {
|
if !resolver.options.AbsoluteCircularRef {
|
||||||
sch.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID)
|
sch.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID)
|
||||||
} else {
|
} else {
|
||||||
sch.Ref = rebasedRef
|
sch.Ref = rebasedRef
|
||||||
}
|
}
|
||||||
case !resolver.options.SkipSchemas:
|
|
||||||
// schema expanded to a $ref in another root
|
|
||||||
sch.Ref = rebasedRef
|
|
||||||
debugLog("rebased to: %s", sch.Ref.String())
|
|
||||||
default:
|
|
||||||
// skip schema expansion but rebase $ref to schema
|
|
||||||
sch.Ref = denormalizeRef(&rebasedRef, resolver.context.basePath, resolver.context.rootID)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// $ref expansion or rebasing is performed by expandSchema below
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
*ref = Ref{}
|
*ref = Ref{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand schema
|
// expand schema
|
||||||
if !resolver.options.SkipSchemas {
|
// yes, we do it even if options.SkipSchema is true: we have to go down that rabbit hole and rebase nested $ref)
|
||||||
s, err := expandSchema(*sch, parentRefs, resolver, basePath)
|
s, err := expandSchema(*sch, parentRefs, resolver, basePath)
|
||||||
if resolver.shouldStopOnError(err) {
|
if resolver.shouldStopOnError(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if s == nil {
|
|
||||||
// guard for when continuing on error
|
if s != nil { // guard for when continuing on error
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*sch = *s
|
*sch = *s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,5 +40,5 @@ func repairURI(in string) (*url.URL, string) {
|
||||||
return u, ""
|
return u, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func fixWindowsURI(u *url.URL, in string) {
|
func fixWindowsURI(_ *url.URL, _ string) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,9 +217,12 @@ func (o *Operation) AddParam(param *Parameter) *Operation {
|
||||||
|
|
||||||
for i, p := range o.Parameters {
|
for i, p := range o.Parameters {
|
||||||
if p.Name == param.Name && p.In == param.In {
|
if p.Name == param.Name && p.In == param.In {
|
||||||
params := append(o.Parameters[:i], *param)
|
params := make([]Parameter, 0, len(o.Parameters)+1)
|
||||||
|
params = append(params, o.Parameters[:i]...)
|
||||||
|
params = append(params, *param)
|
||||||
params = append(params, o.Parameters[i+1:]...)
|
params = append(params, o.Parameters[i+1:]...)
|
||||||
o.Parameters = params
|
o.Parameters = params
|
||||||
|
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,27 +84,27 @@ type ParamProps struct {
|
||||||
// Parameter a unique parameter is defined by a combination of a [name](#parameterName) and [location](#parameterIn).
|
// Parameter a unique parameter is defined by a combination of a [name](#parameterName) and [location](#parameterIn).
|
||||||
//
|
//
|
||||||
// There are five possible parameter types.
|
// There are five possible parameter types.
|
||||||
// * Path - Used together with [Path Templating](#pathTemplating), where the parameter value is actually part
|
// - Path - Used together with [Path Templating](#pathTemplating), where the parameter value is actually part
|
||||||
// of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`,
|
// of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`,
|
||||||
// the path parameter is `itemId`.
|
// the path parameter is `itemId`.
|
||||||
// * Query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`.
|
// - Query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`.
|
||||||
// * Header - Custom headers that are expected as part of the request.
|
// - Header - Custom headers that are expected as part of the request.
|
||||||
// * Body - The payload that's appended to the HTTP request. Since there can only be one payload, there can only be
|
// - Body - The payload that's appended to the HTTP request. Since there can only be one payload, there can only be
|
||||||
// _one_ body parameter. The name of the body parameter has no effect on the parameter itself and is used for
|
// _one_ body parameter. The name of the body parameter has no effect on the parameter itself and is used for
|
||||||
// documentation purposes only. Since Form parameters are also in the payload, body and form parameters cannot exist
|
// documentation purposes only. Since Form parameters are also in the payload, body and form parameters cannot exist
|
||||||
// together for the same operation.
|
// together for the same operation.
|
||||||
// * Form - Used to describe the payload of an HTTP request when either `application/x-www-form-urlencoded` or
|
// - Form - Used to describe the payload of an HTTP request when either `application/x-www-form-urlencoded` or
|
||||||
// `multipart/form-data` are used as the content type of the request (in Swagger's definition,
|
// `multipart/form-data` are used as the content type of the request (in Swagger's definition,
|
||||||
// the [`consumes`](#operationConsumes) property of an operation). This is the only parameter type that can be used
|
// the [`consumes`](#operationConsumes) property of an operation). This is the only parameter type that can be used
|
||||||
// to send files, thus supporting the `file` type. Since form parameters are sent in the payload, they cannot be
|
// to send files, thus supporting the `file` type. Since form parameters are sent in the payload, they cannot be
|
||||||
// declared together with a body parameter for the same operation. Form parameters have a different format based on
|
// declared together with a body parameter for the same operation. Form parameters have a different format based on
|
||||||
// the content-type used (for further details, consult http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4).
|
// the content-type used (for further details, consult http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4).
|
||||||
// * `application/x-www-form-urlencoded` - Similar to the format of Query parameters but as a payload.
|
// - `application/x-www-form-urlencoded` - Similar to the format of Query parameters but as a payload.
|
||||||
// For example, `foo=1&bar=swagger` - both `foo` and `bar` are form parameters. This is normally used for simple
|
// For example, `foo=1&bar=swagger` - both `foo` and `bar` are form parameters. This is normally used for simple
|
||||||
// parameters that are being transferred.
|
// parameters that are being transferred.
|
||||||
// * `multipart/form-data` - each parameter takes a section in the payload with an internal header.
|
// - `multipart/form-data` - each parameter takes a section in the payload with an internal header.
|
||||||
// For example, for the header `Content-Disposition: form-data; name="submit-name"` the name of the parameter is
|
// For example, for the header `Content-Disposition: form-data; name="submit-name"` the name of the parameter is
|
||||||
// `submit-name`. This type of form parameters is more commonly used for file transfers.
|
// `submit-name`. This type of form parameters is more commonly used for file transfers.
|
||||||
//
|
//
|
||||||
// For more information: http://goo.gl/8us55a#parameterObject
|
// For more information: http://goo.gl/8us55a#parameterObject
|
||||||
type Parameter struct {
|
type Parameter struct {
|
||||||
|
|
|
@ -168,14 +168,7 @@ func (r *schemaLoader) load(refURL *url.URL) (interface{}, url.URL, bool, error)
|
||||||
normalized := normalizeBase(pth)
|
normalized := normalizeBase(pth)
|
||||||
debugLog("loading doc from: %s", normalized)
|
debugLog("loading doc from: %s", normalized)
|
||||||
|
|
||||||
unescaped, err := url.PathUnescape(normalized)
|
data, fromCache := r.cache.Get(normalized)
|
||||||
if err != nil {
|
|
||||||
return nil, url.URL{}, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
u := url.URL{Path: unescaped}
|
|
||||||
|
|
||||||
data, fromCache := r.cache.Get(u.RequestURI())
|
|
||||||
if fromCache {
|
if fromCache {
|
||||||
return data, toFetch, fromCache, nil
|
return data, toFetch, fromCache, nil
|
||||||
}
|
}
|
||||||
|
|
149
vendor/github.com/go-openapi/spec/schemas/jsonschema-draft-04.json
generated
vendored
Normal file
149
vendor/github.com/go-openapi/spec/schemas/jsonschema-draft-04.json
generated
vendored
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
{
|
||||||
|
"id": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"description": "Core schema meta-schema",
|
||||||
|
"definitions": {
|
||||||
|
"schemaArray": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": { "$ref": "#" }
|
||||||
|
},
|
||||||
|
"positiveInteger": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"positiveIntegerDefault0": {
|
||||||
|
"allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ]
|
||||||
|
},
|
||||||
|
"simpleTypes": {
|
||||||
|
"enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
|
||||||
|
},
|
||||||
|
"stringArray": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "type": "string" },
|
||||||
|
"minItems": 1,
|
||||||
|
"uniqueItems": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"$schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"default": {},
|
||||||
|
"multipleOf": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0,
|
||||||
|
"exclusiveMinimum": true
|
||||||
|
},
|
||||||
|
"maximum": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"exclusiveMaximum": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"minimum": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"exclusiveMinimum": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"maxLength": { "$ref": "#/definitions/positiveInteger" },
|
||||||
|
"minLength": { "$ref": "#/definitions/positiveIntegerDefault0" },
|
||||||
|
"pattern": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "regex"
|
||||||
|
},
|
||||||
|
"additionalItems": {
|
||||||
|
"anyOf": [
|
||||||
|
{ "type": "boolean" },
|
||||||
|
{ "$ref": "#" }
|
||||||
|
],
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"anyOf": [
|
||||||
|
{ "$ref": "#" },
|
||||||
|
{ "$ref": "#/definitions/schemaArray" }
|
||||||
|
],
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
|
"maxItems": { "$ref": "#/definitions/positiveInteger" },
|
||||||
|
"minItems": { "$ref": "#/definitions/positiveIntegerDefault0" },
|
||||||
|
"uniqueItems": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"maxProperties": { "$ref": "#/definitions/positiveInteger" },
|
||||||
|
"minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" },
|
||||||
|
"required": { "$ref": "#/definitions/stringArray" },
|
||||||
|
"additionalProperties": {
|
||||||
|
"anyOf": [
|
||||||
|
{ "type": "boolean" },
|
||||||
|
{ "$ref": "#" }
|
||||||
|
],
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": { "$ref": "#" },
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": { "$ref": "#" },
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
|
"patternProperties": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": { "$ref": "#" },
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"anyOf": [
|
||||||
|
{ "$ref": "#" },
|
||||||
|
{ "$ref": "#/definitions/stringArray" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enum": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"uniqueItems": true
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"anyOf": [
|
||||||
|
{ "$ref": "#/definitions/simpleTypes" },
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/definitions/simpleTypes" },
|
||||||
|
"minItems": 1,
|
||||||
|
"uniqueItems": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"format": { "type": "string" },
|
||||||
|
"allOf": { "$ref": "#/definitions/schemaArray" },
|
||||||
|
"anyOf": { "$ref": "#/definitions/schemaArray" },
|
||||||
|
"oneOf": { "$ref": "#/definitions/schemaArray" },
|
||||||
|
"not": { "$ref": "#" }
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"exclusiveMaximum": [ "maximum" ],
|
||||||
|
"exclusiveMinimum": [ "minimum" ]
|
||||||
|
},
|
||||||
|
"default": {}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -26,7 +26,7 @@ import (
|
||||||
const (
|
const (
|
||||||
// SwaggerSchemaURL the url for the swagger 2.0 schema to validate specs
|
// SwaggerSchemaURL the url for the swagger 2.0 schema to validate specs
|
||||||
SwaggerSchemaURL = "http://swagger.io/v2/schema.json#"
|
SwaggerSchemaURL = "http://swagger.io/v2/schema.json#"
|
||||||
// JSONSchemaURL the url for the json schema schema
|
// JSONSchemaURL the url for the json schema
|
||||||
JSONSchemaURL = "http://json-schema.org/draft-04/schema#"
|
JSONSchemaURL = "http://json-schema.org/draft-04/schema#"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ func MustLoadJSONSchemaDraft04() *Schema {
|
||||||
|
|
||||||
// JSONSchemaDraft04 loads the json schema document for json shema draft04
|
// JSONSchemaDraft04 loads the json schema document for json shema draft04
|
||||||
func JSONSchemaDraft04() (*Schema, error) {
|
func JSONSchemaDraft04() (*Schema, error) {
|
||||||
b, err := Asset("jsonschema-draft-04.json")
|
b, err := jsonschemaDraft04JSONBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ func MustLoadSwagger20Schema() *Schema {
|
||||||
// Swagger20Schema loads the swagger 2.0 schema from the embedded assets
|
// Swagger20Schema loads the swagger 2.0 schema from the embedded assets
|
||||||
func Swagger20Schema() (*Schema, error) {
|
func Swagger20Schema() (*Schema, error) {
|
||||||
|
|
||||||
b, err := Asset("v2/schema.json")
|
b, err := v2SchemaJSONBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,7 +253,7 @@ func (s SchemaOrBool) MarshalJSON() ([]byte, error) {
|
||||||
// UnmarshalJSON converts this bool or schema object from a JSON structure
|
// UnmarshalJSON converts this bool or schema object from a JSON structure
|
||||||
func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
|
func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
|
||||||
var nw SchemaOrBool
|
var nw SchemaOrBool
|
||||||
if len(data) >= 4 {
|
if len(data) > 0 {
|
||||||
if data[0] == '{' {
|
if data[0] == '{' {
|
||||||
var sch Schema
|
var sch Schema
|
||||||
if err := json.Unmarshal(data, &sch); err != nil {
|
if err := json.Unmarshal(data, &sch); err != nil {
|
||||||
|
@ -261,7 +261,7 @@ func (s *SchemaOrBool) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
nw.Schema = &sch
|
nw.Schema = &sch
|
||||||
}
|
}
|
||||||
nw.Allows = !(data[0] == 'f' && data[1] == 'a' && data[2] == 'l' && data[3] == 's' && data[4] == 'e')
|
nw.Allows = !bytes.Equal(data, []byte("false"))
|
||||||
}
|
}
|
||||||
*s = nw
|
*s = nw
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
//go:build !go1.19
|
|
||||||
// +build !go1.19
|
|
||||||
|
|
||||||
package spec
|
|
||||||
|
|
||||||
import "net/url"
|
|
||||||
|
|
||||||
var parseURL = url.Parse
|
|
|
@ -1,6 +1,3 @@
|
||||||
//go:build go1.19
|
|
||||||
// +build go1.19
|
|
||||||
|
|
||||||
package spec
|
package spec
|
||||||
|
|
||||||
import "net/url"
|
import "net/url"
|
||||||
|
|
|
@ -4,56 +4,58 @@ linters-settings:
|
||||||
golint:
|
golint:
|
||||||
min-confidence: 0
|
min-confidence: 0
|
||||||
gocyclo:
|
gocyclo:
|
||||||
min-complexity: 31
|
min-complexity: 45
|
||||||
maligned:
|
maligned:
|
||||||
suggest-new: true
|
suggest-new: true
|
||||||
dupl:
|
dupl:
|
||||||
threshold: 100
|
threshold: 200
|
||||||
goconst:
|
goconst:
|
||||||
min-len: 2
|
min-len: 2
|
||||||
min-occurrences: 4
|
min-occurrences: 3
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable-all: true
|
||||||
- revive
|
disable:
|
||||||
- goimports
|
- maligned
|
||||||
- gosec
|
|
||||||
- unparam
|
- unparam
|
||||||
- unconvert
|
- lll
|
||||||
- predeclared
|
- gochecknoinits
|
||||||
- prealloc
|
- gochecknoglobals
|
||||||
- misspell
|
- funlen
|
||||||
|
- godox
|
||||||
# disable:
|
- gocognit
|
||||||
# - maligned
|
- whitespace
|
||||||
# - lll
|
- wsl
|
||||||
# - gochecknoinits
|
- wrapcheck
|
||||||
# - gochecknoglobals
|
- testpackage
|
||||||
# - godox
|
- nlreturn
|
||||||
# - gocognit
|
- gomnd
|
||||||
# - whitespace
|
- exhaustivestruct
|
||||||
# - wsl
|
- goerr113
|
||||||
# - funlen
|
- errorlint
|
||||||
# - wrapcheck
|
- nestif
|
||||||
# - testpackage
|
- godot
|
||||||
# - nlreturn
|
- gofumpt
|
||||||
# - gofumpt
|
- paralleltest
|
||||||
# - goerr113
|
- tparallel
|
||||||
# - gci
|
- thelper
|
||||||
# - gomnd
|
- ifshort
|
||||||
# - godot
|
- exhaustruct
|
||||||
# - exhaustivestruct
|
- varnamelen
|
||||||
# - paralleltest
|
- gci
|
||||||
# - varnamelen
|
- depguard
|
||||||
# - ireturn
|
- errchkjson
|
||||||
# - exhaustruct
|
- inamedparam
|
||||||
# #- thelper
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
issues:
|
- ireturn
|
||||||
exclude-rules:
|
- forcetypeassert
|
||||||
- path: bson.go
|
- cyclop
|
||||||
text: "should be .*ObjectID"
|
# deprecated linters
|
||||||
linters:
|
- deadcode
|
||||||
- golint
|
- interfacer
|
||||||
- stylecheck
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
|
- nosnakecase
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
# Strfmt [![Build Status](https://travis-ci.org/go-openapi/strfmt.svg?branch=master)](https://travis-ci.org/go-openapi/strfmt) [![codecov](https://codecov.io/gh/go-openapi/strfmt/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/strfmt) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
# Strfmt [![Build Status](https://github.com/go-openapi/strfmt/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/strfmt/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/strfmt/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/strfmt)
|
||||||
|
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
||||||
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/strfmt/master/LICENSE)
|
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/strfmt/master/LICENSE)
|
||||||
[![GoDoc](https://godoc.org/github.com/go-openapi/strfmt?status.svg)](http://godoc.org/github.com/go-openapi/strfmt)
|
[![GoDoc](https://godoc.org/github.com/go-openapi/strfmt?status.svg)](http://godoc.org/github.com/go-openapi/strfmt)
|
||||||
[![GolangCI](https://golangci.com/badges/github.com/go-openapi/strfmt.svg)](https://golangci.com)
|
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/strfmt)](https://goreportcard.com/report/github.com/go-openapi/strfmt)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/strfmt)](https://goreportcard.com/report/github.com/go-openapi/strfmt)
|
||||||
|
|
||||||
This package exposes a registry of data types to support string formats in the go-openapi toolkit.
|
This package exposes a registry of data types to support string formats in the go-openapi toolkit.
|
||||||
|
|
|
@ -39,10 +39,10 @@ func IsBSONObjectID(str string) bool {
|
||||||
// ObjectId represents a BSON object ID (alias to go.mongodb.org/mongo-driver/bson/primitive.ObjectID)
|
// ObjectId represents a BSON object ID (alias to go.mongodb.org/mongo-driver/bson/primitive.ObjectID)
|
||||||
//
|
//
|
||||||
// swagger:strfmt bsonobjectid
|
// swagger:strfmt bsonobjectid
|
||||||
type ObjectId bsonprim.ObjectID //nolint:revive
|
type ObjectId bsonprim.ObjectID //nolint:revive,stylecheck
|
||||||
|
|
||||||
// NewObjectId creates a ObjectId from a Hex String
|
// NewObjectId creates a ObjectId from a Hex String
|
||||||
func NewObjectId(hex string) ObjectId { //nolint:revive
|
func NewObjectId(hex string) ObjectId { //nolint:revive,stylecheck
|
||||||
oid, err := bsonprim.ObjectIDFromHex(hex)
|
oid, err := bsonprim.ObjectIDFromHex(hex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -135,7 +135,7 @@ func (id *ObjectId) UnmarshalBSON(data []byte) error {
|
||||||
// BSON document if the error is nil.
|
// BSON document if the error is nil.
|
||||||
func (id ObjectId) MarshalBSONValue() (bsontype.Type, []byte, error) {
|
func (id ObjectId) MarshalBSONValue() (bsontype.Type, []byte, error) {
|
||||||
oid := bsonprim.ObjectID(id)
|
oid := bsonprim.ObjectID(id)
|
||||||
return bsontype.ObjectID, oid[:], nil
|
return bson.TypeObjectID, oid[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalBSONValue is an interface implemented by types that can unmarshal a
|
// UnmarshalBSONValue is an interface implemented by types that can unmarshal a
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
|
"github.com/google/uuid"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,24 +58,35 @@ const (
|
||||||
// - long top-level domain names (e.g. example.london) are permitted
|
// - long top-level domain names (e.g. example.london) are permitted
|
||||||
// - symbol unicode points are permitted (e.g. emoji) (not for top-level domain)
|
// - symbol unicode points are permitted (e.g. emoji) (not for top-level domain)
|
||||||
HostnamePattern = `^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z\p{L}]){2,63})$`
|
HostnamePattern = `^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z\p{L}]){2,63})$`
|
||||||
// UUIDPattern Regex for UUID that allows uppercase
|
|
||||||
UUIDPattern = `(?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$`
|
|
||||||
// UUID3Pattern Regex for UUID3 that allows uppercase
|
|
||||||
UUID3Pattern = `(?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$`
|
|
||||||
// UUID4Pattern Regex for UUID4 that allows uppercase
|
|
||||||
UUID4Pattern = `(?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$`
|
|
||||||
// UUID5Pattern Regex for UUID5 that allows uppercase
|
|
||||||
UUID5Pattern = `(?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$`
|
|
||||||
// json null type
|
// json null type
|
||||||
jsonNull = "null"
|
jsonNull = "null"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// UUIDPattern Regex for UUID that allows uppercase
|
||||||
|
//
|
||||||
|
// Deprecated: strfmt no longer uses regular expressions to validate UUIDs.
|
||||||
|
UUIDPattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(^[0-9a-f]{32}$)`
|
||||||
|
|
||||||
|
// UUID3Pattern Regex for UUID3 that allows uppercase
|
||||||
|
//
|
||||||
|
// Deprecated: strfmt no longer uses regular expressions to validate UUIDs.
|
||||||
|
UUID3Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$)|(^[0-9a-f]{12}3[0-9a-f]{3}?[0-9a-f]{16}$)`
|
||||||
|
|
||||||
|
// UUID4Pattern Regex for UUID4 that allows uppercase
|
||||||
|
//
|
||||||
|
// Deprecated: strfmt no longer uses regular expressions to validate UUIDs.
|
||||||
|
UUID4Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$)|(^[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}$)`
|
||||||
|
|
||||||
|
// UUID5Pattern Regex for UUID5 that allows uppercase
|
||||||
|
//
|
||||||
|
// Deprecated: strfmt no longer uses regular expressions to validate UUIDs.
|
||||||
|
UUID5Pattern = `(?i)(^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$)|(^[0-9a-f]{12}5[0-9a-f]{3}[89ab][0-9a-f]{15}$)`
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rxHostname = regexp.MustCompile(HostnamePattern)
|
rxHostname = regexp.MustCompile(HostnamePattern)
|
||||||
rxUUID = regexp.MustCompile(UUIDPattern)
|
|
||||||
rxUUID3 = regexp.MustCompile(UUID3Pattern)
|
|
||||||
rxUUID4 = regexp.MustCompile(UUID4Pattern)
|
|
||||||
rxUUID5 = regexp.MustCompile(UUID5Pattern)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsHostname returns true when the string is a valid hostname
|
// IsHostname returns true when the string is a valid hostname
|
||||||
|
@ -99,24 +111,28 @@ func IsHostname(str string) bool {
|
||||||
return valid
|
return valid
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUUID returns true is the string matches a UUID, upper case is allowed
|
// IsUUID returns true is the string matches a UUID (in any version, including v6 and v7), upper case is allowed
|
||||||
func IsUUID(str string) bool {
|
func IsUUID(str string) bool {
|
||||||
return rxUUID.MatchString(str)
|
_, err := uuid.Parse(str)
|
||||||
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUUID3 returns true is the string matches a UUID, upper case is allowed
|
// IsUUID3 returns true is the string matches a UUID v3, upper case is allowed
|
||||||
func IsUUID3(str string) bool {
|
func IsUUID3(str string) bool {
|
||||||
return rxUUID3.MatchString(str)
|
id, err := uuid.Parse(str)
|
||||||
|
return err == nil && id.Version() == uuid.Version(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUUID4 returns true is the string matches a UUID, upper case is allowed
|
// IsUUID4 returns true is the string matches a UUID v4, upper case is allowed
|
||||||
func IsUUID4(str string) bool {
|
func IsUUID4(str string) bool {
|
||||||
return rxUUID4.MatchString(str)
|
id, err := uuid.Parse(str)
|
||||||
|
return err == nil && id.Version() == uuid.Version(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUUID5 returns true is the string matches a UUID, upper case is allowed
|
// IsUUID5 returns true is the string matches a UUID v5, upper case is allowed
|
||||||
func IsUUID5(str string) bool {
|
func IsUUID5(str string) bool {
|
||||||
return rxUUID5.MatchString(str)
|
id, err := uuid.Parse(str)
|
||||||
|
return err == nil && id.Version() == uuid.Version(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmail validates an email address.
|
// IsEmail validates an email address.
|
||||||
|
|
|
@ -16,6 +16,7 @@ package strfmt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding"
|
"encoding"
|
||||||
|
stderrors "errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -94,7 +95,7 @@ func NewSeededFormats(seeds []knownFormat, normalizer NameNormalizer) Registry {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapStructureHookFunc is a decode hook function for mapstructure
|
// MapStructureHookFunc is a decode hook function for mapstructure
|
||||||
func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { //nolint:gocyclo,cyclop
|
func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc {
|
||||||
return func(from reflect.Type, to reflect.Type, obj interface{}) (interface{}, error) {
|
return func(from reflect.Type, to reflect.Type, obj interface{}) (interface{}, error) {
|
||||||
if from.Kind() != reflect.String {
|
if from.Kind() != reflect.String {
|
||||||
return obj, nil
|
return obj, nil
|
||||||
|
@ -117,7 +118,7 @@ func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { //
|
||||||
case "datetime":
|
case "datetime":
|
||||||
input := data
|
input := data
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
return nil, fmt.Errorf("empty string is an invalid datetime format")
|
return nil, stderrors.New("empty string is an invalid datetime format")
|
||||||
}
|
}
|
||||||
return ParseDateTime(input)
|
return ParseDateTime(input)
|
||||||
case "duration":
|
case "duration":
|
||||||
|
|
|
@ -76,6 +76,8 @@ const (
|
||||||
ISO8601TimeWithReducedPrecisionLocaltime = "2006-01-02T15:04"
|
ISO8601TimeWithReducedPrecisionLocaltime = "2006-01-02T15:04"
|
||||||
// ISO8601TimeUniversalSortableDateTimePattern represents a ISO8601 universal sortable date time pattern.
|
// ISO8601TimeUniversalSortableDateTimePattern represents a ISO8601 universal sortable date time pattern.
|
||||||
ISO8601TimeUniversalSortableDateTimePattern = "2006-01-02 15:04:05"
|
ISO8601TimeUniversalSortableDateTimePattern = "2006-01-02 15:04:05"
|
||||||
|
// short form of ISO8601TimeUniversalSortableDateTimePattern
|
||||||
|
ISO8601TimeUniversalSortableDateTimePatternShortForm = "2006-01-02"
|
||||||
// DateTimePattern pattern to match for the date-time format from http://tools.ietf.org/html/rfc3339#section-5.6
|
// DateTimePattern pattern to match for the date-time format from http://tools.ietf.org/html/rfc3339#section-5.6
|
||||||
DateTimePattern = `^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$`
|
DateTimePattern = `^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$`
|
||||||
)
|
)
|
||||||
|
@ -84,7 +86,7 @@ var (
|
||||||
rxDateTime = regexp.MustCompile(DateTimePattern)
|
rxDateTime = regexp.MustCompile(DateTimePattern)
|
||||||
|
|
||||||
// DateTimeFormats is the collection of formats used by ParseDateTime()
|
// DateTimeFormats is the collection of formats used by ParseDateTime()
|
||||||
DateTimeFormats = []string{RFC3339Micro, RFC3339MicroNoColon, RFC3339Millis, RFC3339MillisNoColon, time.RFC3339, time.RFC3339Nano, ISO8601LocalTime, ISO8601TimeWithReducedPrecision, ISO8601TimeWithReducedPrecisionLocaltime, ISO8601TimeUniversalSortableDateTimePattern}
|
DateTimeFormats = []string{RFC3339Micro, RFC3339MicroNoColon, RFC3339Millis, RFC3339MillisNoColon, time.RFC3339, time.RFC3339Nano, ISO8601LocalTime, ISO8601TimeWithReducedPrecision, ISO8601TimeWithReducedPrecisionLocaltime, ISO8601TimeUniversalSortableDateTimePattern, ISO8601TimeUniversalSortableDateTimePatternShortForm}
|
||||||
|
|
||||||
// MarshalFormat sets the time resolution format used for marshaling time (set to milliseconds)
|
// MarshalFormat sets the time resolution format used for marshaling time (set to milliseconds)
|
||||||
MarshalFormat = RFC3339Millis
|
MarshalFormat = RFC3339Millis
|
||||||
|
@ -245,7 +247,7 @@ func (t DateTime) MarshalBSONValue() (bsontype.Type, []byte, error) {
|
||||||
buf := make([]byte, 8)
|
buf := make([]byte, 8)
|
||||||
binary.LittleEndian.PutUint64(buf, uint64(i64))
|
binary.LittleEndian.PutUint64(buf, uint64(i64))
|
||||||
|
|
||||||
return bsontype.DateTime, buf, nil
|
return bson.TypeDateTime, buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalBSONValue is an interface implemented by types that can unmarshal a
|
// UnmarshalBSONValue is an interface implemented by types that can unmarshal a
|
||||||
|
@ -253,7 +255,7 @@ func (t DateTime) MarshalBSONValue() (bsontype.Type, []byte, error) {
|
||||||
// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it
|
// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it
|
||||||
// wishes to retain the data after returning.
|
// wishes to retain the data after returning.
|
||||||
func (t *DateTime) UnmarshalBSONValue(tpe bsontype.Type, data []byte) error {
|
func (t *DateTime) UnmarshalBSONValue(tpe bsontype.Type, data []byte) error {
|
||||||
if tpe == bsontype.Null {
|
if tpe == bson.TypeNull {
|
||||||
*t = DateTime{}
|
*t = DateTime{}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,3 +2,4 @@ secrets.yml
|
||||||
vendor
|
vendor
|
||||||
Godeps
|
Godeps
|
||||||
.idea
|
.idea
|
||||||
|
*.out
|
||||||
|
|
|
@ -4,14 +4,14 @@ linters-settings:
|
||||||
golint:
|
golint:
|
||||||
min-confidence: 0
|
min-confidence: 0
|
||||||
gocyclo:
|
gocyclo:
|
||||||
min-complexity: 25
|
min-complexity: 45
|
||||||
maligned:
|
maligned:
|
||||||
suggest-new: true
|
suggest-new: true
|
||||||
dupl:
|
dupl:
|
||||||
threshold: 100
|
threshold: 200
|
||||||
goconst:
|
goconst:
|
||||||
min-len: 3
|
min-len: 3
|
||||||
min-occurrences: 2
|
min-occurrences: 3
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
|
@ -20,35 +20,41 @@ linters:
|
||||||
- lll
|
- lll
|
||||||
- gochecknoinits
|
- gochecknoinits
|
||||||
- gochecknoglobals
|
- gochecknoglobals
|
||||||
- nlreturn
|
- funlen
|
||||||
- testpackage
|
- godox
|
||||||
|
- gocognit
|
||||||
|
- whitespace
|
||||||
|
- wsl
|
||||||
- wrapcheck
|
- wrapcheck
|
||||||
|
- testpackage
|
||||||
|
- nlreturn
|
||||||
- gomnd
|
- gomnd
|
||||||
- exhaustive
|
|
||||||
- exhaustivestruct
|
- exhaustivestruct
|
||||||
- goerr113
|
- goerr113
|
||||||
- wsl
|
- errorlint
|
||||||
- whitespace
|
|
||||||
- gofumpt
|
|
||||||
- godot
|
|
||||||
- nestif
|
- nestif
|
||||||
- godox
|
- godot
|
||||||
- funlen
|
- gofumpt
|
||||||
- gci
|
|
||||||
- gocognit
|
|
||||||
- paralleltest
|
- paralleltest
|
||||||
|
- tparallel
|
||||||
- thelper
|
- thelper
|
||||||
- ifshort
|
- ifshort
|
||||||
- gomoddirectives
|
|
||||||
- cyclop
|
|
||||||
- forcetypeassert
|
|
||||||
- ireturn
|
|
||||||
- tagliatelle
|
|
||||||
- varnamelen
|
|
||||||
- goimports
|
|
||||||
- tenv
|
|
||||||
- golint
|
|
||||||
- exhaustruct
|
- exhaustruct
|
||||||
- nilnil
|
- varnamelen
|
||||||
|
- gci
|
||||||
|
- depguard
|
||||||
|
- errchkjson
|
||||||
|
- inamedparam
|
||||||
- nonamedreturns
|
- nonamedreturns
|
||||||
|
- musttag
|
||||||
|
- ireturn
|
||||||
|
- forcetypeassert
|
||||||
|
- cyclop
|
||||||
|
# deprecated linters
|
||||||
|
- deadcode
|
||||||
|
- interfacer
|
||||||
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- golint
|
||||||
- nosnakecase
|
- nosnakecase
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue