diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 51fbc24..f118ccd 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -21,7 +21,7 @@ env: GO111MODULE: "on" CACHE_BENCHMARK: "off" # Enables benchmark result reuse between runs, may skew latency results. RUN_BASE_BENCHMARK: "on" # Runs benchmark for PR base in case benchmark result is missing. - GO_VERSION: 1.21.x + GO_VERSION: 1.22.x jobs: bench: runs-on: ubuntu-latest diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index d2e4b61..6239219 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -21,13 +21,13 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.21.x + go-version: 1.22.x - uses: actions/checkout@v2 - name: golangci-lint - uses: golangci/golangci-lint-action@v3.7.0 + uses: golangci/golangci-lint-action@v4.0.0 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.54.1 + version: v1.56.2 # Optional: working directory, useful for monorepos # working-directory: somedir diff --git a/.github/workflows/gorelease.yml b/.github/workflows/gorelease.yml index 97ebe87..6356a9d 100644 --- a/.github/workflows/gorelease.yml +++ b/.github/workflows/gorelease.yml @@ -9,7 +9,7 @@ concurrency: cancel-in-progress: true env: - GO_VERSION: 1.21.x + GO_VERSION: 1.22.x jobs: gorelease: runs-on: ubuntu-latest diff --git a/.github/workflows/test-unit.yml b/.github/workflows/test-unit.yml index 1f61fb8..7eb27c9 100644 --- a/.github/workflows/test-unit.yml +++ b/.github/workflows/test-unit.yml @@ -15,13 +15,13 @@ concurrency: env: GO111MODULE: "on" RUN_BASE_COVERAGE: "on" # Runs test for PR base in case base test coverage is missing. - COV_GO_VERSION: 1.21.x # Version of Go to collect coverage + COV_GO_VERSION: 1.22.x # Version of Go to collect coverage TARGET_DELTA_COV: 90 # Target coverage of changed lines, in percents jobs: test: strategy: matrix: - go-version: [ 1.13.x, 1.20.x, 1.21.x ] + go-version: [ 1.13.x, 1.21.x, 1.22.x ] runs-on: ubuntu-latest steps: - name: Install Go stable @@ -88,9 +88,9 @@ jobs: id: annotate if: matrix.go-version == env.COV_GO_VERSION && github.event.pull_request.base.sha != '' run: | - curl -sLO https://github.com/vearutop/gocovdiff/releases/download/v1.4.0/linux_amd64.tar.gz && tar xf linux_amd64.tar.gz && rm linux_amd64.tar.gz + curl -sLO https://github.com/vearutop/gocovdiff/releases/download/v1.4.2/linux_amd64.tar.gz && tar xf linux_amd64.tar.gz && rm linux_amd64.tar.gz gocovdiff_hash=$(git hash-object ./gocovdiff) - [ "$gocovdiff_hash" == "f191b45548bb65ec2c7d88909679a57116ff1ba1" ] || (echo "::error::unexpected hash for gocovdiff, possible tampering: $gocovdiff_hash" && exit 1) + [ "$gocovdiff_hash" == "c37862c73a677e5a9c069470287823ab5bbf0244" ] || (echo "::error::unexpected hash for gocovdiff, possible tampering: $gocovdiff_hash" && exit 1) git fetch origin master ${{ github.event.pull_request.base.sha }} REP=$(./gocovdiff -mod github.com/$GITHUB_REPOSITORY -cov unit.coverprofile -gha-annotations gha-unit.txt -delta-cov-file delta-cov-unit.txt -target-delta-cov ${TARGET_DELTA_COV}) echo "${REP}" diff --git a/.golangci.yml b/.golangci.yml index 6f8655e..3dcca94 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -73,5 +73,6 @@ issues: - linters: - errcheck # Error checking omitted for brevity. - gosec + - revive path: "example_" diff --git a/Makefile b/Makefile index 73ced0a..9d78891 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -#GOLANGCI_LINT_VERSION := "v1.54.1" # Optional configuration to pinpoint golangci-lint version. +#GOLANGCI_LINT_VERSION := "v1.56.2" # Optional configuration to pinpoint golangci-lint version. # The head of Makefile determines location of dev-go to include standard targets. GO ?= go diff --git a/_examples/advanced-generic-openapi31/_testdata/openapi.json b/_examples/advanced-generic-openapi31/_testdata/openapi.json index 3ef2188..103c613 100644 --- a/_examples/advanced-generic-openapi31/_testdata/openapi.json +++ b/_examples/advanced-generic-openapi31/_testdata/openapi.json @@ -915,17 +915,17 @@ "simple":{"description":"Simple scalar value in body.","type":"string"}, "uploads1":{ "description":"Uploads with *multipart.FileHeader.", - "items":{"$ref":"#/components/schemas/MultipartFileHeader"},"type":["array","null"] + "items":{"$ref":"#/components/schemas/MultipartFileHeader"},"type":"array" }, "uploads2":{ "description":"Uploads with multipart.File.","items":{"$ref":"#/components/schemas/MultipartFile"}, - "type":["array","null"] + "type":"array" } }, "type":"object" }, - "MultipartFile":{"format":"binary","type":["null","string"]}, - "MultipartFileHeader":{"format":"binary","type":["null","string"]}, + "MultipartFile":{"contentMediaType":"application/octet-stream","format":"binary","type":"string"}, + "MultipartFileHeader":{"contentMediaType":"application/octet-stream","format":"binary","type":"string"}, "RestErrResponse":{ "properties":{ "code":{"description":"Application-specific error code.","type":"integer"}, diff --git a/_examples/advanced/_testdata/openapi.json b/_examples/advanced/_testdata/openapi.json index 8602e49..13351c0 100644 --- a/_examples/advanced/_testdata/openapi.json +++ b/_examples/advanced/_testdata/openapi.json @@ -728,17 +728,16 @@ "simple":{"type":"string","description":"Simple scalar value in body."}, "uploads1":{ "type":"array","items":{"$ref":"#/components/schemas/MultipartFileHeader"}, - "description":"Uploads with *multipart.FileHeader.","nullable":true + "description":"Uploads with *multipart.FileHeader." }, "uploads2":{ "type":"array","items":{"$ref":"#/components/schemas/MultipartFile"}, - "description":"Uploads with multipart.File.","nullable":true + "description":"Uploads with multipart.File." } }, "additionalProperties":false }, - "MultipartFile":{"type":"string","format":"binary","nullable":true}, - "MultipartFileHeader":{"type":"string","format":"binary","nullable":true}, + "MultipartFile":{"type":"string","format":"binary"},"MultipartFileHeader":{"type":"string","format":"binary"}, "RestErrResponse":{ "type":"object", "properties":{ diff --git a/_examples/go.mod b/_examples/go.mod index 7875314..395d380 100644 --- a/_examples/go.mod +++ b/_examples/go.mod @@ -6,27 +6,27 @@ replace github.com/swaggest/rest => ../ require ( github.com/bool64/ctxd v1.2.1 - github.com/bool64/dev v0.2.32 + github.com/bool64/dev v0.2.34 github.com/bool64/httpmock v0.1.13 github.com/bool64/httptestbench v0.1.4 github.com/gin-gonic/gin v1.9.1 - github.com/go-chi/chi/v5 v5.0.10 - github.com/go-chi/jwtauth/v5 v5.1.1 - github.com/google/uuid v1.3.0 + github.com/go-chi/chi/v5 v5.0.12 + github.com/go-chi/jwtauth/v5 v5.3.0 + github.com/google/uuid v1.6.0 github.com/kelseyhightower/envconfig v1.4.0 - github.com/rs/cors v1.9.0 - github.com/stretchr/testify v1.8.4 + github.com/rs/cors v1.10.1 + github.com/stretchr/testify v1.9.0 github.com/swaggest/assertjson v1.9.0 - github.com/swaggest/jsonschema-go v0.3.64 - github.com/swaggest/openapi-go v0.2.43 + github.com/swaggest/jsonschema-go v0.3.66 + github.com/swaggest/openapi-go v0.2.46 github.com/swaggest/rest v0.0.0-00010101000000-000000000000 - github.com/swaggest/swgui v1.7.3 - github.com/swaggest/usecase v1.3.0 - github.com/valyala/fasthttp v1.48.0 + github.com/swaggest/swgui v1.8.0 + github.com/swaggest/usecase v1.3.1 + github.com/valyala/fasthttp v1.52.0 ) require ( - github.com/andybalholm/brotli v1.0.5 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/bool64/shared v0.1.5 // indirect github.com/bytedance/sonic v1.9.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect @@ -42,14 +42,14 @@ require ( github.com/goccy/go-json v0.10.2 // indirect github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.7 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/leodido/go-urn v1.2.4 // indirect - github.com/lestrrat-go/blackmagic v1.0.1 // indirect + github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.4 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect - github.com/lestrrat-go/jwx/v2 v2.0.11 // indirect + github.com/lestrrat-go/jwx/v2 v2.0.20 // indirect github.com/lestrrat-go/option v1.0.1 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -70,10 +70,10 @@ require ( github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/crypto v0.10.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.9.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/crypto v0.20.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/_examples/go.sum b/_examples/go.sum index c68d7ee..b181883 100644 --- a/_examples/go.sum +++ b/_examples/go.sum @@ -1,11 +1,11 @@ -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.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/bool64/ctxd v1.2.1 h1:hARFteq0zdn4bwfmxLhak3fXFuvtJVKDH2X29VV/2ls= github.com/bool64/ctxd v1.2.1/go.mod h1:ZG6QkeGVLTiUl2mxPpyHmFhDzFZCyocr9hluBV3LYuc= github.com/bool64/dev v0.2.5/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU= github.com/bool64/dev v0.2.25/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= -github.com/bool64/dev v0.2.32 h1:DRZtloaoH1Igky3zphaUHV9+SLIV2H3lsf78JsJHFg0= -github.com/bool64/dev v0.2.32/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= +github.com/bool64/dev v0.2.34 h1:P9n315P8LdpxusnYQ0X7MP1CZXwBK5ae5RZrd+GdSZE= +github.com/bool64/dev v0.2.34/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/httpmock v0.1.13 h1:3QpRXQ5kwHLW8xnVT8+Ug7VS6RerhdEFV+RWYC61aVo= github.com/bool64/httpmock v0.1.13/go.mod h1:YMTLaypQ3o5DAx78eA/kDRSLec0f+42sLMDmHdmeY+E= github.com/bool64/httptestbench v0.1.4 h1:35f9RwWqcnQRXM+sA+GUhWVGSa6XEFlKpNSH9oYzOjI= @@ -23,7 +23,6 @@ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583j github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= @@ -34,10 +33,10 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/jwtauth/v5 v5.1.1 h1:Pjixqu5YkjE9sCLpzE01L0Q4sQzJIPdo7uz9r8ftp/c= -github.com/go-chi/jwtauth/v5 v5.1.1/go.mod h1:CYP1WSbzD4MPuKCr537EM3kfFhSQgpUEtMJFuYJjqWU= +github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= +github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/jwtauth/v5 v5.3.0 h1:X7RKGks1lrVeIe2omGyz47pNaNjG2YmwlRN5UKhN8qg= +github.com/go-chi/jwtauth/v5 v5.3.0/go.mod h1:2PoGm/KbnzRN9ILY6HFZAI6fTnb1gEZAKogAyqkd6fY= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= @@ -51,16 +50,16 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= @@ -71,17 +70,16 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= -github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= +github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k= +github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8= github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= -github.com/lestrrat-go/jwx/v2 v2.0.11 h1:ViHMnaMeaO0qV16RZWBHM7GTrAnX2aFLVKofc7FuKLQ= -github.com/lestrrat-go/jwx/v2 v2.0.11/go.mod h1:ZtPtMFlrfDrH2Y0iwfa3dRFn8VzwBrB+cyrm3IBWdDg= -github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/lestrrat-go/jwx/v2 v2.0.20 h1:sAgXuWS/t8ykxS9Bi2Qtn5Qhpakw1wrcjxChudjolCc= +github.com/lestrrat-go/jwx/v2 v2.0.20/go.mod h1:UlCSmKqw+agm5BsOBfEAbTvKsEApaGNqHAEUTv5PJC4= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= @@ -99,8 +97,8 @@ github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= -github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/santhosh-tekuri/jsonschema/v3 v3.1.0 h1:levPcBfnazlA1CyCMC3asL/QLZkq9pa8tQZOH513zQw= github.com/santhosh-tekuri/jsonschema/v3 v3.1.0/go.mod h1:8kzK2TC0k0YjOForaAHdNEa7ik0fokNa2k30BKJ/W7Y= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= @@ -119,30 +117,30 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ= github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU= github.com/swaggest/form/v5 v5.1.1 h1:ct6/rOQBGrqWUQ0FUv3vW5sHvTUb31AwTUWj947N6cY= github.com/swaggest/form/v5 v5.1.1/go.mod h1:X1hraaoONee20PMnGNLQpO32f9zbQ0Czfm7iZThuEKg= -github.com/swaggest/jsonschema-go v0.3.64 h1:HyB41fkA4XP0BZkqWfGap5i2JtRHQGXG/21dGDPbyLM= -github.com/swaggest/jsonschema-go v0.3.64/go.mod h1:DYuKqdpms/edvywsX6p1zHXCZkdwB28wRaBdFCe3Duw= -github.com/swaggest/openapi-go v0.2.43 h1:nuNr60vmsx4pxIh1NoaIKrruh+pVba6iXjF+dXlTLAk= -github.com/swaggest/openapi-go v0.2.43/go.mod h1:/ykzNtS1ZO7X43OnEtyisMktxCiawQLyGd08rkjV68U= +github.com/swaggest/jsonschema-go v0.3.66 h1:4c5d7NRRqPLTswsbaypKqcMe3Z+CYHE3/lGsPIByp8o= +github.com/swaggest/jsonschema-go v0.3.66/go.mod h1:7N43/CwdaWgPUDfYV70K7Qm79tRqe/al7gLSt9YeGIE= +github.com/swaggest/openapi-go v0.2.46 h1:T7gCeErrNLu93aACb2/IacAPAe/lOcGz141a1+LYEx8= +github.com/swaggest/openapi-go v0.2.46/go.mod h1:MK5O26lG289kFgMOyXK1VXDoTZ89KJ8Vt0v0ic23zZw= github.com/swaggest/refl v1.3.0 h1:PEUWIku+ZznYfsoyheF97ypSduvMApYyGkYF3nabS0I= github.com/swaggest/refl v1.3.0/go.mod h1:3Ujvbmh1pfSbDYjC6JGG7nMgPvpG0ehQL4iNonnLNbg= -github.com/swaggest/swgui v1.7.3 h1:e1Du/3kqvR5HxL41M4pdkJhsADHtuyWpahl8tdcPStM= -github.com/swaggest/swgui v1.7.3/go.mod h1:FP9uIPTB/QqVs2ZbOD6zc5yTw8SDTJfftak5f4ZRqOQ= -github.com/swaggest/usecase v1.3.0 h1:Zte74uCWQYeGradJbxlhOrqi77K/GMK16VYTIjyenoA= -github.com/swaggest/usecase v1.3.0/go.mod h1:cae3lDd5VDmM36OQcOOOdAlEDg40TiQYIp99S9ejWqA= +github.com/swaggest/swgui v1.8.0 h1:dPu8TsYIOraaObAkyNdoiLI8mu7nOqQ6SU7HOv254rM= +github.com/swaggest/swgui v1.8.0/go.mod h1:YBaAVAwS3ndfvdtW8A4yWDJpge+W57y+8kW+f/DqZtU= +github.com/swaggest/usecase v1.3.1 h1:JdKV30MTSsDxAXxkldLNcEn8O2uf565khyo6gr5sS+w= +github.com/swaggest/usecase v1.3.1/go.mod h1:cae3lDd5VDmM36OQcOOOdAlEDg40TiQYIp99S9ejWqA= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.48.0 h1:oJWvHb9BIZToTQS3MuQ2R3bJZiNSa2KiNdeI8A+79Tc= -github.com/valyala/fasthttp v1.48.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= +github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0= +github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= github.com/vearutop/dynhist-go v1.1.0 h1:kufNShpt45I97L2eO3bEYTSPKBSued0prheukJUYRok= github.com/vearutop/dynhist-go v1.1.0/go.mod h1:mjWlwr64oGBtouxh8s/9YOXV73MYP0Q9tfKIAp8/xto= github.com/vearutop/statigz v1.4.0 h1:RQL0KG3j/uyA/PFpHeZ/L6l2ta920/MxlOAIGEOuwmU= @@ -154,54 +152,20 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= +golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/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-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= diff --git a/_examples/jwtauth/main.go b/_examples/jwtauth/main.go index e60b4d3..f464394 100644 --- a/_examples/jwtauth/main.go +++ b/_examples/jwtauth/main.go @@ -111,7 +111,7 @@ func router() http.Handler { r.Group(func(r chi.Router) { r.Use( jwtauth.Verifier(tokenAuth), - jwtauth.Authenticator, + jwtauth.Authenticator(tokenAuth), ) r.Method(http.MethodGet, "/", nethttp.NewHandler(Get())) diff --git a/_examples/mount/main.go b/_examples/mount/main.go index ed38729..0279ac6 100644 --- a/_examples/mount/main.go +++ b/_examples/mount/main.go @@ -7,6 +7,7 @@ import ( "net/http" "github.com/go-chi/chi/v5/middleware" + "github.com/swaggest/openapi-go" "github.com/swaggest/openapi-go/openapi3" "github.com/swaggest/rest/nethttp" "github.com/swaggest/rest/web" @@ -36,30 +37,50 @@ func sum() usecase.Interactor { }) } -func main() { - service := web.NewService(openapi3.NewReflector()) - service.OpenAPISchema().SetTitle("Security and Mount Example") +func service() *web.Service { + s := web.NewService(openapi3.NewReflector()) + s.OpenAPISchema().SetTitle("Security and Mount Example") - apiV1 := web.NewService(service.OpenAPIReflector()) + apiV1 := web.NewService(openapi3.NewReflector()) + apiV2 := web.NewService(openapi3.NewReflector()) apiV1.Wrap( middleware.BasicAuth("Admin Access", map[string]string{"admin": "admin"}), - nethttp.HTTPBasicSecurityMiddleware(service.OpenAPICollector, "Admin", "Admin access"), + nethttp.HTTPBasicSecurityMiddleware(s.OpenAPICollector, "Admin", "Admin access"), + nethttp.OpenAPIAnnotationsMiddleware(s.OpenAPICollector, func(oc openapi.OperationContext) error { + oc.SetTags(append(oc.Tags(), "V1")...) + return nil + }), ) - apiV1.Post("/sum", sum()) apiV1.Post("/mul", mul()) - service.Mount("/api/v1", apiV1) - service.Docs("/api/v1/docs", swgui.New) + apiV2.Wrap( + // No auth for V2. + + nethttp.OpenAPIAnnotationsMiddleware(s.OpenAPICollector, func(oc openapi.OperationContext) error { + oc.SetTags(append(oc.Tags(), "V2")...) + return nil + }), + ) + apiV2.Post("/summarization", sum()) + apiV2.Post("/multiplication", mul()) + + s.Mount("/api/v1", apiV1) + s.Mount("/api/v2", apiV2) + s.Docs("/api/docs", swgui.New) // Blanket handler, for example to serve static content. - service.Mount("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.Mount("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte("blanket handler got a request: " + r.URL.String())) })) - fmt.Println("Swagger UI at http://localhost:8010/api/v1/docs.") - if err := http.ListenAndServe("localhost:8010", service); err != nil { + return s +} + +func main() { + fmt.Println("Swagger UI at http://localhost:8010/api/docs.") + if err := http.ListenAndServe("localhost:8010", service()); err != nil { log.Fatal(err) } } diff --git a/_examples/mount/main_test.go b/_examples/mount/main_test.go new file mode 100644 index 0000000..4892019 --- /dev/null +++ b/_examples/mount/main_test.go @@ -0,0 +1,129 @@ +package main + +import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/swaggest/assertjson" +) + +func Test_service(t *testing.T) { + s := service() + + rw := httptest.NewRecorder() + r, err := http.NewRequest(http.MethodGet, "/api/docs/openapi.json", nil) + require.NoError(t, err) + + s.ServeHTTP(rw, r) + assertjson.EqMarshal(t, `{ + "openapi":"3.0.3","info":{"title":"Security and Mount Example","version":""}, + "paths":{ + "/api/v1/mul":{ + "post":{ + "tags":["V1"],"summary":"Mul","operationId":"_examples/mount.mul", + "requestBody":{ + "content":{ + "application/json":{"schema":{"type":"array","items":{"type":"integer"}}} + } + }, + "responses":{ + "200":{ + "description":"OK", + "content":{"application/json":{"schema":{"type":"integer"}}} + }, + "401":{ + "description":"Unauthorized", + "content":{ + "application/json":{"schema":{"$ref":"#/components/schemas/RestErrResponse"}} + } + } + }, + "security":[{"Admin":[]}] + } + }, + "/api/v1/sum":{ + "post":{ + "tags":["V1"],"summary":"Sum","operationId":"_examples/mount.sum", + "requestBody":{ + "content":{ + "application/json":{"schema":{"type":"array","items":{"type":"integer"}}} + } + }, + "responses":{ + "200":{ + "description":"OK", + "content":{"application/json":{"schema":{"type":"integer"}}} + }, + "401":{ + "description":"Unauthorized", + "content":{ + "application/json":{"schema":{"$ref":"#/components/schemas/RestErrResponse"}} + } + } + }, + "security":[{"Admin":[]}] + } + }, + "/api/v2/multiplication":{ + "post":{ + "tags":["V2"],"summary":"Mul","operationId":"_examples/mount.mul2", + "requestBody":{ + "content":{ + "application/json":{"schema":{"type":"array","items":{"type":"integer"}}} + } + }, + "responses":{ + "200":{ + "description":"OK", + "content":{"application/json":{"schema":{"type":"integer"}}} + } + } + } + }, + "/api/v2/summarization":{ + "post":{ + "tags":["V2"],"summary":"Sum","operationId":"_examples/mount.sum2", + "requestBody":{ + "content":{ + "application/json":{"schema":{"type":"array","items":{"type":"integer"}}} + } + }, + "responses":{ + "200":{ + "description":"OK", + "content":{"application/json":{"schema":{"type":"integer"}}} + } + } + } + } + }, + "components":{ + "schemas":{ + "RestErrResponse":{ + "type":"object", + "properties":{ + "code":{"type":"integer","description":"Application-specific error code."}, + "context":{ + "type":"object","additionalProperties":{}, + "description":"Application context." + }, + "error":{"type":"string","description":"Error message."}, + "status":{"type":"string","description":"Status text."} + } + } + }, + "securitySchemes":{"Admin":{"type":"http","scheme":"basic","description":"Admin access"}} + } + }`, json.RawMessage(rw.Body.Bytes())) + + rw = httptest.NewRecorder() + r, err = http.NewRequest(http.MethodPost, "/api/v2/multiplication", bytes.NewReader([]byte(`[1,2,3]`))) + + s.ServeHTTP(rw, r) + assert.Equal(t, "6\n", rw.Body.String()) +} diff --git a/chirouter/example_test.go b/chirouter/example_test.go index d969e88..a5f5e8a 100644 --- a/chirouter/example_test.go +++ b/chirouter/example_test.go @@ -35,7 +35,7 @@ func ExamplePathToURLValues() { router := chi.NewRouter() // Now in router handler you can decode *http.Request into a Go structure. - router.Handle("/foo/{path1}/bar/{path2}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + router.Handle("/foo/{path1}/bar/{path2}", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { var in myRequest _ = dec.Decode(r, &in, nil) diff --git a/chirouter/wrapper_test.go b/chirouter/wrapper_test.go index 0ff0d39..4c4e76a 100644 --- a/chirouter/wrapper_test.go +++ b/chirouter/wrapper_test.go @@ -80,12 +80,12 @@ func TestNewWrapper(t *testing.T) { r.Use(mw) - r.NotFound(r.(*chirouter.Wrapper).HandlerFunc(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))) + r.NotFound(r.(*chirouter.Wrapper).HandlerFunc(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}))) r.Group(func(r chi.Router) { r.Method(http.MethodPost, "/baz/{id}/", - HandlerWithFoo{Handler: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + HandlerWithFoo{Handler: http.HandlerFunc(func(_ http.ResponseWriter, request *http.Request) { val, err := chirouter.PathToURLValues(request) assert.NoError(t, err) assert.Equal(t, url.Values{"id": []string{"123"}}, val) @@ -94,7 +94,7 @@ func TestNewWrapper(t *testing.T) { }) r.Mount("/mount", - HandlerWithFoo{Handler: http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {})}, + HandlerWithFoo{Handler: http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {})}, ) r.Route("/deeper", func(r chi.Router) { @@ -102,19 +102,19 @@ func TestNewWrapper(t *testing.T) { return HandlerWithFoo{Handler: handler} }) - r.Get("/foo", func(writer http.ResponseWriter, request *http.Request) {}) - r.Head("/foo", func(writer http.ResponseWriter, request *http.Request) {}) - r.Post("/foo", func(writer http.ResponseWriter, request *http.Request) {}) - r.Put("/foo", func(writer http.ResponseWriter, request *http.Request) {}) - r.Trace("/foo", func(writer http.ResponseWriter, request *http.Request) {}) - r.Connect("/foo", func(writer http.ResponseWriter, request *http.Request) {}) - r.Options("/foo", func(writer http.ResponseWriter, request *http.Request) {}) - r.Patch("/foo", func(writer http.ResponseWriter, request *http.Request) {}) - r.Delete("/foo", func(writer http.ResponseWriter, request *http.Request) {}) + r.Get("/foo", func(_ http.ResponseWriter, _ *http.Request) {}) + r.Head("/foo", func(_ http.ResponseWriter, _ *http.Request) {}) + r.Post("/foo", func(_ http.ResponseWriter, _ *http.Request) {}) + r.Put("/foo", func(_ http.ResponseWriter, _ *http.Request) {}) + r.Trace("/foo", func(_ http.ResponseWriter, _ *http.Request) {}) + r.Connect("/foo", func(_ http.ResponseWriter, _ *http.Request) {}) + r.Options("/foo", func(_ http.ResponseWriter, _ *http.Request) {}) + r.Patch("/foo", func(_ http.ResponseWriter, _ *http.Request) {}) + r.Delete("/foo", func(_ http.ResponseWriter, _ *http.Request) {}) - r.MethodFunc(http.MethodGet, "/cuux", func(writer http.ResponseWriter, request *http.Request) {}) + r.MethodFunc(http.MethodGet, "/cuux", func(_ http.ResponseWriter, _ *http.Request) {}) - r.Handle("/bar", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {})) + r.Handle("/bar", http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {})) }) for _, u := range []string{"/baz/123/", "/deeper/foo", "/mount/abc"} { @@ -140,7 +140,9 @@ func TestWrapper_Use_precedence(t *testing.T) { func(handler http.Handler) http.Handler { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { log = append(log, "cmw1 before") + handler.ServeHTTP(writer, request) + log = append(log, "cmw1 after") }) }, @@ -148,7 +150,9 @@ func TestWrapper_Use_precedence(t *testing.T) { func(handler http.Handler) http.Handler { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { log = append(log, "cmw2 before") + handler.ServeHTTP(writer, request) + log = append(log, "cmw2 after") }) }, @@ -160,7 +164,9 @@ func TestWrapper_Use_precedence(t *testing.T) { func(handler http.Handler) http.Handler { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { log = append(log, "wmw1 before") + handler.ServeHTTP(writer, request) + log = append(log, "wmw1 after") }) }, @@ -168,7 +174,9 @@ func TestWrapper_Use_precedence(t *testing.T) { func(handler http.Handler) http.Handler { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { log = append(log, "wmw2 before") + handler.ServeHTTP(writer, request) + log = append(log, "wmw2 after") }) }, @@ -177,7 +185,7 @@ func TestWrapper_Use_precedence(t *testing.T) { req, err := http.NewRequest(http.MethodGet, "/", nil) require.NoError(t, err) - h := http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + h := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { log = append(log, "h") }) @@ -238,7 +246,7 @@ func TestWrapper_Use_StripSlashes(t *testing.T) { rw := httptest.NewRecorder() - h := http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + h := http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) { if _, err := writer.Write([]byte("OK")); err != nil { log = append(log, err.Error()) } @@ -276,7 +284,7 @@ func TestWrapper_Mount(t *testing.T) { nethttp.HTTPBasicSecurityMiddleware(service.OpenAPICollector, "Admin", "Admin access"), ) - apiV1.Post("/sum", usecase.NewIOI(new([]int), new(int), func(ctx context.Context, input, output interface{}) error { + apiV1.Post("/sum", usecase.NewIOI(new([]int), new(int), func(_ context.Context, _, _ interface{}) error { return errors.New("oops") })) @@ -387,7 +395,7 @@ func TestWrapper_With(t *testing.T) { cw.Use(wrapper, notWrapper) cw.With(wrapper, notWrapper).Method(http.MethodGet, "/", - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {})) assert.Equal(t, 2, wrapperCalled) assert.Equal(t, 2, wrapperFound) diff --git a/go.mod b/go.mod index b6df15f..a21e629 100644 --- a/go.mod +++ b/go.mod @@ -3,20 +3,20 @@ module github.com/swaggest/rest go 1.17 require ( - github.com/bool64/dev v0.2.32 + github.com/bool64/dev v0.2.34 github.com/bool64/httpmock v0.1.13 github.com/bool64/shared v0.1.5 github.com/cespare/xxhash/v2 v2.2.0 - github.com/go-chi/chi/v5 v5.0.10 - github.com/gorilla/mux v1.8.0 + github.com/go-chi/chi/v5 v5.0.12 + github.com/gorilla/mux v1.8.1 github.com/santhosh-tekuri/jsonschema/v3 v3.1.0 github.com/stretchr/testify v1.8.2 github.com/swaggest/assertjson v1.9.0 github.com/swaggest/form/v5 v5.1.1 - github.com/swaggest/jsonschema-go v0.3.64 - github.com/swaggest/openapi-go v0.2.43 + github.com/swaggest/jsonschema-go v0.3.66 + github.com/swaggest/openapi-go v0.2.46 github.com/swaggest/refl v1.3.0 - github.com/swaggest/usecase v1.3.0 + github.com/swaggest/usecase v1.3.1 ) require ( diff --git a/go.sum b/go.sum index 50a5c4d..b800645 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,9 @@ github.com/bool64/dev v0.2.25/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8 github.com/bool64/dev v0.2.27/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/dev v0.2.29/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/dev v0.2.31/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= -github.com/bool64/dev v0.2.32 h1:DRZtloaoH1Igky3zphaUHV9+SLIV2H3lsf78JsJHFg0= github.com/bool64/dev v0.2.32/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= +github.com/bool64/dev v0.2.34 h1:P9n315P8LdpxusnYQ0X7MP1CZXwBK5ae5RZrd+GdSZE= +github.com/bool64/dev v0.2.34/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/httpmock v0.1.13 h1:3QpRXQ5kwHLW8xnVT8+Ug7VS6RerhdEFV+RWYC61aVo= github.com/bool64/httpmock v0.1.13/go.mod h1:YMTLaypQ3o5DAx78eA/kDRSLec0f+42sLMDmHdmeY+E= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= @@ -17,8 +18,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= +github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -30,8 +31,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= @@ -77,14 +78,14 @@ github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7 github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU= github.com/swaggest/form/v5 v5.1.1 h1:ct6/rOQBGrqWUQ0FUv3vW5sHvTUb31AwTUWj947N6cY= github.com/swaggest/form/v5 v5.1.1/go.mod h1:X1hraaoONee20PMnGNLQpO32f9zbQ0Czfm7iZThuEKg= -github.com/swaggest/jsonschema-go v0.3.64 h1:HyB41fkA4XP0BZkqWfGap5i2JtRHQGXG/21dGDPbyLM= -github.com/swaggest/jsonschema-go v0.3.64/go.mod h1:DYuKqdpms/edvywsX6p1zHXCZkdwB28wRaBdFCe3Duw= -github.com/swaggest/openapi-go v0.2.43 h1:nuNr60vmsx4pxIh1NoaIKrruh+pVba6iXjF+dXlTLAk= -github.com/swaggest/openapi-go v0.2.43/go.mod h1:/ykzNtS1ZO7X43OnEtyisMktxCiawQLyGd08rkjV68U= +github.com/swaggest/jsonschema-go v0.3.66 h1:4c5d7NRRqPLTswsbaypKqcMe3Z+CYHE3/lGsPIByp8o= +github.com/swaggest/jsonschema-go v0.3.66/go.mod h1:7N43/CwdaWgPUDfYV70K7Qm79tRqe/al7gLSt9YeGIE= +github.com/swaggest/openapi-go v0.2.46 h1:T7gCeErrNLu93aACb2/IacAPAe/lOcGz141a1+LYEx8= +github.com/swaggest/openapi-go v0.2.46/go.mod h1:MK5O26lG289kFgMOyXK1VXDoTZ89KJ8Vt0v0ic23zZw= github.com/swaggest/refl v1.3.0 h1:PEUWIku+ZznYfsoyheF97ypSduvMApYyGkYF3nabS0I= github.com/swaggest/refl v1.3.0/go.mod h1:3Ujvbmh1pfSbDYjC6JGG7nMgPvpG0ehQL4iNonnLNbg= -github.com/swaggest/usecase v1.3.0 h1:Zte74uCWQYeGradJbxlhOrqi77K/GMK16VYTIjyenoA= -github.com/swaggest/usecase v1.3.0/go.mod h1:cae3lDd5VDmM36OQcOOOdAlEDg40TiQYIp99S9ejWqA= +github.com/swaggest/usecase v1.3.1 h1:JdKV30MTSsDxAXxkldLNcEn8O2uf565khyo6gr5sS+w= +github.com/swaggest/usecase v1.3.1/go.mod h1:cae3lDd5VDmM36OQcOOOdAlEDg40TiQYIp99S9ejWqA= github.com/yosuke-furukawa/json5 v0.1.2-0.20201207051438-cf7bb3f354ff h1:7YqG491bE4vstXRz1lD38rbSgbXnirvROz1lZiOnPO8= github.com/yosuke-furukawa/json5 v0.1.2-0.20201207051438-cf7bb3f354ff/go.mod h1:sw49aWDqNdRJ6DYUtIQiaA3xyj2IL9tjeNYmX2ixwcU= github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= diff --git a/gzip/container_test.go b/gzip/container_test.go index 89fa113..2ad11ab 100644 --- a/gzip/container_test.go +++ b/gzip/container_test.go @@ -49,7 +49,7 @@ func TestWriteJSON(t *testing.T) { var ur interface{} = cont u.Output = new(interface{}) - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, _, output interface{}) error { *output.(*interface{}) = ur return nil diff --git a/nethttp/handler.go b/nethttp/handler.go index a9456ca..9b081b0 100644 --- a/nethttp/handler.go +++ b/nethttp/handler.go @@ -126,7 +126,6 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } err = h.useCase.Interact(r.Context(), input, output) - if err != nil { h.handleErrResponse(w, r, err) diff --git a/nethttp/handler_test.go b/nethttp/handler_test.go index 6e0d224..feab71b 100644 --- a/nethttp/handler_test.go +++ b/nethttp/handler_test.go @@ -35,7 +35,7 @@ func TestHandler_ServeHTTP(t *testing.T) { u.Input = new(Input) u.Output = new(Output) - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, input, output interface{}) error { in, ok := input.(*Input) require.True(t, ok) require.NotNil(t, in) @@ -56,7 +56,7 @@ func TestHandler_ServeHTTP(t *testing.T) { validatorCalled := false h := nethttp.NewHandler(u, func(h *nethttp.Handler) { - h.ReqValidator = rest.ValidatorFunc(func(in rest.ParamIn, namedData map[string]interface{}) error { + h.ReqValidator = rest.ValidatorFunc(func(_ rest.ParamIn, _ map[string]interface{}) error { validatorCalled = true return nil @@ -71,7 +71,9 @@ func TestHandler_ServeHTTP(t *testing.T) { h.SetRequestDecoder(request.DecoderFunc( func(r *http.Request, input interface{}, validator rest.Validator) error { assert.Equal(t, req, r) + in, ok := input.(*Input) + require.True(t, ok) require.NotNil(t, in) @@ -116,7 +118,7 @@ func TestHandler_ServeHTTP_decodeErr(t *testing.T) { u.Input = new(Input) u.Output = new(Output) - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, _, _ interface{}) error { assert.Fail(t, "should not be called") return nil @@ -127,7 +129,7 @@ func TestHandler_ServeHTTP_decodeErr(t *testing.T) { uh := nethttp.NewHandler(u) uh.SetRequestDecoder(request.DecoderFunc( - func(r *http.Request, input interface{}, validator rest.Validator) error { + func(_ *http.Request, _ interface{}, _ rest.Validator) error { return errors.New("failed to decode request") }, )) @@ -156,7 +158,7 @@ func TestHandler_ServeHTTP_emptyPorts(t *testing.T) { usecase.Interactor }{} - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, input, output interface{}) error { assert.Nil(t, input) assert.Nil(t, output) @@ -182,7 +184,7 @@ func TestHandler_ServeHTTP_customErrResp(t *testing.T) { usecase.OutputWithNoContent }{} - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, input, output interface{}) error { assert.Nil(t, input) assert.Nil(t, output) @@ -190,7 +192,7 @@ func TestHandler_ServeHTTP_customErrResp(t *testing.T) { }) h := nethttp.NewHandler(u) - h.MakeErrResp = func(ctx context.Context, err error) (int, interface{}) { + h.MakeErrResp = func(_ context.Context, err error) (int, interface{}) { return http.StatusExpectationFailed, struct { Custom string `json:"custom"` }{ @@ -213,7 +215,7 @@ func TestHandlerWithRouteMiddleware(t *testing.T) { called := false var h http.Handler - h = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + h = http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { called = true }) @@ -242,7 +244,7 @@ func TestHandler_ServeHTTP_getWithBody(t *testing.T) { u.Input = new(reqWithBody) - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, input, output interface{}) error { in, ok := input.(*reqWithBody) assert.True(t, ok) assert.Equal(t, 123, in.ID) @@ -273,7 +275,7 @@ func TestHandler_ServeHTTP_customMapping(t *testing.T) { }{} u.Input = new(Input) - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, input, _ interface{}) error { in, ok := input.(*Input) assert.True(t, ok) assert.Equal(t, 123, in.ID) @@ -309,11 +311,11 @@ func TestHandler_ServeHTTP_customMapping(t *testing.T) { } func TestOptionsMiddleware(t *testing.T) { - u := usecase.NewIOI(nil, nil, func(ctx context.Context, input, output interface{}) error { + u := usecase.NewIOI(nil, nil, func(_ context.Context, _, _ interface{}) error { return errors.New("failed") }) h := nethttp.NewHandler(u, func(h *nethttp.Handler) { - h.MakeErrResp = func(ctx context.Context, err error) (int, interface{}) { + h.MakeErrResp = func(_ context.Context, err error) (int, interface{}) { return http.StatusExpectationFailed, struct { Foo string `json:"foo"` }{Foo: err.Error()} @@ -331,8 +333,9 @@ func TestOptionsMiddleware(t *testing.T) { handleErrResponse := h.HandleErrResponse h.HandleErrResponse = func(w http.ResponseWriter, r *http.Request, err error) { assert.Equal(t, req, r) - loggedErr = err handleErrResponse(w, r, err) + + loggedErr = err } })(h) diff --git a/nethttp/openapi_test.go b/nethttp/openapi_test.go index f514bf3..d59ee3c 100644 --- a/nethttp/openapi_test.go +++ b/nethttp/openapi_test.go @@ -26,7 +26,7 @@ func TestOpenAPIMiddleware(t *testing.T) { Value string `json:"val"` Header int }) - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, input, _ interface{}) error { in, ok := input.(*Input) assert.True(t, ok) assert.Equal(t, 123, in.ID) diff --git a/nethttp/options.go b/nethttp/options.go index 6b0ef77..c18e1bc 100644 --- a/nethttp/options.go +++ b/nethttp/options.go @@ -96,7 +96,7 @@ func RequestMapping(v interface{}) func(h *Handler) { } { mm := make(map[string]string) - refl.WalkTaggedFields(reflect.ValueOf(v), func(v reflect.Value, sf reflect.StructField, tag string) { + refl.WalkTaggedFields(reflect.ValueOf(v), func(_ reflect.Value, sf reflect.StructField, tag string) { mm[sf.Name] = tag }, string(in)) @@ -124,7 +124,7 @@ func ResponseHeaderMapping(v interface{}) func(h *Handler) { mm := make(map[string]string) - refl.WalkTaggedFields(reflect.ValueOf(v), func(v reflect.Value, sf reflect.StructField, tag string) { + refl.WalkTaggedFields(reflect.ValueOf(v), func(_ reflect.Value, sf reflect.StructField, tag string) { mm[sf.Name] = tag }, "header") diff --git a/nethttp/options_test.go b/nethttp/options_test.go index b9eea72..21fb229 100644 --- a/nethttp/options_test.go +++ b/nethttp/options_test.go @@ -42,7 +42,7 @@ func TestRequestBodyContent(t *testing.T) { func TestRequestBodyContent_webService(t *testing.T) { s := web.NewService(openapi3.NewReflector()) - u := usecase.NewIOI(new(string), nil, func(ctx context.Context, input, output interface{}) error { + u := usecase.NewIOI(new(string), nil, func(_ context.Context, _, _ interface{}) error { return nil }) diff --git a/nethttp/usecase.go b/nethttp/usecase.go index e3d1433..9e5a26d 100644 --- a/nethttp/usecase.go +++ b/nethttp/usecase.go @@ -20,8 +20,8 @@ func UseCaseMiddlewares(mw ...usecase.Middleware) func(http.Handler) http.Handle } u := uh.UseCase() - fu := usecase.Wrap(u, usecase.MiddlewareFunc(func(next usecase.Interactor) usecase.Interactor { - return usecase.Interact(func(ctx context.Context, input, output interface{}) error { + fu := usecase.Wrap(u, usecase.MiddlewareFunc(func(_ usecase.Interactor) usecase.Interactor { + return usecase.Interact(func(ctx context.Context, _, _ interface{}) error { return ctx.Value(decodeErrCtxKey{}).(error) }) })) diff --git a/nethttp/wrap_test.go b/nethttp/wrap_test.go index 0a4e6b6..41b9081 100644 --- a/nethttp/wrap_test.go +++ b/nethttp/wrap_test.go @@ -12,7 +12,7 @@ func TestWrapHandler(t *testing.T) { var flow []string h := nethttp.WrapHandler( - http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { flow = append(flow, "handler") }), func(handler http.Handler) http.Handler { @@ -20,7 +20,9 @@ func TestWrapHandler(t *testing.T) { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { flow = append(flow, "mw1 before") + handler.ServeHTTP(writer, request) + flow = append(flow, "mw1 after") }) }, @@ -29,7 +31,9 @@ func TestWrapHandler(t *testing.T) { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { flow = append(flow, "mw2 before") + handler.ServeHTTP(writer, request) + flow = append(flow, "mw2 after") }) }, @@ -38,7 +42,9 @@ func TestWrapHandler(t *testing.T) { return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { flow = append(flow, "mw3 before") + handler.ServeHTTP(writer, request) + flow = append(flow, "mw3 after") }) }, diff --git a/openapi/collector.go b/openapi/collector.go index 01dbb68..3c16579 100644 --- a/openapi/collector.go +++ b/openapi/collector.go @@ -321,6 +321,7 @@ func (c *Collector) setupOutput(oc openapi.OperationContext, u usecase.Interacto if h.SuccessStatus != 0 { status = h.SuccessStatus } + oc.AddRespStructure(output, func(cu *openapi.ContentUnit) { cu.HTTPStatus = status setupCU(cu) diff --git a/openapi/collector_test.go b/openapi/collector_test.go index b312bd0..0a9087c 100644 --- a/openapi/collector_test.go +++ b/openapi/collector_test.go @@ -106,7 +106,7 @@ func TestCollector_Collect(t *testing.T) { assertjson.Equal(t, j, rw.Body.Bytes()) val := validatorMock{ - AddSchemaFunc: func(in rest.ParamIn, name string, schemaData []byte, required bool) error { + AddSchemaFunc: func(_ rest.ParamIn, _ string, _ []byte, _ bool) error { return nil }, } @@ -209,7 +209,7 @@ func TestCollector_Collect_requestMapping(t *testing.T) { }, "components":{ "schemas":{ - "MultipartFile":{"type":"string","format":"binary","nullable":true}, + "MultipartFile":{"type":"string","format":"binary"}, "OpenapiTestInput":{ "type":"object", "properties":{ @@ -222,7 +222,7 @@ func TestCollector_Collect_requestMapping(t *testing.T) { }`, collector.SpecSchema()) val := validatorMock{ - AddSchemaFunc: func(in rest.ParamIn, name string, schemaData []byte, required bool) error { + AddSchemaFunc: func(_ rest.ParamIn, _ string, _ []byte, _ bool) error { return nil }, } @@ -246,7 +246,7 @@ func TestCollector_Collect_CombineErrors(t *testing.T) { u.SetExpectedErrors(status.InvalidArgument, anotherErr{}, status.FailedPrecondition, status.AlreadyExists) h := rest.HandlerTrait{} - h.MakeErrResp = func(ctx context.Context, err error) (int, interface{}) { + h.MakeErrResp = func(_ context.Context, err error) (int, interface{}) { code, er := rest.Err(err) var ae anotherErr diff --git a/request/decoder_test.go b/request/decoder_test.go index 3662892..772a805 100644 --- a/request/decoder_test.go +++ b/request/decoder_test.go @@ -141,7 +141,7 @@ func BenchmarkDecoderFunc_Decode(b *testing.B) { req.AddCookie(&c) df := request.NewDecoderFactory() - df.SetDecoderFunc(rest.ParamInPath, func(r *http.Request) (url.Values, error) { + df.SetDecoderFunc(rest.ParamInPath, func(_ *http.Request) (url.Values, error) { return url.Values{"in_path": []string{"mno"}}, nil }) diff --git a/request/factory.go b/request/factory.go index c859424..823e245 100644 --- a/request/factory.go +++ b/request/factory.go @@ -182,7 +182,7 @@ func (df *DecoderFactory) prepareCustomMapping(input interface{}, customMapping if hdm, exists := cm[rest.ParamInHeader]; !exists && refl.HasTaggedFields(input, string(rest.ParamInHeader)) { hdm = make(map[string]string) - refl.WalkTaggedFields(reflect.ValueOf(input), func(v reflect.Value, sf reflect.StructField, tag string) { + refl.WalkTaggedFields(reflect.ValueOf(input), func(_ reflect.Value, sf reflect.StructField, tag string) { hdm[sf.Name] = http.CanonicalHeaderKey(tag) }, string(rest.ParamInHeader)) @@ -195,7 +195,7 @@ func (df *DecoderFactory) prepareCustomMapping(input interface{}, customMapping fields := make(map[string]bool) - refl.WalkTaggedFields(reflect.ValueOf(input), func(v reflect.Value, sf reflect.StructField, tag string) { + refl.WalkTaggedFields(reflect.ValueOf(input), func(_ reflect.Value, sf reflect.StructField, _ string) { fields[sf.Name] = true }, "") @@ -221,7 +221,7 @@ func (df *DecoderFactory) prepareCustomMapping(input interface{}, customMapping // jsonParams configures custom decoding for parameters with JSON struct values. func (df *DecoderFactory) jsonParams(formDecoder *form.Decoder, in rest.ParamIn, input interface{}) { // Check fields for struct values with json tags. E.g. query parameter with json value. - refl.WalkTaggedFields(reflect.ValueOf(input), func(v reflect.Value, sf reflect.StructField, tag string) { + refl.WalkTaggedFields(reflect.ValueOf(input), func(v reflect.Value, sf reflect.StructField, _ string) { // Skip unexported fields. if sf.PkgPath != "" { return @@ -234,7 +234,9 @@ func (df *DecoderFactory) jsonParams(formDecoder *form.Decoder, in rest.ParamIn, // from a string value into a struct. formDecoder.RegisterFunc(func(s string) (interface{}, error) { var err error + f := reflect.New(sf.Type) + if df.JSONReader != nil { err = df.JSONReader(bytes.NewBufferString(s), f.Interface()) } else { @@ -254,7 +256,7 @@ func (df *DecoderFactory) jsonParams(formDecoder *form.Decoder, in rest.ParamIn, func (df *DecoderFactory) makeDefaultDecoder(input interface{}, m *decoder) { defaults := url.Values{} - refl.WalkFieldsRecursively(reflect.ValueOf(input), func(v reflect.Value, sf reflect.StructField, path []reflect.StructField) { + refl.WalkFieldsRecursively(reflect.ValueOf(input), func(_ reflect.Value, sf reflect.StructField, path []reflect.StructField) { var key string for _, p := range path { @@ -286,7 +288,7 @@ func (df *DecoderFactory) makeDefaultDecoder(input interface{}, m *decoder) { dec := df.defaultValDecoder - m.decoders = append(m.decoders, func(r *http.Request, v interface{}, validator rest.Validator) error { + m.decoders = append(m.decoders, func(_ *http.Request, v interface{}, _ rest.Validator) error { return dec.Decode(v, defaults) }) m.in = append(m.in, defaultTag) diff --git a/request/factory_test.go b/request/factory_test.go index 6572e45..765fdae 100644 --- a/request/factory_test.go +++ b/request/factory_test.go @@ -23,16 +23,19 @@ func TestDecoderFactory_SetDecoderFunc(t *testing.T) { } var m map[string]json.RawMessage + err := json.Unmarshal([]byte(ah[7:]), &m) if err != nil { return nil, err } res := make(url.Values) + for k, v := range m { if len(v) > 2 && v[0] == '"' && v[len(v)-1] == '"' { v = v[1 : len(v)-1] } + res[k] = []string{string(v)} } @@ -79,10 +82,12 @@ func BenchmarkDecoderFactory_SetDecoderFunc(b *testing.B) { } res := make(url.Values) + for k, v := range m { if len(v) > 2 && v[0] == '"' && v[len(v)-1] == '"' { v = v[1 : len(v)-1] } + res[k] = []string{string(v)} } @@ -254,7 +259,7 @@ func TestDecoderFactory_MakeDecoder_header_case_sensitivity(t *testing.T) { req.Header.Set("x-One-Two-threE", "hello!") - require.NoError(t, d.Decode(req, &v, rest.ValidatorFunc(func(in rest.ParamIn, namedData map[string]interface{}) error { + require.NoError(t, d.Decode(req, &v, rest.ValidatorFunc(func(_ rest.ParamIn, namedData map[string]interface{}) error { fmt.Printf("%+v", namedData) return nil diff --git a/request/file_test.go b/request/file_test.go index 315aed3..3387488 100644 --- a/request/file_test.go +++ b/request/file_test.go @@ -37,7 +37,7 @@ type fileReqTest struct { } func TestDecoder_Decode_fileUploadOptional(t *testing.T) { - u := usecase.NewIOI(new(ReqEmb), nil, func(ctx context.Context, input, output interface{}) error { + u := usecase.NewIOI(new(ReqEmb), nil, func(_ context.Context, _, _ interface{}) error { return nil }) @@ -88,7 +88,7 @@ func TestDecoder_Decode_fileUploadTag(t *testing.T) { }{} u.Input = new(fileReqTest) - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, input, _ interface{}) error { in, ok := input.(*fileReqTest) assert.True(t, ok) assert.NotNil(t, in.Upload) diff --git a/request/jsonbody_test.go b/request/jsonbody_test.go index f7dcad9..3380b62 100644 --- a/request/jsonbody_test.go +++ b/request/jsonbody_test.go @@ -30,7 +30,7 @@ func Test_decodeJSONBody(t *testing.T) { assert.Equal(t, "248df4b7-aa70-47b8-a036-33ac447e668d", i.CustomerID) assert.Equal(t, "withdraw", i.Type) - vl := rest.ValidatorFunc(func(in rest.ParamIn, namedData map[string]interface{}) error { + vl := rest.ValidatorFunc(func(_ rest.ParamIn, _ map[string]interface{}) error { return nil }) @@ -90,7 +90,7 @@ func Test_decodeJSONBody_validateFailed(t *testing.T) { var i []int - vl := rest.ValidatorFunc(func(in rest.ParamIn, namedData map[string]interface{}) error { + vl := rest.ValidatorFunc(func(_ rest.ParamIn, _ map[string]interface{}) error { return errors.New("failed") }) diff --git a/request/reflect.go b/request/reflect.go index 428dc9d..f82f5d5 100644 --- a/request/reflect.go +++ b/request/reflect.go @@ -10,7 +10,7 @@ import ( func hasFileFields(i interface{}, tagname string) bool { found := false - refl.WalkTaggedFields(reflect.ValueOf(i), func(v reflect.Value, sf reflect.StructField, tag string) { + refl.WalkTaggedFields(reflect.ValueOf(i), func(_ reflect.Value, sf reflect.StructField, _ string) { if sf.Type == multipartFileType || sf.Type == multipartFileHeaderType || sf.Type == multipartFilesType || sf.Type == multipartFileHeadersType { found = true diff --git a/response/encoder.go b/response/encoder.go index f34a8bb..39f6a2b 100644 --- a/response/encoder.go +++ b/response/encoder.go @@ -90,7 +90,7 @@ func (h *Encoder) setupHeadersEncoder(output interface{}, ht *rest.HandlerTrait) if len(respHeaderMapping) == 0 && refl.HasTaggedFields(output, string(rest.ParamInHeader)) { respHeaderMapping = make(map[string]string) - refl.WalkTaggedFields(reflect.ValueOf(output), func(v reflect.Value, sf reflect.StructField, tag string) { + refl.WalkTaggedFields(reflect.ValueOf(output), func(_ reflect.Value, sf reflect.StructField, _ string) { // Converting name to canonical form, while keeping omitempty and any other options. t := sf.Tag.Get(string(rest.ParamInHeader)) parts := strings.Split(t, ",") @@ -137,7 +137,7 @@ func (h *Encoder) setupCookiesEncoder(output interface{}, ht *rest.HandlerTrait) respCookieMapping = make(map[string]http.Cookie) h.outputCookieBase = make([]http.Cookie, 0) - refl.WalkTaggedFields(reflect.ValueOf(output), func(v reflect.Value, sf reflect.StructField, tag string) { + refl.WalkTaggedFields(reflect.ValueOf(output), func(_ reflect.Value, sf reflect.StructField, tag string) { c := http.Cookie{ Name: tag, } @@ -147,11 +147,13 @@ func (h *Encoder) setupCookiesEncoder(output interface{}, ht *rest.HandlerTrait) resp := http.Response{} resp.Header = make(http.Header) resp.Header.Add("Set-Cookie", tag+"=x;"+strings.Join(options, ";")) + cc := resp.Cookies() if len(cc) == 1 { c = *cc[0] } } + c.Value = "" c.Raw = "" diff --git a/response/gzip/middleware_test.go b/response/gzip/middleware_test.go index ddda589..69c28ab 100644 --- a/response/gzip/middleware_test.go +++ b/response/gzip/middleware_test.go @@ -18,7 +18,7 @@ import ( func TestMiddleware(t *testing.T) { resp := []byte(strings.Repeat("A", 10000) + "!!!") - h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, err := rw.Write(resp) assert.NoError(t, err) })) @@ -67,7 +67,7 @@ func TestMiddleware(t *testing.T) { // BenchmarkMiddleware-12 108810 9619 ns/op 1223 B/op 11 allocs/op. func BenchmarkMiddleware(b *testing.B) { resp := []byte(strings.Repeat("A", 10000) + "!!!") - h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, err := rw.Write(resp) assert.NoError(b, err) })) @@ -92,7 +92,7 @@ func BenchmarkMiddleware(b *testing.B) { // BenchmarkMiddleware_control-4 214824 5945 ns/op 11184 B/op 9 allocs/op. func BenchmarkMiddleware_control(b *testing.B) { resp := []byte(strings.Repeat("A", 10000) + "!!!") - h := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + h := http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, err := rw.Write(resp) assert.NoError(b, err) }) @@ -114,12 +114,12 @@ func BenchmarkMiddleware_control(b *testing.B) { func TestMiddleware_concurrency(t *testing.T) { resp := []byte(strings.Repeat("A", 10000) + "!!!") respGz := gzipEncode(t, resp) - h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, err := rw.Write(resp) assert.NoError(t, err) })) - hg := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + hg := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, err := gzip2.WriteCompressedBytes(respGz, rw) assert.NoError(t, err) })) @@ -161,7 +161,7 @@ func TestGzipResponseWriter_ExpectCompressedBytes(t *testing.T) { resp := []byte(strings.Repeat("A", 10000) + "!!!") respGz := gzipEncode(t, resp) - h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, err := gzip2.WriteCompressedBytes(respGz, rw) assert.NoError(t, err) })) @@ -181,7 +181,7 @@ func TestGzipResponseWriter_ExpectCompressedBytes(t *testing.T) { func TestMiddleware_skipContentEncoding(t *testing.T) { resp := []byte(strings.Repeat("A", 10000) + "!!!") - h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { rw.Header().Set("Content-Encoding", "br") _, err := rw.Write(resp) assert.NoError(t, err) @@ -201,7 +201,7 @@ func TestMiddleware_skipContentEncoding(t *testing.T) { } func TestMiddleware_noContent(t *testing.T) { - h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { rw.WriteHeader(http.StatusNoContent) // Second call does not hurt. @@ -252,7 +252,7 @@ func gzipDecode(t *testing.T, data []byte) []byte { func TestMiddleware_hijacker(t *testing.T) { rb := []byte(strings.Repeat("A", 10000) + "!!!") - h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + h := gzip.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, ok := rw.(http.Hijacker) require.True(t, ok) diff --git a/response/middleware_test.go b/response/middleware_test.go index bb68ded..560645f 100644 --- a/response/middleware_test.go +++ b/response/middleware_test.go @@ -25,7 +25,7 @@ func TestEncoderMiddleware(t *testing.T) { } u.Output = new(outputPort) - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, _, output interface{}) error { output.(*outputPort).Name = "Jane" output.(*outputPort).Items = []string{"one", "two", "three"} diff --git a/response/validator_test.go b/response/validator_test.go index 0fdf48d..1d32985 100644 --- a/response/validator_test.go +++ b/response/validator_test.go @@ -32,7 +32,7 @@ func TestValidatorMiddleware(t *testing.T) { } u.Output = new(outputPort) - u.Interactor = usecase.Interact(func(ctx context.Context, input, output interface{}) error { + u.Interactor = usecase.Interact(func(_ context.Context, _, output interface{}) error { out, ok := output.(*outputPort) require.True(t, ok) diff --git a/resttest/client_test.go b/resttest/client_test.go index 1bc6443..74e5d3d 100644 --- a/resttest/client_test.go +++ b/resttest/client_test.go @@ -36,7 +36,9 @@ func TestNewClient(t *testing.T) { assert.Equal(t, "bar", c.Value) ncnt := atomic.AddInt64(&cnt, 1) + rw.Header().Set("Content-Type", "application/json") + if ncnt > 1 { rw.WriteHeader(http.StatusConflict) _, err := rw.Write([]byte(`{"error":"conflict"}`)) @@ -88,7 +90,7 @@ func TestNewClient(t *testing.T) { } func TestNewClient_failedExpectation(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + srv := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) { _, err := writer.Write([]byte(`{"bar":"foo"}`)) assert.NoError(t, err) })) diff --git a/web/service_test.go b/web/service_test.go index 1d822cf..eb436f7 100644 --- a/web/service_test.go +++ b/web/service_test.go @@ -22,7 +22,7 @@ type albumID struct { } func albumByID() usecase.Interactor { - u := usecase.NewIOI(new(albumID), new(album), func(ctx context.Context, input, output interface{}) error { + u := usecase.NewIOI(new(albumID), new(album), func(_ context.Context, _, _ interface{}) error { return nil }) u.SetTags("Album") @@ -35,8 +35,8 @@ func TestDefaultService(t *testing.T) { service := web.NewService( openapi3.NewReflector(), - func(s *web.Service) { l = append(l, "one") }, - func(s *web.Service) { l = append(l, "two") }, + func(_ *web.Service) { l = append(l, "one") }, + func(_ *web.Service) { l = append(l, "two") }, ) service.OpenAPISchema().SetTitle("Albums API") @@ -51,9 +51,9 @@ func TestDefaultService(t *testing.T) { service.Put("/albums", postAlbums(), nethttp.SuccessStatus(http.StatusCreated)) service.Trace("/albums", postAlbums(), nethttp.SuccessStatus(http.StatusCreated)) service.Options("/albums", postAlbums(), nethttp.SuccessStatus(http.StatusCreated)) - service.Docs("/docs", func(title, schemaURL, basePath string) http.Handler { + service.Docs("/docs", func(_, _, _ string) http.Handler { // Mount github.com/swaggest/swgui/v4emb.New here. - return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {}) + return http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}) }) service.OnNotFound(usecase.NewIOI( @@ -61,7 +61,7 @@ func TestDefaultService(t *testing.T) { new(struct { Foo string `json:"foo"` }), - func(ctx context.Context, input, output interface{}) error { + func(_ context.Context, _, _ interface{}) error { return nil }), ) @@ -71,7 +71,7 @@ func TestDefaultService(t *testing.T) { new(struct { Foo string `json:"foo"` }), - func(ctx context.Context, input, output interface{}) error { + func(_ context.Context, _, _ interface{}) error { return nil }), )