From 42df208085bdf90c0b4b1ad109613421e332d59f Mon Sep 17 00:00:00 2001 From: Frederic BIDON Date: Fri, 8 Dec 2023 12:18:44 +0100 Subject: [PATCH] chore: relinting, continued This phase applies trivial relinting fixes, to keep the amount of changes reviewable. Non-trivial fixes are deferred to a follow-up PR. Signed-off-by: Frederic BIDON --- bytestream.go | 18 ++++--- client/keepalive.go | 3 +- client/opentelemetry_test.go | 2 +- client/opentracing_test.go | 4 +- client/request.go | 9 ++-- client/request_test.go | 2 +- client/runtime.go | 25 +++++---- client/runtime_test.go | 70 +++++++++++++------------- client_operation.go | 2 +- client_request.go | 6 +-- internal/testing/petstore/api.go | 2 +- internal/testing/simplepetstore/api.go | 2 +- middleware/context.go | 11 ++-- middleware/context_test.go | 2 +- middleware/denco/router.go | 2 +- middleware/denco/server_test.go | 4 +- middleware/header/header.go | 11 ++-- middleware/parameter.go | 21 +++++--- middleware/parameter_test.go | 21 ++++---- middleware/rapidoc.go | 8 +-- middleware/rapidoc_test.go | 7 ++- middleware/redoc.go | 6 +-- middleware/redoc_test.go | 7 ++- middleware/request.go | 2 +- middleware/request_test.go | 26 +++++----- middleware/router.go | 6 +-- middleware/string_conversion_test.go | 12 ++--- middleware/swaggerui.go | 6 +-- middleware/swaggerui_oauth2_test.go | 5 +- middleware/swaggerui_test.go | 12 +++-- middleware/ui_defaults.go | 8 +++ middleware/untyped/api.go | 15 +++--- middleware/untyped/api_test.go | 2 +- request.go | 7 ++- security/authenticator.go | 4 +- 35 files changed, 196 insertions(+), 154 deletions(-) create mode 100644 middleware/ui_defaults.go diff --git a/bytestream.go b/bytestream.go index 3142a090..0a6b8ec6 100644 --- a/bytestream.go +++ b/bytestream.go @@ -52,14 +52,15 @@ func ByteStreamConsumer(opts ...byteStreamOpt) Consumer { return errors.New("ByteStreamConsumer requires a reader") // early exit } - close := defaultCloser //nolint:revive,predeclared + closer := defaultCloser if vals.Close { if cl, ok := reader.(io.Closer); ok { - close = cl.Close //nolint:revive + closer = cl.Close } } - //nolint:errcheck // closing a reader wouldn't fail. - defer close() + defer func() { + _ = closer() + }() if wrtr, ok := data.(io.Writer); ok { _, err := io.Copy(wrtr, reader) @@ -109,14 +110,15 @@ func ByteStreamProducer(opts ...byteStreamOpt) Producer { if writer == nil { return errors.New("ByteStreamProducer requires a writer") // early exit } - close := defaultCloser //nolint:revive,predeclared + closer := defaultCloser if vals.Close { if cl, ok := writer.(io.Closer); ok { - close = cl.Close //nolint:revive + closer = cl.Close } } - //nolint:errcheck // TODO: closing a writer would fail. - defer close() + defer func() { + _ = closer() + }() if rc, ok := data.(io.ReadCloser); ok { defer rc.Close() diff --git a/client/keepalive.go b/client/keepalive.go index bc7b7fa4..7dd6b51c 100644 --- a/client/keepalive.go +++ b/client/keepalive.go @@ -48,8 +48,7 @@ func (d *drainingReadCloser) Close() error { // If the reader side (a HTTP server) is misbehaving, it still may send // some bytes, but the closer ignores them to keep the underling // connection open. - //nolint:errcheck - io.Copy(io.Discard, d.rdr) + _, _ = io.Copy(io.Discard, d.rdr) } return d.rdr.Close() } diff --git a/client/opentelemetry_test.go b/client/opentelemetry_test.go index 3a844cb9..a5f41e02 100644 --- a/client/opentelemetry_test.go +++ b/client/opentelemetry_test.go @@ -121,7 +121,7 @@ func assertOpenTelemetrySubmit(t *testing.T, operation *runtime.ClientOperation, attribute.String("http.route", "/kubernetes-clusters/{cluster_id}"), attribute.String("http.method", http.MethodGet), attribute.String("span.kind", trace.SpanKindClient.String()), - attribute.String("http.scheme", "https"), + attribute.String("http.scheme", schemeHTTPS), // NOTE: this becomes http.response.status_code with semconv v1.21 attribute.Int("http.status_code", 490), }, span.Attributes) diff --git a/client/opentracing_test.go b/client/opentracing_test.go index 9bb5cabf..cd33f9d3 100644 --- a/client/opentracing_test.go +++ b/client/opentracing_test.go @@ -42,7 +42,7 @@ type mockRuntime struct { func (m *mockRuntime) Submit(operation *runtime.ClientOperation) (interface{}, error) { _ = operation.Params.WriteToRequest(&m.req, nil) _, _ = operation.Reader.ReadResponse(&tres{}, nil) - return nil, nil //nolint:nilnil + return map[string]interface{}{}, nil } func testOperation(ctx context.Context) *runtime.ClientOperation { @@ -52,7 +52,7 @@ func testOperation(ctx context.Context) *runtime.ClientOperation { PathPattern: "/kubernetes-clusters/{cluster_id}", ProducesMediaTypes: []string{"application/json"}, ConsumesMediaTypes: []string{"application/json"}, - Schemes: []string{"https"}, + Schemes: []string{schemeHTTPS}, Reader: runtime.ClientResponseReaderFunc(func(runtime.ClientResponse, runtime.Consumer) (interface{}, error) { return nil, nil }), diff --git a/client/request.go b/client/request.go index 8b433865..65ef8295 100644 --- a/client/request.go +++ b/client/request.go @@ -16,6 +16,7 @@ package client import ( "bytes" + "context" "fmt" "io" "log" @@ -317,13 +318,13 @@ DoneChoosingBodySource: urlPath := path.Join(basePathURL.Path, pathPatternURL.Path) for k, v := range r.pathParams { - urlPath = strings.Replace(urlPath, "{"+k+"}", url.PathEscape(v), -1) //nolint:gocritic + urlPath = strings.ReplaceAll(urlPath, "{"+k+"}", url.PathEscape(v)) } if reinstateSlash { - urlPath = urlPath + "/" //nolint:gocritic + urlPath += "/" } - req, err := http.NewRequest(r.method, urlPath, body) //nolint:noctx + req, err := http.NewRequestWithContext(context.Background(), r.method, urlPath, body) if err != nil { return nil, err } @@ -361,7 +362,7 @@ func (r *request) GetMethod() string { func (r *request) GetPath() string { path := r.pathPattern for k, v := range r.pathParams { - path = strings.Replace(path, "{"+k+"}", v, -1) //nolint:gocritic + path = strings.ReplaceAll(path, "{"+k+"}", v) } return path } diff --git a/client/request_test.go b/client/request_test.go index a8ab7d29..40616946 100644 --- a/client/request_test.go +++ b/client/request_test.go @@ -769,7 +769,7 @@ func TestGetBodyCallsBeforeRoundTrip(t *testing.T) { }), } - openAPIClient := New(hu.Host, "/", []string{"http"}) + openAPIClient := New(hu.Host, "/", []string{schemeHTTP}) res, err := openAPIClient.Submit(operation) require.NoError(t, err) diff --git a/client/runtime.go b/client/runtime.go index 629866b8..8d293a59 100644 --- a/client/runtime.go +++ b/client/runtime.go @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//nolint:goconst package client import ( @@ -40,6 +39,11 @@ import ( "github.com/opentracing/opentracing-go" ) +const ( + schemeHTTP = "http" + schemeHTTPS = "https" +) + // TLSClientOptions to configure client authentication with mutual TLS type TLSClientOptions struct { // Certificate is the path to a PEM-encoded certificate to be used for @@ -112,7 +116,9 @@ type TLSClientOptions struct { // TLSClientAuth creates a tls.Config for mutual auth func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) { // create client tls config - cfg := &tls.Config{} //nolint:gosec + cfg := &tls.Config{ + MinVersion: tls.VersionTLS12, + } // load client cert if specified if opts.Certificate != "" { @@ -158,11 +164,12 @@ func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) { // When no CA certificate is provided, default to the system cert pool // that way when a request is made to a server known by the system trust store, // the name is still verified - if opts.LoadedCA != nil { //nolint:gocritic + switch { + case opts.LoadedCA != nil: caCertPool := basePool(opts.LoadedCAPool) caCertPool.AddCert(opts.LoadedCA) cfg.RootCAs = caCertPool - } else if opts.CA != "" { + case opts.CA != "": // load ca cert caCert, err := os.ReadFile(opts.CA) if err != nil { @@ -171,7 +178,7 @@ func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) { caCertPool := basePool(opts.LoadedCAPool) caCertPool.AppendCertsFromPEM(caCert) cfg.RootCAs = caCertPool - } else if opts.LoadedCAPool != nil { + case opts.LoadedCAPool != nil: cfg.RootCAs = opts.LoadedCAPool } @@ -227,7 +234,7 @@ type Runtime struct { Host string BasePath string Formats strfmt.Registry - Context context.Context //nolint:containedctx + Context context.Context //nolint:containedctx // we precisely want this type to contain the request context Debug bool logger logger.Logger @@ -316,7 +323,7 @@ func (r *Runtime) pickScheme(schemes []string) string { if v := r.selectScheme(schemes); v != "" { return v } - return "http" + return schemeHTTP } func (r *Runtime) selectScheme(schemes []string) string { @@ -327,9 +334,9 @@ func (r *Runtime) selectScheme(schemes []string) string { scheme := schemes[0] // prefer https, but skip when not possible - if scheme != "https" && schLen > 1 { + if scheme != schemeHTTPS && schLen > 1 { for _, sch := range schemes { - if sch == "https" { + if sch == schemeHTTPS { scheme = sch break } diff --git a/client/runtime_test.go b/client/runtime_test.go index 58fc2ff3..b3a5ce47 100644 --- a/client/runtime_test.go +++ b/client/runtime_test.go @@ -299,7 +299,7 @@ func TestRuntime_ManualCertificateValidation(t *testing.T) { require.NoError(t, err) hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := NewWithClient(hu.Host, "/", []string{"https"}, client) + rt := NewWithClient(hu.Host, "/", []string{schemeHTTPS}, client) rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { return nil @@ -351,7 +351,7 @@ func TestRuntime_Concurrent(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) resCC := make(chan interface{}) errCC := make(chan error) var res interface{} @@ -426,7 +426,7 @@ func TestRuntime_Canary(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Method: http.MethodGet, @@ -478,7 +478,7 @@ func TestRuntime_XMLCanary(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Method: http.MethodGet, @@ -520,7 +520,7 @@ func TestRuntime_TextCanary(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Method: http.MethodGet, @@ -565,7 +565,7 @@ func TestRuntime_CSVCanary(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Method: http.MethodGet, @@ -604,9 +604,9 @@ func TestRuntime_CustomTransport(t *testing.T) { {false, "task 2 content", 2}, } - rt := New("localhost:3245", "/", []string{"ws", "wss", "https"}) + rt := New("localhost:3245", "/", []string{"ws", "wss", schemeHTTPS}) rt.Transport = roundTripperFunc(func(req *http.Request) (*http.Response, error) { - if req.URL.Scheme != "https" { + if req.URL.Scheme != schemeHTTPS { return nil, errors.New("this was not a https request") } assert.Equal(t, "localhost:3245", req.Host) @@ -627,7 +627,7 @@ func TestRuntime_CustomTransport(t *testing.T) { ID: "getTasks", Method: http.MethodGet, PathPattern: "/", - Schemes: []string{"ws", "wss", "https"}, + Schemes: []string{"ws", "wss", schemeHTTPS}, Params: rwrtr, Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { if response.Code() == http.StatusOK { @@ -680,7 +680,7 @@ func TestRuntime_CustomCookieJar(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) rt.Jar, err = cookiejar.New(nil) require.NoError(t, err) @@ -693,7 +693,7 @@ func TestRuntime_CustomCookieJar(t *testing.T) { AuthInfo: authInfo, Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, _ runtime.Consumer) (interface{}, error) { if response.Code() == http.StatusOK { - return nil, nil //nolint:nilnil + return map[string]interface{}{}, nil } return nil, errors.New("generic error") }), @@ -735,7 +735,7 @@ func TestRuntime_AuthCanary(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Params: rwrtr, @@ -783,12 +783,12 @@ func TestRuntime_PickConsumer(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Method: "POST", PathPattern: "/", - Schemes: []string{"http"}, + Schemes: []string{schemeHTTP}, ConsumesMediaTypes: []string{"application/octet-stream"}, Params: rwrtr, Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { @@ -837,12 +837,12 @@ func TestRuntime_ContentTypeCanary(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Method: http.MethodGet, PathPattern: "/", - Schemes: []string{"http"}, + Schemes: []string{schemeHTTP}, Params: rwrtr, Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { if response.Code() == http.StatusOK { @@ -892,12 +892,12 @@ func TestRuntime_ChunkedResponse(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Method: http.MethodGet, PathPattern: "/", - Schemes: []string{"http"}, + Schemes: []string{schemeHTTP}, Params: rwrtr, Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { if response.Code() == http.StatusOK { @@ -922,7 +922,7 @@ func TestRuntime_DebugValue(t *testing.T) { t.Run("empty DEBUG means Debug is False", func(t *testing.T) { t.Setenv("DEBUG", "") - runtime := New("", "/", []string{"https"}) + runtime := New("", "/", []string{schemeHTTPS}) assert.False(t, runtime.Debug) }) @@ -930,42 +930,42 @@ func TestRuntime_DebugValue(t *testing.T) { t.Run("with numerical value", func(t *testing.T) { t.Setenv("DEBUG", "1") - runtime := New("", "/", []string{"https"}) + runtime := New("", "/", []string{schemeHTTPS}) assert.True(t, runtime.Debug) }) t.Run("with boolean value true", func(t *testing.T) { t.Setenv("DEBUG", "true") - runtime := New("", "/", []string{"https"}) + runtime := New("", "/", []string{schemeHTTPS}) assert.True(t, runtime.Debug) }) t.Run("with boolean value false", func(t *testing.T) { t.Setenv("DEBUG", "false") - runtime := New("", "/", []string{"https"}) + runtime := New("", "/", []string{schemeHTTPS}) assert.False(t, runtime.Debug) }) t.Run("with string value ", func(t *testing.T) { t.Setenv("DEBUG", "foo") - runtime := New("", "/", []string{"https"}) + runtime := New("", "/", []string{schemeHTTPS}) assert.True(t, runtime.Debug) }) }) } func TestRuntime_OverrideScheme(t *testing.T) { - runtime := New("", "/", []string{"https"}) - sch := runtime.pickScheme([]string{"http"}) - assert.Equal(t, "https", sch) + runtime := New("", "/", []string{schemeHTTPS}) + sch := runtime.pickScheme([]string{schemeHTTP}) + assert.Equal(t, schemeHTTPS, sch) } func TestRuntime_OverrideClient(t *testing.T) { client := &http.Client{} - runtime := NewWithClient("", "/", []string{"https"}, client) + runtime := NewWithClient("", "/", []string{schemeHTTPS}, client) var i int runtime.clientOnce.Do(func() { i++ }) assert.Equal(t, client, runtime.client) @@ -986,7 +986,7 @@ func (o *overrideRoundTripper) RoundTrip(_ *http.Request) (*http.Response, error func TestRuntime_OverrideClientOperation(t *testing.T) { client := &http.Client{} - rt := NewWithClient("", "/", []string{"https"}, client) + rt := NewWithClient("", "/", []string{schemeHTTPS}, client) var i int rt.clientOnce.Do(func() { i++ }) assert.Equal(t, client, rt.client) @@ -1003,7 +1003,7 @@ func TestRuntime_OverrideClientOperation(t *testing.T) { return nil }), Reader: runtime.ClientResponseReaderFunc(func(_ runtime.ClientResponse, _ runtime.Consumer) (interface{}, error) { - return nil, nil //nolint:nilnil + return map[string]interface{}{}, nil }), }) require.NoError(t, err) @@ -1029,7 +1029,7 @@ func TestRuntime_PreserveTrailingSlash(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { return nil }) @@ -1044,7 +1044,7 @@ func TestRuntime_PreserveTrailingSlash(t *testing.T) { return nil, errors.New("expected Submit to preserve trailing slashes - this caused a redirect") } if response.Code() == http.StatusOK { - return nil, nil //nolint:nilnil + return map[string]interface{}{}, nil } return nil, errors.New("generic error") }), @@ -1067,14 +1067,14 @@ func TestRuntime_FallbackConsumer(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) // without the fallback consumer _, err = rt.Submit(&runtime.ClientOperation{ ID: "getTasks", Method: "POST", PathPattern: "/", - Schemes: []string{"http"}, + Schemes: []string{schemeHTTP}, ConsumesMediaTypes: []string{"application/octet-stream"}, Params: rwrtr, Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { @@ -1097,7 +1097,7 @@ func TestRuntime_FallbackConsumer(t *testing.T) { ID: "getTasks", Method: "POST", PathPattern: "/", - Schemes: []string{"http"}, + Schemes: []string{schemeHTTP}, ConsumesMediaTypes: []string{"application/octet-stream"}, Params: rwrtr, Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { @@ -1145,7 +1145,7 @@ func TestRuntime_AuthHeaderParamDetected(t *testing.T) { hu, err := url.Parse(server.URL) require.NoError(t, err) - rt := New(hu.Host, "/", []string{"http"}) + rt := New(hu.Host, "/", []string{schemeHTTP}) rt.DefaultAuthentication = BearerToken("not-the-super-secret-token") res, err := rt.Submit(&runtime.ClientOperation{ ID: "getTasks", diff --git a/client_operation.go b/client_operation.go index 1a1975f1..5a5d6356 100644 --- a/client_operation.go +++ b/client_operation.go @@ -30,7 +30,7 @@ type ClientOperation struct { AuthInfo ClientAuthInfoWriter Params ClientRequestWriter Reader ClientResponseReader - Context context.Context //nolint:containedctx + Context context.Context //nolint:containedctx // we precisely want this type to contain the request context Client *http.Client } diff --git a/client_request.go b/client_request.go index 654333af..4ebb2dea 100644 --- a/client_request.go +++ b/client_request.go @@ -37,10 +37,8 @@ type ClientRequestWriter interface { } // ClientRequest is an interface for things that know how to -// add information to a swagger client request -// -//nolint:interfacebloat -type ClientRequest interface { +// add information to a swagger client request. +type ClientRequest interface { //nolint:interfacebloat // a swagger-capable request is quite rich, hence the many getter/setters SetHeaderParam(string, ...string) error GetHeaderParams() http.Header diff --git a/internal/testing/petstore/api.go b/internal/testing/petstore/api.go index 9765ad6a..b9276b95 100644 --- a/internal/testing/petstore/api.go +++ b/internal/testing/petstore/api.go @@ -169,5 +169,5 @@ func (s *stubOperationHandler) ParameterModel() interface{} { } func (s *stubOperationHandler) Handle(_ interface{}) (interface{}, error) { - return nil, nil //nolint:nilnil + return map[string]interface{}{}, nil } diff --git a/internal/testing/simplepetstore/api.go b/internal/testing/simplepetstore/api.go index df7f1ddc..044710e9 100644 --- a/internal/testing/simplepetstore/api.go +++ b/internal/testing/simplepetstore/api.go @@ -59,7 +59,7 @@ var createPet = runtime.OperationHandlerFunc(func(data interface{}) (interface{} var deletePet = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) { id := data.(map[string]interface{})["id"].(int64) removePet(id) - return nil, nil //nolint:nilnil + return map[string]interface{}{}, nil }) var getPetByID = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) { diff --git a/middleware/context.go b/middleware/context.go index f68b7511..d890ed3b 100644 --- a/middleware/context.go +++ b/middleware/context.go @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//nolint:goconst package middleware import ( @@ -517,7 +516,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()})) pr, ok := prods[c.api.DefaultProduces()] if !ok { - panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format)) + panic(errors.New(http.StatusInternalServerError, cantFindProducer(format))) } prod = pr } @@ -550,7 +549,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st producers := c.api.ProducersFor(normalizeOffers(offers)) prod, ok := producers[format] 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 { panic(err) // let the recovery middleware deal with this @@ -571,7 +570,7 @@ func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []st prods := c.api.ProducersFor(normalizeOffers([]string{c.api.DefaultProduces()})) pr, ok := prods[c.api.DefaultProduces()] if !ok { - panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format)) + panic(errors.New(http.StatusInternalServerError, cantFindProducer(format))) } prod = pr } @@ -634,3 +633,7 @@ func (c *Context) RoutesHandler(builder Builder) http.Handler { } return NewRouter(c, b(NewOperationExecutor(c))) } + +func cantFindProducer(format string) string { + return "can't find a producer for " + format +} diff --git a/middleware/context_test.go b/middleware/context_test.go index 0db0042c..4c0a62d3 100644 --- a/middleware/context_test.go +++ b/middleware/context_test.go @@ -49,7 +49,7 @@ func (s *stubOperationHandler) ParameterModel() interface{} { } func (s *stubOperationHandler) Handle(_ interface{}) (interface{}, error) { - return nil, nil //nolint:nilnil + return map[string]interface{}{}, nil } func init() { diff --git a/middleware/denco/router.go b/middleware/denco/router.go index 2ddd2f94..1bfa5c61 100644 --- a/middleware/denco/router.go +++ b/middleware/denco/router.go @@ -51,7 +51,7 @@ func New() *Router { // 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"}]. func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool) { - if data, found := rt.static[path]; found { //nolint:govet + if data, found = rt.static[path]; found { return data, nil, true } if len(rt.param.node) == 1 { diff --git a/middleware/denco/server_test.go b/middleware/denco/server_test.go index e887c15d..fcc56db2 100644 --- a/middleware/denco/server_test.go +++ b/middleware/denco/server_test.go @@ -84,7 +84,9 @@ func TestNotFound(t *testing.T) { w.WriteHeader(http.StatusServiceUnavailable) fmt.Fprintf(w, "method: %s, path: %s, params: %v", r.Method, r.URL.Path, params) } - res, err := http.Get(server.URL) //nolint:noctx + req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, server.URL, nil) + require.NoError(t, err) + res, err := http.DefaultClient.Do(req) require.NoError(t, err) defer res.Body.Close() diff --git a/middleware/header/header.go b/middleware/header/header.go index 1923fa55..df073c87 100644 --- a/middleware/header/header.go +++ b/middleware/header/header.go @@ -195,9 +195,8 @@ func ParseAccept2(header http.Header, key string) (specs []AcceptSpec) { } // ParseAccept parses Accept* headers. -// -//nolint:nakedret -func ParseAccept(header http.Header, key string) (specs []AcceptSpec) { +func ParseAccept(header http.Header, key string) []AcceptSpec { + var specs []AcceptSpec loop: for _, s := range header[key] { for { @@ -220,6 +219,7 @@ loop: } } } + specs = append(specs, spec) s = skipSpace(s) if !strings.HasPrefix(s, ",") { @@ -228,7 +228,8 @@ loop: s = skipSpace(s[1:]) } } - return + + return specs } func skipSpace(s string) (rest string) { @@ -308,7 +309,7 @@ func expectTokenOrQuoted(s string) (value string, rest string) { p := make([]byte, len(s)-1) j := copy(p, s[:i]) escape := true - for i = i + 1; i < len(s); i++ { //nolint:gocritic + for i++; i < len(s); i++ { b := s[i] switch { case escape: diff --git a/middleware/parameter.go b/middleware/parameter.go index 97acfc12..9c3353a9 100644 --- a/middleware/parameter.go +++ b/middleware/parameter.go @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//nolint:goconst package middleware import ( @@ -35,6 +34,11 @@ import ( const defaultMaxMemory = 32 << 20 +const ( + typeString = "string" + typeArray = "array" +) + var textUnmarshalType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem() func newUntypedParamBinder(param spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedParamBinder { @@ -67,7 +71,7 @@ func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items case "boolean": return reflect.TypeOf(true) - case "string": + case typeString: if tt, ok := p.formats.GetType(format); ok { return tt } @@ -95,7 +99,7 @@ func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items return reflect.TypeOf(float64(0)) } - case "array": + case typeArray: if items == nil { return nil } @@ -120,7 +124,7 @@ func (p *untypedParamBinder) allowsMulti() bool { 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 - if tpe == "array" { + if tpe == typeArray { if cf == "multi" { if !p.allowsMulti() { return nil, false, false, errors.InvalidCollectionFormat(name, in, cf) @@ -209,10 +213,11 @@ func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams if ffErr != nil { if p.parameter.Required { return errors.NewParseError(p.Name, p.parameter.In, "", ffErr) - } else { //nolint:revive - return nil } + + return nil } + target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header})) return nil } @@ -264,7 +269,7 @@ func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams } 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) } var d string @@ -318,7 +323,7 @@ func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue in return nil } - switch target.Kind() { //nolint:exhaustive + switch target.Kind() { //nolint:exhaustive // we want to check only types that map from a swagger parameter case reflect.Bool: if data == "" { if target.CanSet() { diff --git a/middleware/parameter_test.go b/middleware/parameter_test.go index c2b0dddd..cbec8ab8 100644 --- a/middleware/parameter_test.go +++ b/middleware/parameter_test.go @@ -46,15 +46,14 @@ func np(param *spec.Parameter) *untypedParamBinder { var stringItems = new(spec.Items) func init() { - stringItems.Type = "string" + stringItems.Type = typeString } func testCollectionFormat(t *testing.T, param *spec.Parameter, valid bool) { binder := &untypedParamBinder{ parameter: param, } - // ICI - _, _, _, err := binder.readValue(runtime.Values(nil), reflect.ValueOf(nil)) //nolint:dogsled + _, _, _, err := binder.readValue(runtime.Values(nil), reflect.ValueOf(nil)) //nolint:dogsled // we just want to test the error if valid { require.NoError(t, err) } else { @@ -109,7 +108,7 @@ func validateRequiredAllowEmptyTest(t *testing.T, param *spec.Parameter, value r } func TestRequiredValidation(t *testing.T) { - strParam := spec.QueryParam("name").Typed("string", "").AsRequired() + strParam := spec.QueryParam("name").Typed(typeString, "").AsRequired() validateRequiredTest(t, strParam, reflect.ValueOf("")) validateRequiredAllowEmptyTest(t, strParam, reflect.ValueOf("")) @@ -127,11 +126,11 @@ func TestRequiredValidation(t *testing.T) { validateRequiredTest(t, doubleParam, reflect.ValueOf(float64(0))) validateRequiredAllowEmptyTest(t, doubleParam, reflect.ValueOf(float64(0))) - dateTimeParam := spec.QueryParam("registered").Typed("string", "date-time").AsRequired() + dateTimeParam := spec.QueryParam("registered").Typed(typeString, "date-time").AsRequired() validateRequiredTest(t, dateTimeParam, reflect.ValueOf(strfmt.DateTime{})) // validateRequiredAllowEmptyTest(t, dateTimeParam, reflect.ValueOf(strfmt.DateTime{})) - dateParam := spec.QueryParam("registered").Typed("string", "date").AsRequired() + dateParam := spec.QueryParam("registered").Typed(typeString, "date").AsRequired() validateRequiredTest(t, dateParam, reflect.ValueOf(strfmt.Date{})) // validateRequiredAllowEmptyTest(t, dateParam, reflect.ValueOf(strfmt.DateTime{})) @@ -234,7 +233,7 @@ func TestTypeValidation(t *testing.T) { require.EqualError(t, err, invalidTypeError(doubleParam, str4).Error()) // fails for invalid string - dateParam := newParam("badDate").Typed("string", "date") + dateParam := newParam("badDate").Typed(typeString, "date") value = reflect.ValueOf(strfmt.Date{}) binder = np(dateParam) err = binder.bindValue([]string{"yada"}, true, value) @@ -242,7 +241,7 @@ func TestTypeValidation(t *testing.T) { require.EqualError(t, err, invalidTypeError(dateParam, "yada").Error()) // fails for invalid string - dateTimeParam := newParam("badDateTime").Typed("string", "date-time") + dateTimeParam := newParam("badDateTime").Typed(typeString, "date-time") value = reflect.ValueOf(strfmt.DateTime{}) binder = np(dateTimeParam) err = binder.bindValue([]string{"yada"}, true, value) @@ -250,7 +249,7 @@ func TestTypeValidation(t *testing.T) { require.EqualError(t, err, invalidTypeError(dateTimeParam, "yada").Error()) // fails for invalid string - byteParam := newParam("badByte").Typed("string", "byte") + byteParam := newParam("badByte").Typed(typeString, "byte") values := url.Values(map[string][]string{}) values.Add("badByte", "yaĆ¼da") v5 := []byte{} @@ -271,7 +270,7 @@ func TestTypeDetectionInvalidItems(t *testing.T) { assert.Nil(t, binder.Type()) items := new(spec.Items) - items.Type = "array" + items.Type = typeArray withInvalidItems := spec.QueryParam("invalidItems").CollectionOf(items, "") binder = &untypedParamBinder{ Name: "invalidItems", @@ -331,7 +330,7 @@ func TestTypeDetectionInvalidItems(t *testing.T) { // } // // params := parametersForAllTypes("") -// emailParam := spec.QueryParam("email").Typed("string", "email") +// emailParam := spec.QueryParam("email").Typed(typeString, "email") // params["email"] = *emailParam // // fileParam := spec.FileParam("file") diff --git a/middleware/rapidoc.go b/middleware/rapidoc.go index c0593999..5cb5314d 100644 --- a/middleware/rapidoc.go +++ b/middleware/rapidoc.go @@ -1,4 +1,4 @@ -//nolint:dupl,goconst +//nolint:dupl package middleware import ( @@ -29,16 +29,16 @@ func (r *RapiDocOpts) EnsureDefaults() { r.BasePath = "/" } if r.Path == "" { - r.Path = "docs" + r.Path = defaultDocsPath } if r.SpecURL == "" { - r.SpecURL = "/swagger.json" + r.SpecURL = defaultDocsURL } if r.RapiDocURL == "" { r.RapiDocURL = rapidocLatest } if r.Title == "" { - r.Title = "API documentation" + r.Title = defaultDocsTitle } } diff --git a/middleware/rapidoc_test.go b/middleware/rapidoc_test.go index c15550a5..8c9f0ce4 100644 --- a/middleware/rapidoc_test.go +++ b/middleware/rapidoc_test.go @@ -2,6 +2,7 @@ package middleware import ( "context" + "fmt" "net/http" "net/http/httptest" "testing" @@ -19,7 +20,9 @@ func TestRapiDocMiddleware(t *testing.T) { rapidoc.ServeHTTP(recorder, req) assert.Equal(t, http.StatusOK, recorder.Code) assert.Equal(t, "text/html; charset=utf-8", recorder.Header().Get("Content-Type")) - assert.Contains(t, recorder.Body.String(), "API documentation") - assert.Contains(t, recorder.Body.String(), "") + var o RapiDocOpts + o.EnsureDefaults() + assert.Contains(t, recorder.Body.String(), fmt.Sprintf("%s", o.Title)) + assert.Contains(t, recorder.Body.String(), fmt.Sprintf("", o.SpecURL)) assert.Contains(t, recorder.Body.String(), rapidocLatest) } diff --git a/middleware/redoc.go b/middleware/redoc.go index 665d0592..ca1d4edc 100644 --- a/middleware/redoc.go +++ b/middleware/redoc.go @@ -29,16 +29,16 @@ func (r *RedocOpts) EnsureDefaults() { r.BasePath = "/" } if r.Path == "" { - r.Path = "docs" + r.Path = defaultDocsPath } if r.SpecURL == "" { - r.SpecURL = "/swagger.json" + r.SpecURL = defaultDocsURL } if r.RedocURL == "" { r.RedocURL = redocLatest } if r.Title == "" { - r.Title = "API documentation" + r.Title = defaultDocsTitle } } diff --git a/middleware/redoc_test.go b/middleware/redoc_test.go index 364d8cf0..71a7c1b8 100644 --- a/middleware/redoc_test.go +++ b/middleware/redoc_test.go @@ -2,6 +2,7 @@ package middleware import ( "context" + "fmt" "net/http" "net/http/httptest" "testing" @@ -19,7 +20,9 @@ func TestRedocMiddleware(t *testing.T) { redoc.ServeHTTP(recorder, req) assert.Equal(t, http.StatusOK, recorder.Code) assert.Equal(t, "text/html; charset=utf-8", recorder.Header().Get("Content-Type")) - assert.Contains(t, recorder.Body.String(), "API documentation") - assert.Contains(t, recorder.Body.String(), "") + var o RedocOpts + o.EnsureDefaults() + assert.Contains(t, recorder.Body.String(), fmt.Sprintf("%s", o.Title)) + assert.Contains(t, recorder.Body.String(), fmt.Sprintf("", o.SpecURL)) assert.Contains(t, recorder.Body.String(), redocLatest) } diff --git a/middleware/request.go b/middleware/request.go index 760c3786..d4b9fc6a 100644 --- a/middleware/request.go +++ b/middleware/request.go @@ -65,7 +65,7 @@ func (o *UntypedRequestBinder) Bind(request *http.Request, routeParams RoutePara if isMap { tpe := binder.Type() if tpe == nil { - if param.Schema.Type.Contains("array") { + if param.Schema.Type.Contains(typeArray) { tpe = reflect.TypeOf([]interface{}{}) } else { tpe = reflect.TypeOf(map[string]interface{}{}) diff --git a/middleware/request_test.go b/middleware/request_test.go index 91ba915b..b37085ec 100644 --- a/middleware/request_test.go +++ b/middleware/request_test.go @@ -77,7 +77,7 @@ func parametersForAllTypes(fmt string) map[string]spec.Parameter { if fmt == "" { fmt = csvFormat } - nameParam := spec.QueryParam("name").Typed("string", "") + nameParam := spec.QueryParam("name").Typed(typeString, "") idParam := spec.PathParam("id").Typed("integer", "int64") ageParam := spec.QueryParam("age").Typed("integer", "int32") scoreParam := spec.QueryParam("score").Typed("number", "float") @@ -91,13 +91,13 @@ func parametersForAllTypes(fmt string) map[string]spec.Parameter { requestIDParam.Extensions.Add("go-name", "RequestID") items := new(spec.Items) - items.Type = "string" + items.Type = typeString tagsParam := spec.QueryParam("tags").CollectionOf(items, fmt) confirmedParam := spec.QueryParam("confirmed").Typed("boolean", "") - plannedParam := spec.QueryParam("planned").Typed("string", "date") - deliveredParam := spec.QueryParam("delivered").Typed("string", "date-time") - pictureParam := spec.QueryParam("picture").Typed("string", "byte") // base64 encoded during transport + plannedParam := spec.QueryParam("planned").Typed(typeString, "date") + deliveredParam := spec.QueryParam("delivered").Typed(typeString, "date-time") + pictureParam := spec.QueryParam("picture").Typed(typeString, "byte") // base64 encoded during transport return map[string]spec.Parameter{ "ID": *idParam, @@ -119,7 +119,7 @@ func parametersForJSONRequestParams(fmt string) map[string]spec.Parameter { if fmt == "" { fmt = csvFormat } - nameParam := spec.QueryParam("name").Typed("string", "") + nameParam := spec.QueryParam("name").Typed(typeString, "") idParam := spec.PathParam("id").Typed("integer", "int64") friendSchema := new(spec.Schema).Typed("object", "") @@ -130,7 +130,7 @@ func parametersForJSONRequestParams(fmt string) map[string]spec.Parameter { requestIDParam.Extensions.Add("go-name", "RequestID") items := new(spec.Items) - items.Type = "string" + items.Type = typeString tagsParam := spec.QueryParam("tags").CollectionOf(items, fmt) return map[string]spec.Parameter{ @@ -145,7 +145,7 @@ func parametersForJSONRequestSliceParams(fmt string) map[string]spec.Parameter { if fmt == "" { fmt = csvFormat } - nameParam := spec.QueryParam("name").Typed("string", "") + nameParam := spec.QueryParam("name").Typed(typeString, "") idParam := spec.PathParam("id").Typed("integer", "int64") friendSchema := new(spec.Schema).Typed("object", "") @@ -156,7 +156,7 @@ func parametersForJSONRequestSliceParams(fmt string) map[string]spec.Parameter { requestIDParam.Extensions.Add("go-name", "RequestID") items := new(spec.Items) - items.Type = "string" + items.Type = typeString tagsParam := spec.QueryParam("tags").CollectionOf(items, fmt) return map[string]spec.Parameter{ @@ -276,7 +276,7 @@ func TestRequestBindingForInvalid(t *testing.T) { err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data) require.Error(t, err) - invalidInParam := spec.HeaderParam("tags").Typed("string", "") + invalidInParam := spec.HeaderParam("tags").Typed(typeString, "") invalidInParam.In = "invalid" op5 := map[string]spec.Parameter{"Tags": *invalidInParam} binder = NewUntypedRequestBinder(op5, new(spec.Swagger), strfmt.Default) @@ -383,7 +383,7 @@ type formRequest struct { } func parametersForFormUpload() map[string]spec.Parameter { - nameParam := spec.FormDataParam("name").Typed("string", "") + nameParam := spec.FormDataParam("name").Typed(typeString, "") ageParam := spec.FormDataParam("age").Typed("integer", "int32") @@ -419,7 +419,7 @@ type fileRequest struct { } func paramsForFileUpload() *UntypedRequestBinder { - nameParam := spec.FormDataParam("name").Typed("string", "") + nameParam := spec.FormDataParam("name").Typed(typeString, "") fileParam := spec.FileParam("file").AsRequired() @@ -506,7 +506,7 @@ func TestBindingFileUpload(t *testing.T) { } func paramsForOptionalFileUpload() *UntypedRequestBinder { - nameParam := spec.FormDataParam("name").Typed("string", "") + nameParam := spec.FormDataParam("name").Typed(typeString, "") fileParam := spec.FileParam("file").AsOptional() params := map[string]spec.Parameter{"Name": *nameParam, "File": *fileParam} diff --git a/middleware/router.go b/middleware/router.go index 5e057b8f..46b8f87c 100644 --- a/middleware/router.go +++ b/middleware/router.go @@ -449,11 +449,11 @@ func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Oper func (d *defaultRouteBuilder) buildAuthenticators(operation *spec.Operation) RouteAuthenticators { requirements := d.analyzer.SecurityRequirementsFor(operation) - var auths []RouteAuthenticator //nolint:prealloc + auths := make([]RouteAuthenticator, 0, len(requirements)) for _, reqs := range requirements { - var schemes []string + schemes := make([]string, 0, len(reqs)) scopes := make(map[string][]string, len(reqs)) - var scopeSlices [][]string + scopeSlices := make([][]string, 0, len(reqs)) for _, req := range reqs { schemes = append(schemes, req.Name) scopes[req.Name] = req.Scopes diff --git a/middleware/string_conversion_test.go b/middleware/string_conversion_test.go index d577d6e3..2265b51d 100644 --- a/middleware/string_conversion_test.go +++ b/middleware/string_conversion_test.go @@ -109,7 +109,7 @@ func TestParamBinding(t *testing.T) { fld := val.FieldByName(pName) binder := &untypedParamBinder{ - parameter: spec.QueryParam(pName).Typed("string", "").WithDefault("some-name"), + parameter: spec.QueryParam(pName).Typed(typeString, "").WithDefault("some-name"), Name: pName, } @@ -172,7 +172,7 @@ func TestParamBinding(t *testing.T) { timeField := val.FieldByName(pName) dt := strfmt.DateTime(time.Date(2014, 3, 19, 2, 9, 0, 0, time.UTC)) binder = &untypedParamBinder{ - parameter: spec.QueryParam(pName).Typed("string", "date-time").WithDefault(dt), + parameter: spec.QueryParam(pName).Typed(typeString, "date-time").WithDefault(dt), Name: pName, } exp := strfmt.DateTime(time.Date(2014, 5, 14, 2, 9, 0, 0, time.UTC)) @@ -192,7 +192,7 @@ func TestParamBinding(t *testing.T) { pName = "Birthdate" dateField := val.FieldByName(pName) binder = &untypedParamBinder{ - parameter: spec.QueryParam(pName).Typed("string", "date").WithDefault(ddt), + parameter: spec.QueryParam(pName).Typed(typeString, "date").WithDefault(ddt), Name: pName, } expd := strfmt.Date(time.Date(2014, 5, 14, 0, 0, 0, 0, time.UTC)) @@ -213,7 +213,7 @@ func TestParamBinding(t *testing.T) { pName = "LastFailure" ftimeField := val.FieldByName(pName) binder = &untypedParamBinder{ - parameter: spec.QueryParam(pName).Typed("string", "date").WithDefault(fdt), + parameter: spec.QueryParam(pName).Typed(typeString, "date").WithDefault(fdt), Name: pName, } exp = strfmt.DateTime(time.Date(2014, 5, 14, 2, 9, 0, 0, time.UTC)) @@ -239,7 +239,7 @@ func TestParamBinding(t *testing.T) { pName = "Unsupported" unsupportedField := val.FieldByName(pName) binder = &untypedParamBinder{ - parameter: spec.QueryParam(pName).Typed("string", ""), + parameter: spec.QueryParam(pName).Typed(typeString, ""), Name: pName, } err = binder.setFieldValue(unsupportedField, nil, "", true) @@ -255,7 +255,7 @@ func TestSliceConversion(t *testing.T) { // _, _, err := readFormattedSliceFieldValue("Prefs", prefsField, cData, "csv", nil) // require.Error(t, err) - sliced := []string{"some", "string", "values"} + sliced := []string{"some", typeString, "values"} seps := map[string]string{"ssv": " ", "tsv": "\t", "pipes": "|", "csv": ",", "": ","} tagsField := val.FieldByName("Tags") diff --git a/middleware/swaggerui.go b/middleware/swaggerui.go index b4dea29e..846e3cfb 100644 --- a/middleware/swaggerui.go +++ b/middleware/swaggerui.go @@ -37,10 +37,10 @@ func (r *SwaggerUIOpts) EnsureDefaults() { r.BasePath = "/" } if r.Path == "" { - r.Path = "docs" + r.Path = defaultDocsPath } if r.SpecURL == "" { - r.SpecURL = "/swagger.json" + r.SpecURL = defaultDocsURL } if r.OAuthCallbackURL == "" { r.OAuthCallbackURL = path.Join(r.BasePath, r.Path, "oauth2-callback") @@ -61,7 +61,7 @@ func (r *SwaggerUIOpts) EnsureDefaults() { r.Favicon32 = swaggerFavicon32Latest } if r.Title == "" { - r.Title = "API documentation" + r.Title = defaultDocsTitle } } diff --git a/middleware/swaggerui_oauth2_test.go b/middleware/swaggerui_oauth2_test.go index 7d3796f0..c9b28c97 100644 --- a/middleware/swaggerui_oauth2_test.go +++ b/middleware/swaggerui_oauth2_test.go @@ -2,6 +2,7 @@ package middleware import ( "context" + "fmt" "net/http" "net/http/httptest" "testing" @@ -19,5 +20,7 @@ func TestSwaggerUIOAuth2CallbackMiddleware(t *testing.T) { redoc.ServeHTTP(recorder, req) assert.Equal(t, http.StatusOK, recorder.Code) assert.Equal(t, "text/html; charset=utf-8", recorder.Header().Get("Content-Type")) - assert.Contains(t, recorder.Body.String(), "API documentation") + var o SwaggerUIOpts + o.EnsureDefaults() + assert.Contains(t, recorder.Body.String(), fmt.Sprintf("%s", o.Title)) } diff --git a/middleware/swaggerui_test.go b/middleware/swaggerui_test.go index 0613db01..4047e66c 100644 --- a/middleware/swaggerui_test.go +++ b/middleware/swaggerui_test.go @@ -2,8 +2,10 @@ package middleware import ( "context" + "fmt" "net/http" "net/http/httptest" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -11,16 +13,18 @@ import ( ) func TestSwaggerUIMiddleware(t *testing.T) { - redoc := SwaggerUI(SwaggerUIOpts{}, nil) + var o SwaggerUIOpts + o.EnsureDefaults() + swui := SwaggerUI(o, nil) req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/docs", nil) require.NoError(t, err) recorder := httptest.NewRecorder() - redoc.ServeHTTP(recorder, req) + swui.ServeHTTP(recorder, req) assert.Equal(t, http.StatusOK, recorder.Code) assert.Equal(t, "text/html; charset=utf-8", recorder.Header().Get("Content-Type")) - assert.Contains(t, recorder.Body.String(), "API documentation") - assert.Contains(t, recorder.Body.String(), "url: '\\/swagger.json',") + assert.Contains(t, recorder.Body.String(), fmt.Sprintf("%s", o.Title)) + assert.Contains(t, recorder.Body.String(), fmt.Sprintf(`url: '%s',`, strings.ReplaceAll(o.SpecURL, `/`, `\/`))) assert.Contains(t, recorder.Body.String(), swaggerLatest) assert.Contains(t, recorder.Body.String(), swaggerPresetLatest) assert.Contains(t, recorder.Body.String(), swaggerStylesLatest) diff --git a/middleware/ui_defaults.go b/middleware/ui_defaults.go new file mode 100644 index 00000000..25817d20 --- /dev/null +++ b/middleware/ui_defaults.go @@ -0,0 +1,8 @@ +package middleware + +const ( + // constants that are common to all UI-serving middlewares + defaultDocsPath = "docs" + defaultDocsURL = "/swagger.json" + defaultDocsTitle = "API Documentation" +) diff --git a/middleware/untyped/api.go b/middleware/untyped/api.go index 94788d26..7b7269bd 100644 --- a/middleware/untyped/api.go +++ b/middleware/untyped/api.go @@ -197,30 +197,31 @@ func (d *API) Validate() error { // validateWith validates the registrations in this API against the provided spec analyzer func (d *API) validate() error { - var consumes []string //nolint:prealloc + consumes := make([]string, 0, len(d.consumers)) for k := range d.consumers { consumes = append(consumes, k) } - var produces []string //nolint:prealloc + produces := make([]string, 0, len(d.producers)) for k := range d.producers { produces = append(produces, k) } - var authenticators []string //nolint:prealloc + authenticators := make([]string, 0, len(d.authenticators)) for k := range d.authenticators { authenticators = append(authenticators, k) } - var operations []string + operations := make([]string, 0, len(d.operations)) for m, v := range d.operations { for p := range v { operations = append(operations, fmt.Sprintf("%s %s", strings.ToUpper(m), p)) } } - var definedAuths []string //nolint:prealloc - for k := range d.spec.Spec().SecurityDefinitions { + secDefinitions := d.spec.Spec().SecurityDefinitions + definedAuths := make([]string, 0, len(secDefinitions)) + for k := range secDefinitions { definedAuths = append(definedAuths, k) } @@ -267,7 +268,7 @@ func (d *API) verify(name string, registrations []string, expectations []string) delete(expected, k) } - var unregistered []string //nolint:prealloc + unregistered := make([]string, 0, len(expected)) for k := range expected { unregistered = append(unregistered, k) } diff --git a/middleware/untyped/api_test.go b/middleware/untyped/api_test.go index 9c10f9a6..fa2a1fe6 100644 --- a/middleware/untyped/api_test.go +++ b/middleware/untyped/api_test.go @@ -59,7 +59,7 @@ func (s *stubOperationHandler) ParameterModel() interface{} { } func (s *stubOperationHandler) Handle(_ interface{}) (interface{}, error) { - return nil, nil //nolint:nilnil + return map[string]interface{}{}, nil } func TestUntypedAPIRegistrations(t *testing.T) { diff --git a/request.go b/request.go index 3b9e9836..9e3e1ecb 100644 --- a/request.go +++ b/request.go @@ -16,6 +16,7 @@ package runtime import ( "bufio" + "context" "errors" "io" "net/http" @@ -114,9 +115,11 @@ func (p *peekingReader) Close() error { 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) { - req, err := http.NewRequest(method, urlStr, body) //nolint:noctx + req, err := http.NewRequestWithContext(context.Background(), method, urlStr, body) if err != nil { return nil, err } diff --git a/security/authenticator.go b/security/authenticator.go index 8653b86b..a57d5e80 100644 --- a/security/authenticator.go +++ b/security/authenticator.go @@ -158,7 +158,7 @@ func APIKeyAuth(name, in string, authenticate TokenAuthentication) runtime.Authe inl := strings.ToLower(in) if inl != query && inl != header { // panic because this is most likely a typo - panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\".")) //nolint:revive + panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\"")) } var getToken func(*http.Request) string @@ -186,7 +186,7 @@ func APIKeyAuthCtx(name, in string, authenticate TokenAuthenticationCtx) runtime inl := strings.ToLower(in) if inl != query && inl != header { // panic because this is most likely a typo - panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\".")) //nolint:revive + panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\"")) } var getToken func(*http.Request) string