File: //opt/go/pkg/mod/github.com/go-openapi/
[email protected]/middleware/untyped/api_test.go
// Copyright 2015 go-swagger maintainers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package untyped
import (
"io"
"net/http"
"sort"
"testing"
"github.com/go-openapi/analysis"
"github.com/go-openapi/errors"
"github.com/go-openapi/loads"
"github.com/go-openapi/runtime"
swaggerspec "github.com/go-openapi/spec"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func stubAutenticator() runtime.Authenticator {
return runtime.AuthenticatorFunc(func(_ interface{}) (bool, interface{}, error) { return false, nil, nil })
}
func stubAuthorizer() runtime.Authorizer {
return runtime.AuthorizerFunc(func(_ *http.Request, _ interface{}) error { return nil })
}
type stubConsumer struct {
}
func (s *stubConsumer) Consume(_ io.Reader, _ interface{}) error {
return nil
}
type stubProducer struct {
}
func (s *stubProducer) Produce(_ io.Writer, _ interface{}) error {
return nil
}
type stubOperationHandler struct {
}
func (s *stubOperationHandler) ParameterModel() interface{} {
return nil
}
func (s *stubOperationHandler) Handle(_ interface{}) (interface{}, error) {
return map[string]interface{}{}, nil
}
func TestUntypedAPIRegistrations(t *testing.T) {
api := NewAPI(new(loads.Document)).WithJSONDefaults()
api.RegisterConsumer("application/yada", new(stubConsumer))
api.RegisterProducer("application/yada-2", new(stubProducer))
api.RegisterOperation("get", "/{someId}", new(stubOperationHandler))
api.RegisterAuth("basic", stubAutenticator())
api.RegisterAuthorizer(stubAuthorizer())
assert.NotNil(t, api.authorizer)
assert.NotEmpty(t, api.authenticators)
_, ok := api.authenticators["basic"]
assert.True(t, ok)
_, ok = api.consumers["application/yada"]
assert.True(t, ok)
_, ok = api.producers["application/yada-2"]
assert.True(t, ok)
_, ok = api.consumers["application/json"]
assert.True(t, ok)
_, ok = api.producers["application/json"]
assert.True(t, ok)
_, ok = api.operations["GET"]["/{someId}"]
assert.True(t, ok)
authorizer := api.Authorizer()
assert.NotNil(t, authorizer)
h, ok := api.OperationHandlerFor("get", "/{someId}")
assert.True(t, ok)
assert.NotNil(t, h)
_, ok = api.OperationHandlerFor("doesntExist", "/{someId}")
assert.False(t, ok)
}
func TestUntypedAppValidation(t *testing.T) {
invalidSpecStr := `{
"consumes": ["application/json"],
"produces": ["application/json"],
"security": [
{"apiKey":[]}
],
"parameters": {
"format": {
"in": "query",
"name": "format",
"type": "string"
}
},
"paths": {
"/": {
"parameters": [
{
"name": "limit",
"type": "integer",
"format": "int32",
"x-go-name": "Limit"
}
],
"get": {
"consumes": ["application/x-yaml"],
"produces": ["application/x-yaml"],
"security": [
{"basic":[]}
],
"parameters": [
{
"name": "skip",
"type": "integer",
"format": "int32"
}
]
}
}
}
}`
specStr := `{
"consumes": ["application/json"],
"produces": ["application/json"],
"security": [
{"apiKey":[]}
],
"securityDefinitions": {
"basic": { "type": "basic" },
"apiKey": { "type": "apiKey", "in":"header", "name":"X-API-KEY" }
},
"parameters": {
"format": {
"in": "query",
"name": "format",
"type": "string"
}
},
"paths": {
"/": {
"parameters": [
{
"name": "limit",
"type": "integer",
"format": "int32",
"x-go-name": "Limit"
}
],
"get": {
"consumes": ["application/x-yaml"],
"produces": ["application/x-yaml"],
"security": [
{"basic":[]}
],
"parameters": [
{
"name": "skip",
"type": "integer",
"format": "int32"
}
]
}
}
}
}`
validSpec, err := loads.Analyzed([]byte(specStr), "")
require.NoError(t, err)
assert.NotNil(t, validSpec)
spec, err := loads.Analyzed([]byte(invalidSpecStr), "")
require.NoError(t, err)
assert.NotNil(t, spec)
analyzed := analysis.New(spec.Spec())
analyzedValid := analysis.New(validSpec.Spec())
cons := analyzed.ConsumesFor(analyzed.AllPaths()["/"].Get)
assert.Len(t, cons, 1)
prods := analyzed.RequiredProduces()
assert.Len(t, prods, 2)
api1 := NewAPI(spec)
err = api1.Validate()
require.Error(t, err)
assert.Equal(t, "missing [application/x-yaml] consumes registrations", err.Error())
api1.RegisterConsumer("application/x-yaml", new(stubConsumer))
err = api1.validate()
require.Error(t, err)
assert.Equal(t, "missing [application/x-yaml] produces registrations", err.Error())
api1.RegisterProducer("application/x-yaml", new(stubProducer))
err = api1.validate()
require.Error(t, err)
assert.Equal(t, "missing [GET /] operation registrations", err.Error())
api1.RegisterOperation("get", "/", new(stubOperationHandler))
err = api1.validate()
require.Error(t, err)
assert.Equal(t, "missing [apiKey, basic] auth scheme registrations", err.Error())
api1.RegisterAuth("basic", stubAutenticator())
api1.RegisterAuth("apiKey", stubAutenticator())
err = api1.validate()
require.Error(t, err)
assert.Equal(t, "missing [apiKey, basic] security definitions registrations", err.Error())
api3 := NewAPI(validSpec)
api3.RegisterConsumer("application/x-yaml", new(stubConsumer))
api3.RegisterProducer("application/x-yaml", new(stubProducer))
api3.RegisterOperation("get", "/", new(stubOperationHandler))
api3.RegisterAuth("basic", stubAutenticator())
api3.RegisterAuth("apiKey", stubAutenticator())
err = api3.validate()
require.NoError(t, err)
api3.RegisterConsumer("application/something", new(stubConsumer))
err = api3.validate()
require.Error(t, err)
assert.Equal(t, "missing from spec file [application/something] consumes", err.Error())
api2 := NewAPI(spec)
api2.RegisterConsumer("application/something", new(stubConsumer))
err = api2.validate()
require.Error(t, err)
assert.Equal(t, "missing [application/x-yaml] consumes registrations\nmissing from spec file [application/something] consumes", err.Error())
api2.RegisterConsumer("application/x-yaml", new(stubConsumer))
delete(api2.consumers, "application/something")
api2.RegisterProducer("application/something", new(stubProducer))
err = api2.validate()
require.Error(t, err)
assert.Equal(t, "missing [application/x-yaml] produces registrations\nmissing from spec file [application/something] produces", err.Error())
delete(api2.producers, "application/something")
api2.RegisterProducer("application/x-yaml", new(stubProducer))
expected := []string{"application/x-yaml"}
sort.Strings(expected)
consumes := analyzed.ConsumesFor(analyzed.AllPaths()["/"].Get)
sort.Strings(consumes)
assert.Equal(t, expected, consumes)
consumers := api1.ConsumersFor(consumes)
assert.Len(t, consumers, 1)
produces := analyzed.ProducesFor(analyzed.AllPaths()["/"].Get)
sort.Strings(produces)
assert.Equal(t, expected, produces)
producers := api1.ProducersFor(produces)
assert.Len(t, producers, 1)
definitions := analyzedValid.SecurityDefinitionsFor(analyzedValid.AllPaths()["/"].Get)
expectedSchemes := map[string]swaggerspec.SecurityScheme{"basic": *swaggerspec.BasicAuth()}
assert.Equal(t, expectedSchemes, definitions)
authenticators := api3.AuthenticatorsFor(definitions)
assert.Len(t, authenticators, 1)
opHandler := runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) {
return data, nil
})
d, err := opHandler.Handle(1)
require.NoError(t, err)
assert.Equal(t, 1, d)
authenticator := runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
if str, ok := params.(string); ok {
return ok, str, nil
}
return true, nil, errors.Unauthenticated("authenticator")
})
ok, p, err := authenticator.Authenticate("hello")
assert.True(t, ok)
require.NoError(t, err)
assert.Equal(t, "hello", p)
}