Skip to content

Commit 0f5ebfc

Browse files
authored
Inspect wrapped handlers in Mount (#86)
1 parent c1989ca commit 0f5ebfc

File tree

9 files changed

+247
-48
lines changed

9 files changed

+247
-48
lines changed

.github/workflows/test-examples.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
test:
1212
strategy:
1313
matrix:
14-
go-version: [ 1.17.x, 1.18.x ]
14+
go-version: [1.18.x ]
1515
runs-on: ubuntu-latest
1616
steps:
1717
- name: Install Go stable

.github/workflows/test-unit.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ jobs:
8888
id: annotate
8989
if: matrix.go-version == env.COV_GO_VERSION && github.event.pull_request.base.sha != ''
9090
run: |
91+
curl -sLO https://github.com/vearutop/gocovdiff/releases/download/v1.3.6/linux_amd64.tar.gz && tar xf linux_amd64.tar.gz
92+
gocovdiff_hash=$(git hash-object ./gocovdiff)
93+
[ "$gocovdiff_hash" == "8e507e0d671d4d6dfb3612309b72b163492f28eb" ] || (echo "::error::unexpected hash for gocovdiff, possible tampering: $gocovdiff_hash" && exit 1)
9194
git fetch origin master ${{ github.event.pull_request.base.sha }}
92-
curl -sLO https://github.com/vearutop/gocovdiff/releases/download/v1.3.4/linux_amd64.tar.gz && tar xf linux_amd64.tar.gz && shasum -a 256 gocovdiff && echo "b351c67526eefeb0671c82e9271ae984875865eed19e911f40f78348cb98347c gocovdiff" | shasum -c
9395
REP=$(./gocovdiff -cov unit.coverprofile -gha-annotations gha-unit.txt -delta-cov-file delta-cov-unit.txt -target-delta-cov ${TARGET_DELTA_COV})
9496
echo "${REP}"
9597
REP="${REP//$'\n'/%0A}"

_examples/go.mod

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ replace github.com/swaggest/rest => ../
66

77
require (
88
github.com/bool64/ctxd v1.1.2
9-
github.com/bool64/dev v0.2.16
10-
github.com/bool64/httpmock v0.1.1
9+
github.com/bool64/dev v0.2.18
10+
github.com/bool64/httpmock v0.1.6
1111
github.com/bool64/httptestbench v0.1.3
1212
github.com/go-chi/chi/v5 v5.0.7
1313
github.com/kelseyhightower/envconfig v1.4.0
1414
github.com/rs/cors v1.8.2
15-
github.com/stretchr/testify v1.7.2
15+
github.com/stretchr/testify v1.8.0
1616
github.com/swaggest/assertjson v1.7.0
1717
github.com/swaggest/jsonschema-go v0.3.35
1818
github.com/swaggest/openapi-go v0.2.18
@@ -25,7 +25,7 @@ require github.com/swaggest/rest v0.0.0-00010101000000-000000000000
2525

2626
require (
2727
github.com/andybalholm/brotli v1.0.4 // indirect
28-
github.com/bool64/shared v0.1.4 // indirect
28+
github.com/bool64/shared v0.1.5 // indirect
2929
github.com/cespare/xxhash/v2 v2.1.2 // indirect
3030
github.com/davecgh/go-spew v1.1.1 // indirect
3131
github.com/fsnotify/fsnotify v1.5.4 // indirect
@@ -41,8 +41,6 @@ require (
4141
github.com/yosuke-furukawa/json5 v0.1.2-0.20201207051438-cf7bb3f354ff // indirect
4242
github.com/yudai/gojsondiff v1.0.0 // indirect
4343
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
44-
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
45-
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
4644
gopkg.in/yaml.v2 v2.4.0 // indirect
4745
gopkg.in/yaml.v3 v3.0.1 // indirect
4846
)

_examples/go.sum

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ github.com/bool64/ctxd v1.1.2 h1:6J05q1vTG0op2O0kP+LosCd9wJ0qJybcvdE+bPjUJZE=
55
github.com/bool64/ctxd v1.1.2/go.mod h1:5rwLykeZBJHK27q5sSfhfKig6076270V+3iiXbP+HFY=
66
github.com/bool64/dev v0.1.35/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
77
github.com/bool64/dev v0.1.41/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
8-
github.com/bool64/dev v0.2.5/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
9-
github.com/bool64/dev v0.2.16 h1:ZlybgWWXmHGMojqIjDrtl5QF6jmE4hNeojE00nioVk0=
10-
github.com/bool64/dev v0.2.16/go.mod h1:/csLrm+4oDSsKJRIVS0mrywAonLnYKFG8RvGT7Jh9b8=
11-
github.com/bool64/httpmock v0.1.1 h1:jpqM0S8efvJfN7Uy5fBUJKu2C640/ZS0yboxpeyVwm0=
12-
github.com/bool64/httpmock v0.1.1/go.mod h1:Ju7xrs8gVyxANbgIxoxX4Pkj1uHygzPEpGEnfqct+gA=
8+
github.com/bool64/dev v0.2.18 h1:FPXZxR4+bgNgBKtORwCr7W/s46bY/LkKFwVy8f63cqI=
9+
github.com/bool64/dev v0.2.18/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg=
10+
github.com/bool64/httpmock v0.1.6 h1:v9+AmoSabaHuR7abjnhGwGxsaNljtFAYtluF0p4Q3ng=
11+
github.com/bool64/httpmock v0.1.6/go.mod h1:pQukYUfoG9gW4fRAv+xHuvA2BlRoauEXK/XG5mKD04I=
1312
github.com/bool64/httptestbench v0.1.3 h1:bPDM3YPtE3o2sqIwjhdTC55wiqwfHsqps2RGcWBesuo=
1413
github.com/bool64/httptestbench v0.1.3/go.mod h1:3SoL5hfGcPylcOVSEF2+jJC8VG0oKMHlZYRoliBKbzE=
15-
github.com/bool64/shared v0.1.4 h1:zwtb1dl2QzDa9TJOq2jzDTdb5IPf9XlxTGKN8cySWT0=
16-
github.com/bool64/shared v0.1.4/go.mod h1:ryGjsnQFh6BnEXClfVlEJrzjwzat7CmA8PNS5E+jPp0=
14+
github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E=
15+
github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs=
1716
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
1817
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
1918
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -49,9 +48,11 @@ github.com/santhosh-tekuri/jsonschema/v3 v3.1.0/go.mod h1:8kzK2TC0k0YjOForaAHdNE
4948
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
5049
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
5150
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
51+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
5252
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
53-
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
54-
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
53+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
54+
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
55+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
5556
github.com/swaggest/assertjson v1.7.0 h1:SKw5Rn0LQs6UvmGrIdaKQbMR1R3ncXm5KNon+QJ7jtw=
5657
github.com/swaggest/assertjson v1.7.0/go.mod h1:vxMJMehbSVJd+dDWFCKv3QRZKNTpy/ktZKTz9LOEDng=
5758
github.com/swaggest/form/v5 v5.0.1 h1:YQH0REX7iMKhtoVPWXREZgbt50VYXNCKK61psnD8Fgo=
@@ -82,15 +83,15 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDf
8283
github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI=
8384
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
8485
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
85-
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
8686
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
87+
golang.org/x/net v0.0.0-20220630215102-69896b714898 h1:K7wO6V1IrczY9QOQ2WkVpw4JQSwCd52UsxVEirZUfiw=
8788
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
8889
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
8990
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
9091
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
9192
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
92-
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
9393
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
94+
golang.org/x/sys v0.0.0-20220702020025-31831981b65f h1:xdsejrW/0Wf2diT5CPp3XmKUNbr7Xvw8kYilQ+6qjRY=
9495
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
9596
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
9697
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -101,10 +102,10 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
101102
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
102103
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
103104
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
104-
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
105105
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
106106
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
107107
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
108108
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
109+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
109110
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
110111
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

_examples/mount/main.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"net/http"
8+
9+
"github.com/go-chi/chi/v5/middleware"
10+
"github.com/swaggest/rest/nethttp"
11+
"github.com/swaggest/rest/web"
12+
swgui "github.com/swaggest/swgui/v4emb"
13+
"github.com/swaggest/usecase"
14+
)
15+
16+
func mul() usecase.Interactor {
17+
return usecase.NewInteractor(func(ctx context.Context, input []int, output *int) error {
18+
*output = 1
19+
20+
for _, v := range input {
21+
*output *= v
22+
}
23+
24+
return nil
25+
})
26+
}
27+
28+
func sum() usecase.Interactor {
29+
return usecase.NewInteractor(func(ctx context.Context, input []int, output *int) error {
30+
for _, v := range input {
31+
*output += v
32+
}
33+
34+
return nil
35+
})
36+
}
37+
38+
func main() {
39+
service := web.DefaultService()
40+
service.OpenAPI.Info.Title = "Security and Mount Example"
41+
42+
apiV1 := web.DefaultService()
43+
44+
apiV1.Wrap(
45+
middleware.BasicAuth("Admin Access", map[string]string{"admin": "admin"}),
46+
nethttp.HTTPBasicSecurityMiddleware(service.OpenAPICollector, "Admin", "Admin access"),
47+
)
48+
49+
apiV1.Post("/sum", sum())
50+
apiV1.Post("/mul", mul())
51+
52+
service.Mount("/api/v1", apiV1)
53+
service.Docs("/api/v1/docs", swgui.New)
54+
55+
// Blanket handler, for example to serve static content.
56+
service.Mount("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
57+
_, _ = w.Write([]byte("blanket handler got a request: " + r.URL.String()))
58+
}))
59+
60+
fmt.Println("Swagger UI at http://localhost:8010/api/v1/docs.")
61+
if err := http.ListenAndServe("localhost:8010", service); err != nil {
62+
log.Fatal(err)
63+
}
64+
}

chirouter/wrapper.go

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strings"
66

77
"github.com/go-chi/chi/v5"
8+
"github.com/swaggest/rest"
89
"github.com/swaggest/rest/nethttp"
910
)
1011

@@ -25,6 +26,7 @@ type Wrapper struct {
2526

2627
middlewares []func(http.Handler) http.Handler
2728
wraps []func(http.Handler) http.Handler
29+
handlers []http.Handler
2830
}
2931

3032
var _ chi.Router = &Wrapper{}
@@ -89,8 +91,27 @@ func (r *Wrapper) Route(pattern string, fn func(r chi.Router)) chi.Router {
8991

9092
// Mount attaches another http.Handler along "./basePattern/*".
9193
func (r *Wrapper) Mount(pattern string, h http.Handler) {
92-
h = r.prepareHandler("", pattern, h)
93-
r.captureHandler(h)
94+
if hr, ok := h.(interface {
95+
handlersWithRoute() []http.Handler
96+
handlerWraps() []func(http.Handler) http.Handler
97+
}); ok {
98+
pattern = strings.TrimSuffix(pattern, "/")
99+
100+
for _, h := range hr.handlersWithRoute() {
101+
var rh rest.HandlerWithRoute
102+
if nethttp.HandlerAs(h, &rh) {
103+
m := rh.RouteMethod()
104+
p := r.resolvePattern(pattern + rh.RoutePattern())
105+
h := nethttp.WrapHandler(h, nethttp.HandlerWithRouteMiddleware(m, p))
106+
h = nethttp.WrapHandler(h, hr.handlerWraps()...)
107+
_ = nethttp.WrapHandler(h, r.wraps...)
108+
}
109+
}
110+
} else {
111+
h = r.prepareHandler("", pattern, h)
112+
r.captureHandler(h)
113+
}
114+
94115
r.Router.Mount(pattern, h)
95116
}
96117

@@ -167,9 +188,17 @@ func (r *Wrapper) captureHandler(h http.Handler) {
167188
}
168189

169190
func (r *Wrapper) prepareHandler(method, pattern string, h http.Handler) http.Handler {
170-
mw := r.wraps
171-
mw = append(mw, nethttp.HandlerWithRouteMiddleware(method, r.resolvePattern(pattern)))
172-
h = nethttp.WrapHandler(h, mw...)
191+
h = nethttp.WrapHandler(h, nethttp.HandlerWithRouteMiddleware(method, r.resolvePattern(pattern)))
192+
r.handlers = append(r.handlers, h)
193+
h = nethttp.WrapHandler(h, r.wraps...)
173194

174195
return h
175196
}
197+
198+
func (r *Wrapper) handlersWithRoute() []http.Handler {
199+
return r.handlers
200+
}
201+
202+
func (r *Wrapper) handlerWraps() []func(http.Handler) http.Handler {
203+
return r.wraps
204+
}

chirouter/wrapper_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package chirouter_test
22

33
import (
4+
"bytes"
5+
"context"
6+
"errors"
47
"net/http"
58
"net/http/httptest"
69
"net/url"
@@ -10,9 +13,12 @@ import (
1013
"github.com/go-chi/chi/v5/middleware"
1114
"github.com/stretchr/testify/assert"
1215
"github.com/stretchr/testify/require"
16+
"github.com/swaggest/assertjson"
1317
"github.com/swaggest/rest"
1418
"github.com/swaggest/rest/chirouter"
1519
"github.com/swaggest/rest/nethttp"
20+
"github.com/swaggest/rest/web"
21+
"github.com/swaggest/usecase"
1622
)
1723

1824
type HandlerWithFoo struct {
@@ -254,3 +260,99 @@ func TestWrapper_Use_StripSlashes(t *testing.T) {
254260
"h", "h",
255261
}, log)
256262
}
263+
264+
func TestWrapper_Mount(t *testing.T) {
265+
service := web.DefaultService()
266+
service.OpenAPI.Info.Title = "Security and Mount Example"
267+
268+
apiV1 := web.DefaultService()
269+
270+
apiV1.Wrap(
271+
middleware.BasicAuth("Admin Access", map[string]string{"admin": "admin"}),
272+
nethttp.HTTPBasicSecurityMiddleware(service.OpenAPICollector, "Admin", "Admin access"),
273+
)
274+
275+
apiV1.Post("/sum", usecase.NewIOI(new([]int), new(int), func(ctx context.Context, input, output interface{}) error {
276+
return errors.New("oops")
277+
}))
278+
279+
service.Mount("/api/v1", apiV1)
280+
281+
// Blanket handler, for example to serve static content.
282+
service.Mount("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
283+
_, err := w.Write([]byte("blanket handler got a request: " + r.URL.String()))
284+
assert.NoError(t, err)
285+
}))
286+
287+
req, err := http.NewRequest(http.MethodGet, "/foo", nil)
288+
require.NoError(t, err)
289+
290+
rw := httptest.NewRecorder()
291+
service.ServeHTTP(rw, req)
292+
293+
assert.Equal(t, "blanket handler got a request: /foo", rw.Body.String())
294+
295+
req, err = http.NewRequest(http.MethodPost, "/api/v1/sum", bytes.NewBufferString(`[1,2,3]`))
296+
require.NoError(t, err)
297+
298+
rw = httptest.NewRecorder()
299+
300+
service.ServeHTTP(rw, req)
301+
assert.Equal(t, http.StatusUnauthorized, rw.Code)
302+
303+
req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW4=")
304+
305+
rw = httptest.NewRecorder()
306+
307+
service.ServeHTTP(rw, req)
308+
assert.Equal(t, `{"error":"oops"}`+"\n", rw.Body.String())
309+
310+
assertjson.EqualMarshal(t, []byte(`{
311+
"openapi":"3.0.3","info":{"title":"Security and Mount Example","version":""},
312+
"paths":{
313+
"/api/v1/sum":{
314+
"post":{
315+
"summary":"Test Wrapper _ Mount",
316+
"operationId":"rest/chirouter_test.TestWrapper_Mount",
317+
"requestBody":{
318+
"content":{
319+
"application/json":{
320+
"schema":{"type":"array","items":{"type":"integer"},"nullable":true}
321+
}
322+
}
323+
},
324+
"responses":{
325+
"200":{
326+
"description":"OK",
327+
"content":{"application/json":{"schema":{"type":"integer"}}}
328+
},
329+
"401":{
330+
"description":"Unauthorized",
331+
"content":{
332+
"application/json":{"schema":{"$ref":"#/components/schemas/RestErrResponse"}}
333+
}
334+
}
335+
},
336+
"security":[{"Admin":[]}]
337+
}
338+
}
339+
},
340+
"components":{
341+
"schemas":{
342+
"RestErrResponse":{
343+
"type":"object",
344+
"properties":{
345+
"code":{"type":"integer","description":"Application-specific error code."},
346+
"context":{
347+
"type":"object","additionalProperties":{},
348+
"description":"Application context."
349+
},
350+
"error":{"type":"string","description":"Error message."},
351+
"status":{"type":"string","description":"Status text."}
352+
}
353+
}
354+
},
355+
"securitySchemes":{"Admin":{"type":"http","scheme":"basic","description":"Admin access"}}
356+
}
357+
}`), service.OpenAPI)
358+
}

0 commit comments

Comments
 (0)