From e0cdd625d2a40edefb7e4c8f9af1c2fa5a349ad3 Mon Sep 17 00:00:00 2001 From: Anhad Jai Singh Date: Mon, 30 Oct 2017 22:37:58 +0530 Subject: [PATCH] Add more dependencies required by pdns-go --- glide.lock | 32 +- glide.yaml | 4 +- .../asaskevich/govalidator/.travis.yml | 14 + .../github.com/asaskevich/govalidator/LICENSE | 21 + .../asaskevich/govalidator/README.md | 423 ++ .../asaskevich/govalidator/arrays.go | 58 + .../asaskevich/govalidator/arrays_test.go | 116 + .../asaskevich/govalidator/converter.go | 45 + .../asaskevich/govalidator/converter_test.go | 78 + .../asaskevich/govalidator/error.go | 36 + .../asaskevich/govalidator/error_test.go | 29 + .../asaskevich/govalidator/numerics.go | 57 + .../asaskevich/govalidator/numerics_test.go | 204 + .../asaskevich/govalidator/patterns.go | 90 + .../asaskevich/govalidator/types.go | 613 +++ .../asaskevich/govalidator/utils.go | 262 + .../asaskevich/govalidator/utils_test.go | 500 ++ .../asaskevich/govalidator/validator.go | 1061 ++++ .../asaskevich/govalidator/validator_test.go | 2949 ++++++++++ .../asaskevich/govalidator/wercker.yml | 15 + .../analysis/.github/CONTRIBUTING.md | 117 + .../github.com/go-openapi/analysis/.gitignore | 3 + .../go-openapi/analysis/.travis.yml | 18 + .../go-openapi/analysis/CODE_OF_CONDUCT.md | 74 + vendor/github.com/go-openapi/analysis/LICENSE | 202 + .../github.com/go-openapi/analysis/README.md | 6 + .../go-openapi/analysis/analyzer.go | 785 +++ .../go-openapi/analysis/analyzer_test.go | 284 + .../go-openapi/analysis/fixtures/allOf.yml | 43 + .../go-openapi/analysis/fixtures/bar-crud.yml | 180 + .../analysis/fixtures/definitions.yml | 86 + .../analysis/fixtures/empty-paths.json | 8 + .../fixtures/external/definitions.yml | 50 + .../fixtures/external/definitions2.yml | 9 + .../analysis/fixtures/external/errors.yml | 13 + .../fixtures/external/nestedParams.yml | 35 + .../fixtures/external/nestedResponses.yml | 32 + .../analysis/fixtures/external/parameters.yml | 12 + .../analysis/fixtures/external/pathItem.yml | 9 + .../analysis/fixtures/external/responses.yml | 4 + .../fixtures/external_definitions.yml | 95 + .../go-openapi/analysis/fixtures/flatten.yml | 85 + .../go-openapi/analysis/fixtures/foo-crud.yml | 180 + .../analysis/fixtures/inline_schemas.yml | 187 + .../fixtures/nested_inline_schemas.yml | 298 + .../go-openapi/analysis/fixtures/no-paths.yml | 38 + .../go-openapi/analysis/fixtures/patterns.yml | 124 + .../analysis/fixtures/references.yml | 89 + .../analysis/fixtures/widget-crud.yml | 181 + .../github.com/go-openapi/analysis/flatten.go | 756 +++ .../go-openapi/analysis/flatten_test.go | 805 +++ .../github.com/go-openapi/analysis/mixin.go | 199 + .../go-openapi/analysis/mixin_test.go | 64 + .../github.com/go-openapi/analysis/schema.go | 233 + .../go-openapi/analysis/schema_test.go | 266 + .../go-openapi/errors/.github/CONTRIBUTING.md | 117 + .../github.com/go-openapi/errors/.gitignore | 2 + .../github.com/go-openapi/errors/.travis.yml | 12 + .../go-openapi/errors/CODE_OF_CONDUCT.md | 74 + vendor/github.com/go-openapi/errors/LICENSE | 202 + vendor/github.com/go-openapi/errors/README.md | 5 + vendor/github.com/go-openapi/errors/api.go | 150 + .../github.com/go-openapi/errors/api_test.go | 97 + vendor/github.com/go-openapi/errors/auth.go | 20 + .../github.com/go-openapi/errors/auth_test.go | 27 + .../github.com/go-openapi/errors/headers.go | 85 + .../go-openapi/errors/middleware.go | 51 + .../go-openapi/errors/middleware_test.go | 33 + .../github.com/go-openapi/errors/parsing.go | 59 + .../go-openapi/errors/parsing_test.go | 32 + vendor/github.com/go-openapi/errors/schema.go | 548 ++ .../go-openapi/errors/schema_test.go | 284 + vendor/github.com/go-openapi/loads/.drone.yml | 39 + .../github.com/go-openapi/loads/.editorconfig | 26 + .../go-openapi/loads/.github/CONTRIBUTING.md | 117 + vendor/github.com/go-openapi/loads/.gitignore | 4 + .../github.com/go-openapi/loads/.travis.yml | 16 + .../go-openapi/loads/CODE_OF_CONDUCT.md | 74 + vendor/github.com/go-openapi/loads/LICENSE | 202 + vendor/github.com/go-openapi/loads/README.md | 5 + .../json/models/modelWithArrayRef.json | 17 + .../json/models/modelWithComposition.json | 68 + .../json/models/modelWithDateTimeMap.json | 7 + .../json/models/modelWithExamples.json | 28 + .../json/models/modelWithInt32Map.json | 7 + .../json/models/modelWithInt64Map.json | 7 + .../models/modelWithMultipleProperties.json | 67 + .../json/models/modelWithObjectMap.json | 15 + .../json/models/modelWithPrimitiveArray.json | 18 + .../json/models/modelWithStringProperty.json | 8 + .../json/models/modelWithXmlAttributes.json | 26 + .../loads/fixtures/json/models/models.json | 14 + .../fixtures/json/models/multipleModels.json | 28 + .../properties/propertyWithBooleanArray.json | 6 + .../properties/propertyWithByteArray.json | 7 + .../properties/propertyWithComplexArray.json | 6 + .../properties/propertyWithDateTimeArray.json | 7 + .../properties/propertyWithInt32Array.json | 7 + .../properties/propertyWithInt64Array.json | 7 + .../models/properties/propertyWithRef.json | 5 + .../properties/propertyWithStringArray.json | 6 + .../properties/simpleBooleanProperty.json | 5 + .../models/properties/simpleByteProperty.json | 4 + .../properties/simpleDateTimeProperty.json | 4 + .../properties/simpleInt32Property.json | 4 + .../properties/simpleInt64Property.json | 4 + .../properties/simpleStringProperty.json | 3 + .../json/resources/cascadingSchemes.json | 98 + .../json/resources/commonParameters.json | 100 + .../json/resources/multipleMimeTypes.json | 109 + .../operations/operationWithTags.json | 30 + .../stringPathAndBoolQueryParamResource.json | 36 + .../operations/stringPathParamResource.json | 33 + .../parameters/bodyComplexArrayParameter.json | 13 + .../parameters/bodyComplexParameter.json | 9 + .../parameters/bodyInt64Parameter.json | 10 + .../parameters/bodyStringArrayParameter.json | 12 + .../parameters/bodyStringParameter.json | 9 + .../parameters/formDataComplexParameter.json | 7 + .../parameters/formDataInt64Parameter.json | 8 + .../formDataStringArrayParameter.json | 10 + .../parameters/formDataStringParameter.json | 7 + .../parameters/headerInt64ArrayParameter.json | 12 + .../headerStringArrayParameter.json | 11 + .../parameters/headerStringParameter.json | 7 + .../parameters/pathInt64Parameter.json | 8 + .../parameters/pathStringArrayParameter.json | 11 + .../parameters/pathStringParameter.json | 7 + .../parameters/queryInt64ArrayParameter.json | 12 + .../parameters/queryStringParameter.json | 8 + .../parameters/queryWithComplexParameter.json | 9 + .../resources/resourceWithExamplePayload.json | 114 + .../resourceWithLinkedDefinitions.json | 62 + .../resourceWithLinkedDefinitions_part1.json | 38 + .../resources/resourceWithRelativeHost.json | 99 + .../json/resources/reusableParameters.json | 105 + .../json/resources/securityExample.json | 181 + .../resources/stringPathParamResource.json | 97 + .../json/resources/taggedResource.json | 112 + .../resources/vendorExtensionExamples.json | 107 + .../json/responses/complexArrayResponse.json | 9 + .../json/responses/dateTimeResponse.json | 7 + .../json/responses/int32Response.json | 7 + .../json/responses/int64Response.json | 7 + .../json/responses/multipleResponses.json | 18 + .../json/responses/stringArrayResponse.json | 9 + .../json/responses/stringResponse.json | 6 + .../responses/stringResponseWithHeader.json | 10 + .../fixtures/json/responses/voidResponse.json | 3 + .../go-openapi/loads/fixtures/yaml/.gitkeep | 0 .../yaml/models/modelWithArrayRef.yaml | 5 + .../yaml/models/modelWithComposition.yaml | 5 + .../yaml/models/modelWithDateTimeMap.yaml | 4 + .../yaml/models/modelWithExamples.yaml | 3 + .../yaml/models/modelWithInt32Map.yaml | 4 + .../yaml/models/modelWithInt64Map.yaml | 4 + .../models/modelWithMultipleProperties.yaml | 14 + .../yaml/models/modelWithObjectMap.yaml | 9 + .../yaml/models/modelWithPrimitiveArray.yaml | 5 + .../yaml/models/modelWithStringProperty.yaml | 3 + .../yaml/models/modelWithXmlAttributes.yaml | 6 + .../loads/fixtures/yaml/models/models.yaml | 2 + .../fixtures/yaml/models/multipleModels.yaml | 3 + .../properties/propertyWithBooleanArray.yaml | 3 + .../properties/propertyWithByteArray.yaml | 4 + .../properties/propertyWithComplexArray.yaml | 3 + .../properties/propertyWithDateTimeArray.yaml | 4 + .../properties/propertyWithInt32Array.yaml | 4 + .../properties/propertyWithInt64Array.yaml | 4 + .../models/properties/propertyWithRef.yaml | 3 + .../properties/propertyWithStringArray.yaml | 3 + .../properties/simpleBooleanProperty.yaml | 3 + .../models/properties/simpleByteProperty.yaml | 2 + .../properties/simpleDateTimeProperty.yaml | 2 + .../properties/simpleInt32Property.yaml | 2 + .../properties/simpleInt64Property.yaml | 2 + .../properties/simpleStringProperty.yaml | 1 + .../yaml/resources/cascadingSchemes.yaml | 23 + .../yaml/resources/commonParameters.yaml | 23 + .../yaml/resources/multipleMimeTypes.yaml | 32 + .../operations/operationWithTags.yaml | 14 + .../stringPathAndBoolQueryParamResource.yaml | 12 + .../operations/stringPathParamResource.yaml | 12 + .../parameters/bodyComplexArrayParameter.yaml | 8 + .../parameters/bodyComplexParameter.yaml | 6 + .../parameters/bodyInt64Parameter.yaml | 7 + .../parameters/bodyStringArrayParameter.yaml | 7 + .../parameters/bodyStringParameter.yaml | 6 + .../parameters/formDataComplexParameter.yaml | 5 + .../parameters/formDataInt64Parameter.yaml | 6 + .../formDataStringArrayParameter.yaml | 7 + .../parameters/formDataStringParameter.yaml | 5 + .../parameters/headerInt64ArrayParameter.yaml | 9 + .../headerStringArrayParameter.yaml | 8 + .../parameters/headerStringParameter.yaml | 5 + .../parameters/pathInt64Parameter.yaml | 6 + .../parameters/pathStringArrayParameter.yaml | 8 + .../parameters/pathStringParameter.yaml | 5 + .../parameters/queryInt64ArrayParameter.yaml | 9 + .../parameters/queryStringParameter.yaml | 6 + .../parameters/queryWithComplexParameter.yaml | 6 + .../resources/resourceWithExamplePayload.yaml | 23 + .../resourceWithLinkedDefinitions.yaml | 23 + .../resourceWithLinkedDefinitions_part1.yaml | 7 + .../resources/resourceWithRelativeHost.yaml | 22 + .../yaml/resources/reusableParameters.yaml | 26 + .../yaml/resources/securityExample.yaml | 29 + .../resources/stringPathParamResource.yaml | 23 + .../yaml/resources/taggedResource.yaml | 29 + .../resources/vendorExtensionExamples.yaml | 27 + .../yaml/responses/complexArrayResponse.yaml | 4 + .../yaml/responses/dateTimeResponse.yaml | 4 + .../yaml/responses/int32Response.yaml | 4 + .../yaml/responses/int64Response.yaml | 4 + .../yaml/responses/multipleResponses.yaml | 8 + .../yaml/responses/stringArrayResponse.yaml | 4 + .../yaml/responses/stringResponse.yaml | 3 + .../responses/stringResponseWithHeader.yaml | 6 + .../fixtures/yaml/responses/voidResponse.yaml | 1 + .../yaml/swagger/1/2/3/4/swagger.yaml | 42 + .../yaml/swagger/shared/definitions/page.yaml | 18 + .../yaml/swagger/shared/something.yaml | 44 + .../loads/fixtures/yaml/yaml/.gitkeep | 0 .../yaml/yaml/models/modelWithArrayRef.yaml | 5 + .../yaml/models/modelWithComposition.yaml | 5 + .../yaml/models/modelWithDateTimeMap.yaml | 4 + .../yaml/yaml/models/modelWithExamples.yaml | 3 + .../yaml/yaml/models/modelWithInt32Map.yaml | 4 + .../yaml/yaml/models/modelWithInt64Map.yaml | 4 + .../models/modelWithMultipleProperties.yaml | 14 + .../yaml/yaml/models/modelWithObjectMap.yaml | 9 + .../yaml/models/modelWithPrimitiveArray.yaml | 5 + .../yaml/models/modelWithStringProperty.yaml | 3 + .../yaml/models/modelWithXmlAttributes.yaml | 6 + .../fixtures/yaml/yaml/models/models.yaml | 2 + .../yaml/yaml/models/multipleModels.yaml | 3 + .../properties/propertyWithBooleanArray.yaml | 3 + .../properties/propertyWithByteArray.yaml | 4 + .../properties/propertyWithComplexArray.yaml | 3 + .../properties/propertyWithDateTimeArray.yaml | 4 + .../properties/propertyWithInt32Array.yaml | 4 + .../properties/propertyWithInt64Array.yaml | 4 + .../models/properties/propertyWithRef.yaml | 3 + .../properties/propertyWithStringArray.yaml | 3 + .../properties/simpleBooleanProperty.yaml | 3 + .../models/properties/simpleByteProperty.yaml | 2 + .../properties/simpleDateTimeProperty.yaml | 2 + .../properties/simpleInt32Property.yaml | 2 + .../properties/simpleInt64Property.yaml | 2 + .../properties/simpleStringProperty.yaml | 1 + .../yaml/yaml/resources/cascadingSchemes.yaml | 23 + .../yaml/yaml/resources/commonParameters.yaml | 23 + .../yaml/resources/multipleMimeTypes.yaml | 32 + .../operations/operationWithTags.yaml | 14 + .../stringPathAndBoolQueryParamResource.yaml | 12 + .../operations/stringPathParamResource.yaml | 12 + .../parameters/bodyComplexArrayParameter.yaml | 8 + .../parameters/bodyComplexParameter.yaml | 6 + .../parameters/bodyInt64Parameter.yaml | 7 + .../parameters/bodyStringArrayParameter.yaml | 7 + .../parameters/bodyStringParameter.yaml | 6 + .../parameters/formDataComplexParameter.yaml | 5 + .../parameters/formDataInt64Parameter.yaml | 6 + .../formDataStringArrayParameter.yaml | 7 + .../parameters/formDataStringParameter.yaml | 5 + .../parameters/headerInt64ArrayParameter.yaml | 9 + .../headerStringArrayParameter.yaml | 8 + .../parameters/headerStringParameter.yaml | 5 + .../parameters/pathInt64Parameter.yaml | 6 + .../parameters/pathStringArrayParameter.yaml | 8 + .../parameters/pathStringParameter.yaml | 5 + .../parameters/queryInt64ArrayParameter.yaml | 9 + .../parameters/queryStringParameter.yaml | 6 + .../parameters/queryWithComplexParameter.yaml | 6 + .../resources/resourceWithExamplePayload.yaml | 23 + .../resourceWithLinkedDefinitions.yaml | 23 + .../resourceWithLinkedDefinitions_part1.yaml | 7 + .../resources/resourceWithRelativeHost.yaml | 22 + .../yaml/resources/reusableParameters.yaml | 26 + .../yaml/yaml/resources/securityExample.yaml | 29 + .../resources/stringPathParamResource.yaml | 23 + .../yaml/yaml/resources/taggedResource.yaml | 29 + .../resources/vendorExtensionExamples.yaml | 27 + .../yaml/responses/complexArrayResponse.yaml | 4 + .../yaml/yaml/responses/dateTimeResponse.yaml | 4 + .../yaml/yaml/responses/int32Response.yaml | 4 + .../yaml/yaml/responses/int64Response.yaml | 4 + .../yaml/responses/multipleResponses.yaml | 8 + .../yaml/responses/stringArrayResponse.yaml | 4 + .../yaml/yaml/responses/stringResponse.yaml | 3 + .../responses/stringResponseWithHeader.yaml | 6 + .../yaml/yaml/responses/voidResponse.yaml | 1 + .../go-openapi/loads/fmts/fixture_test.go | 298 + .../github.com/go-openapi/loads/fmts/yaml.go | 30 + .../go-openapi/loads/fmts/yaml_test.go | 445 ++ .../go-openapi/loads/hack/build-drone.sh | 25 + .../github.com/go-openapi/loads/hack/coverage | 20 + .../github.com/go-openapi/loads/json_test.go | 318 ++ vendor/github.com/go-openapi/loads/spec.go | 264 + .../github.com/go-openapi/loads/spec_test.go | 643 +++ .../go-openapi/runtime/.editorconfig | 26 + .../runtime/.github/CONTRIBUTING.md | 117 + .../github.com/go-openapi/runtime/.gitignore | 5 + .../github.com/go-openapi/runtime/.travis.yml | 25 + .../go-openapi/runtime/CODE_OF_CONDUCT.md | 74 + vendor/github.com/go-openapi/runtime/LICENSE | 202 + .../github.com/go-openapi/runtime/README.md | 5 + .../go-openapi/runtime/authinfo_test.go | 33 + .../go-openapi/runtime/bytestream.go | 116 + .../go-openapi/runtime/bytestream_test.go | 140 + .../go-openapi/runtime/client/auth_info.go | 60 + .../runtime/client/auth_info_test.go | 69 + .../go-openapi/runtime/client/request.go | 282 + .../go-openapi/runtime/client/request_test.go | 287 + .../go-openapi/runtime/client/response.go | 44 + .../runtime/client/response_test.go | 40 + .../go-openapi/runtime/client/runtime.go | 330 ++ .../go-openapi/runtime/client/runtime_test.go | 721 +++ .../go-openapi/runtime/client_auth_info.go | 30 + .../go-openapi/runtime/client_operation.go | 42 + .../go-openapi/runtime/client_request.go | 59 + .../go-openapi/runtime/client_request_test.go | 68 + .../go-openapi/runtime/client_response.go | 63 + .../runtime/client_response_test.go | 60 + .../go-openapi/runtime/constants.go | 41 + .../github.com/go-openapi/runtime/discard.go | 9 + vendor/github.com/go-openapi/runtime/file.go | 27 + .../go-openapi/runtime/file_test.go | 14 + .../runtime/fixtures/bugs/264/swagger.yml | 21 + .../runtime/fixtures/certs/myCA.crt | 29 + .../runtime/fixtures/certs/myCA.key | 51 + .../runtime/fixtures/certs/mycert1.crt | 27 + .../runtime/fixtures/certs/mycert1.key | 51 + .../runtime/fixtures/certs/mycert1.req | 26 + .../runtime/fixtures/certs/myclient.crt | 29 + .../runtime/fixtures/certs/myclient.csr | 27 + .../runtime/fixtures/certs/myclient.key | 51 + .../runtime/fixtures/certs/myclient.p12 | Bin 0 -> 4021 bytes .../go-openapi/runtime/fixtures/certs/serial | 1 + .../go-openapi/runtime/flagext/byte_size.go | 38 + .../runtime/flagext/byte_size_test.go | 43 + .../go-openapi/runtime/hack/coverage | 20 + .../runtime/hack/gen-self-signed-certs.sh | 16 + .../github.com/go-openapi/runtime/headers.go | 45 + .../go-openapi/runtime/headers_test.go | 61 + .../go-openapi/runtime/interfaces.go | 103 + .../runtime/internal/testing/data.go | 811 +++ .../runtime/internal/testing/petstore/api.go | 159 + .../internal/testing/simplepetstore/api.go | 351 ++ .../testing/simplepetstore/api_test.go | 81 + vendor/github.com/go-openapi/runtime/json.go | 37 + .../go-openapi/runtime/json_test.go | 62 + .../runtime/middleware/body_test.go | 101 + .../go-openapi/runtime/middleware/context.go | 559 ++ .../runtime/middleware/context_test.go | 434 ++ .../runtime/middleware/denco/LICENSE | 19 + .../runtime/middleware/denco/README.md | 180 + .../runtime/middleware/denco/router.go | 452 ++ .../middleware/denco/router_bench_test.go | 178 + .../runtime/middleware/denco/router_test.go | 526 ++ .../runtime/middleware/denco/server.go | 106 + .../runtime/middleware/denco/server_test.go | 106 + .../runtime/middleware/denco/util.go | 12 + .../runtime/middleware/denco/util_test.go | 31 + .../go-openapi/runtime/middleware/doc.go | 62 + .../go-openapi/runtime/middleware/go18.go | 9 + .../runtime/middleware/header/header.go | 326 ++ .../runtime/middleware/negotiate.go | 98 + .../runtime/middleware/negotiate_test.go | 83 + .../runtime/middleware/not_implemented.go | 48 + .../runtime/middleware/operation.go | 30 + .../runtime/middleware/operation_test.go | 64 + .../runtime/middleware/parameter.go | 480 ++ .../runtime/middleware/parameter_test.go | 340 ++ .../go-openapi/runtime/middleware/pre_go18.go | 9 + .../go-openapi/runtime/middleware/redoc.go | 101 + .../runtime/middleware/redoc_test.go | 22 + .../go-openapi/runtime/middleware/request.go | 104 + .../runtime/middleware/request_test.go | 466 ++ .../runtime/middleware/route_param_test.go | 38 + .../go-openapi/runtime/middleware/router.go | 270 + .../runtime/middleware/router_test.go | 227 + .../go-openapi/runtime/middleware/security.go | 39 + .../runtime/middleware/security_test.go | 58 + .../go-openapi/runtime/middleware/spec.go | 47 + .../runtime/middleware/spec_test.go | 56 + .../middleware/string_conversion_test.go | 301 + .../runtime/middleware/untyped/api.go | 286 + .../runtime/middleware/untyped/api_test.go | 286 + .../middleware/untyped_request_test.go | 164 + .../runtime/middleware/validation.go | 122 + .../runtime/middleware/validation_test.go | 155 + .../github.com/go-openapi/runtime/request.go | 77 + .../go-openapi/runtime/request_test.go | 122 + .../runtime/security/apikey_auth_test.go | 94 + .../runtime/security/authenticator.go | 128 + .../go-openapi/runtime/security/authorizer.go | 27 + .../runtime/security/authorizer_test.go | 28 + .../runtime/security/basic_auth_test.go | 75 + .../runtime/security/bearer_auth_test.go | 143 + .../github.com/go-openapi/runtime/statuses.go | 90 + vendor/github.com/go-openapi/runtime/text.go | 111 + .../go-openapi/runtime/text_test.go | 176 + .../github.com/go-openapi/runtime/values.go | 19 + vendor/github.com/go-openapi/runtime/xml.go | 36 + .../github.com/go-openapi/runtime/xml_test.go | 53 + .../go-openapi/runtime/yamlpc/yaml.go | 44 + .../go-openapi/runtime/yamlpc/yaml_test.go | 62 + .../go-openapi/strfmt/.editorconfig | 26 + .../go-openapi/strfmt/.github/CONTRIBUTING.md | 117 + .../github.com/go-openapi/strfmt/.gitignore | 2 + .../github.com/go-openapi/strfmt/.travis.yml | 18 + .../go-openapi/strfmt/CODE_OF_CONDUCT.md | 74 + vendor/github.com/go-openapi/strfmt/LICENSE | 202 + vendor/github.com/go-openapi/strfmt/README.md | 5 + vendor/github.com/go-openapi/strfmt/bson.go | 124 + .../github.com/go-openapi/strfmt/bson_test.go | 53 + .../github.com/go-openapi/strfmt/conv/date.go | 18 + .../go-openapi/strfmt/conv/date_test.go | 15 + .../go-openapi/strfmt/conv/default.go | 290 + .../go-openapi/strfmt/conv/default_test.go | 122 + .../go-openapi/strfmt/conv/duration.go | 18 + .../go-openapi/strfmt/conv/duration_test.go | 14 + .../github.com/go-openapi/strfmt/conv/time.go | 18 + .../go-openapi/strfmt/conv/time_test.go | 15 + vendor/github.com/go-openapi/strfmt/date.go | 152 + .../github.com/go-openapi/strfmt/date_test.go | 83 + .../github.com/go-openapi/strfmt/default.go | 1697 ++++++ .../go-openapi/strfmt/default_test.go | 691 +++ vendor/github.com/go-openapi/strfmt/doc.go | 18 + .../github.com/go-openapi/strfmt/duration.go | 194 + .../go-openapi/strfmt/duration_test.go | 143 + vendor/github.com/go-openapi/strfmt/format.go | 298 + .../go-openapi/strfmt/format_test.go | 223 + .../go-openapi/strfmt/hack/coverage | 20 + vendor/github.com/go-openapi/strfmt/time.go | 188 + .../github.com/go-openapi/strfmt/time_test.go | 154 + .../validate/.github/CONTRIBUTING.md | 117 + .../github.com/go-openapi/validate/.gitignore | 4 + .../go-openapi/validate/.travis.yml | 22 + .../go-openapi/validate/CODE_OF_CONDUCT.md | 74 + vendor/github.com/go-openapi/validate/LICENSE | 202 + .../github.com/go-openapi/validate/README.md | 3 + .../go-openapi/validate/defaulter_test.go | 53 + .../validate/fixtures/bugs/123/swagger.yml | 197 + .../fixtures/bugs/18/headerItems.json | 27 + .../validate/fixtures/bugs/18/headers.json | 33 + .../validate/fixtures/bugs/18/paramItems.json | 36 + .../validate/fixtures/bugs/18/parameters.json | 30 + .../validate/fixtures/bugs/18/schema.json | 25 + .../validate/fixtures/bugs/52/swagger.json | 11 + .../validate/fixtures/bugs/53/noswagger.json | 14 + .../fixtures/bugs/6/empty-responses.json | 15 + .../fixtures/bugs/6/no-responses.json | 14 + .../fixtures/bugs/61/multiple-refs.json | 55 + .../bugs/61/unresolved-ref-for-name.json | 47 + .../validate/fixtures/bugs/62/swagger.json | 14 + .../validate/fixtures/bugs/63/swagger.json | 47 + .../validate/fixtures/defaulting/schema.json | 101 + .../jsonschema_suite/additionalItems.json | 82 + .../additionalProperties.json | 88 + .../fixtures/jsonschema_suite/allOf.json | 112 + .../fixtures/jsonschema_suite/anyOf.json | 68 + .../fixtures/jsonschema_suite/default.json | 49 + .../jsonschema_suite/definitions.json | 32 + .../jsonschema_suite/dependencies.json | 113 + .../fixtures/jsonschema_suite/enum.json | 72 + .../fixtures/jsonschema_suite/format.json | 143 + .../fixtures/jsonschema_suite/items.json | 61 + .../fixtures/jsonschema_suite/maxItems.json | 28 + .../fixtures/jsonschema_suite/maxLength.json | 33 + .../jsonschema_suite/maxProperties.json | 28 + .../fixtures/jsonschema_suite/maximum.json | 42 + .../fixtures/jsonschema_suite/minItems.json | 28 + .../fixtures/jsonschema_suite/minLength.json | 33 + .../jsonschema_suite/minProperties.json | 28 + .../fixtures/jsonschema_suite/minimum.json | 42 + .../fixtures/jsonschema_suite/multipleOf.json | 60 + .../fixtures/jsonschema_suite/not.json | 96 + .../fixtures/jsonschema_suite/oneOf.json | 68 + .../jsonschema_suite/optional/bignum.json | 107 + .../optional/ecmascript-regex.json | 13 + .../jsonschema_suite/optional/format.json | 148 + .../optional/zeroTerminatedFloats.json | 15 + .../fixtures/jsonschema_suite/pattern.json | 34 + .../jsonschema_suite/patternProperties.json | 110 + .../fixtures/jsonschema_suite/properties.json | 92 + .../fixtures/jsonschema_suite/ref.json | 212 + .../fixtures/jsonschema_suite/refRemote.json | 74 + .../remotes/folder/folderInteger.json | 3 + .../jsonschema_suite/remotes/integer.json | 3 + .../jsonschema_suite/remotes/subSchemas.json | 8 + .../fixtures/jsonschema_suite/required.json | 44 + .../fixtures/jsonschema_suite/type.json | 345 ++ .../jsonschema_suite/uniqueItems.json | 79 + .../fixtures/local_expansion/item.yaml | 12 + .../fixtures/local_expansion/spec.yaml | 30 + .../fixtures/recursive_expansion/item.yaml | 15 + .../fixtures/recursive_expansion/spec.yaml | 38 + .../validate/fixtures/schemas/int-enum.json | 39 + .../validation/direct-circular-ancestor.json | 138 + .../fixtures/validation/duplicateprops.json | 137 + .../validation/empty-path-param-name.json | 119 + .../indirect-circular-ancestor.json | 132 + .../invalid-default-value-header-items.json | 117 + .../invalid-default-value-header.json | 114 + ...invalid-default-value-parameter-items.json | 119 + .../invalid-default-value-parameter-ref.json | 119 + .../invalid-default-value-parameter.json | 117 + ...ult-value-schema-additionalProperties.json | 111 + .../invalid-default-value-schema-allOf.json | 118 + .../invalid-default-value-schema-items.json | 114 + ...efault-value-schema-patternProperties.json | 113 + .../invalid-default-value-schema-ref.json | 108 + .../invalid-default-value-schema.json | 107 + .../invalid-example-response-ref.json | 119 + .../validation/invalid-example-response.json | 114 + .../invalid-formdata-body-params.json | 128 + .../fixtures/validation/invalid-ref.json | 107 + .../validation/invalid-referenced.yml | 31 + .../validation/nestedduplicateprops.json | 137 + .../recursive-circular-ancestor.json | 130 + .../valid-default-value-header-items.json | 117 + .../valid-default-value-header.json | 114 + .../valid-default-value-parameter-items.json | 119 + .../valid-default-value-parameter-ref.json | 119 + .../valid-default-value-parameter.json | 116 + ...ult-value-schema-additionalProperties.json | 111 + .../valid-default-value-schema-allOf.json | 118 + .../valid-default-value-schema-items.json | 107 + ...efault-value-schema-patternProperties.json | 114 + .../valid-default-value-schema-ref.json | 107 + .../valid-default-value-schema.json | 115 + .../valid-example-response-ref.json | 120 + .../validation/valid-example-response.json | 115 + .../fixtures/validation/valid-ref.json | 107 + .../fixtures/validation/valid-referenced.yml | 39 + .../github.com/go-openapi/validate/formats.go | 72 + .../validate/items_validator_test.go | 517 ++ .../go-openapi/validate/object_validator.go | 171 + .../validate/object_validator_test.go | 34 + .../validate/parameter_validator_test.go | 230 + .../github.com/go-openapi/validate/result.go | 89 + .../github.com/go-openapi/validate/schema.go | 219 + .../go-openapi/validate/schema_props.go | 197 + .../go-openapi/validate/slice_validator.go | 106 + vendor/github.com/go-openapi/validate/spec.go | 826 +++ .../go-openapi/validate/spec_test.go | 607 +++ vendor/github.com/go-openapi/validate/type.go | 155 + .../go-openapi/validate/type_test.go | 211 + .../go-openapi/validate/update-fixtures.sh | 15 + .../go-openapi/validate/validator.go | 592 ++ .../go-openapi/validate/validator_test.go | 40 + .../github.com/go-openapi/validate/values.go | 222 + .../go-openapi/validate/values_test.go | 157 + .../mitchellh/mapstructure/.travis.yml | 7 + .../github.com/mitchellh/mapstructure/LICENSE | 21 + .../mitchellh/mapstructure/README.md | 46 + .../mitchellh/mapstructure/decode_hooks.go | 152 + .../mapstructure/decode_hooks_test.go | 229 + .../mitchellh/mapstructure/error.go | 50 + .../mitchellh/mapstructure/mapstructure.go | 834 +++ .../mapstructure_benchmark_test.go | 279 + .../mapstructure/mapstructure_bugs_test.go | 260 + .../mapstructure_examples_test.go | 203 + .../mapstructure/mapstructure_test.go | 1193 ++++ vendor/gopkg.in/mgo.v2/.travis.yml | 45 + vendor/gopkg.in/mgo.v2/LICENSE | 25 + vendor/gopkg.in/mgo.v2/Makefile | 5 + vendor/gopkg.in/mgo.v2/README.md | 4 + vendor/gopkg.in/mgo.v2/auth.go | 467 ++ vendor/gopkg.in/mgo.v2/auth_test.go | 1180 ++++ vendor/gopkg.in/mgo.v2/bson/LICENSE | 25 + vendor/gopkg.in/mgo.v2/bson/bson.go | 738 +++ vendor/gopkg.in/mgo.v2/bson/bson_test.go | 1832 +++++++ vendor/gopkg.in/mgo.v2/bson/decimal.go | 310 ++ vendor/gopkg.in/mgo.v2/bson/decimal_test.go | 4109 ++++++++++++++ vendor/gopkg.in/mgo.v2/bson/decode.go | 849 +++ vendor/gopkg.in/mgo.v2/bson/encode.go | 514 ++ vendor/gopkg.in/mgo.v2/bson/json.go | 380 ++ vendor/gopkg.in/mgo.v2/bson/json_test.go | 184 + .../gopkg.in/mgo.v2/bson/specdata/update.sh | 27 + vendor/gopkg.in/mgo.v2/bson/specdata_test.go | 241 + vendor/gopkg.in/mgo.v2/bulk.go | 351 ++ vendor/gopkg.in/mgo.v2/bulk_test.go | 504 ++ vendor/gopkg.in/mgo.v2/cluster.go | 682 +++ vendor/gopkg.in/mgo.v2/cluster_test.go | 2090 +++++++ vendor/gopkg.in/mgo.v2/dbtest/dbserver.go | 196 + .../gopkg.in/mgo.v2/dbtest/dbserver_test.go | 108 + vendor/gopkg.in/mgo.v2/dbtest/export_test.go | 12 + vendor/gopkg.in/mgo.v2/doc.go | 31 + vendor/gopkg.in/mgo.v2/export_test.go | 33 + vendor/gopkg.in/mgo.v2/gridfs.go | 761 +++ vendor/gopkg.in/mgo.v2/gridfs_test.go | 708 +++ .../gopkg.in/mgo.v2/harness/certs/client.crt | 20 + .../gopkg.in/mgo.v2/harness/certs/client.key | 27 + .../gopkg.in/mgo.v2/harness/certs/client.pem | 57 + .../gopkg.in/mgo.v2/harness/certs/client.req | 17 + .../gopkg.in/mgo.v2/harness/certs/server.crt | 22 + .../gopkg.in/mgo.v2/harness/certs/server.key | 28 + .../gopkg.in/mgo.v2/harness/certs/server.pem | 50 + vendor/gopkg.in/mgo.v2/harness/daemons/.env | 57 + .../mgo.v2/harness/daemons/cfg1/db/.empty | 0 .../daemons/cfg1/db/journal/tempLatencyTest | Bin 0 -> 204800 bytes .../harness/daemons/cfg1/db/mongod.lock | 0 .../mgo.v2/harness/daemons/cfg1/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/cfg1/run | 8 + .../mgo.v2/harness/daemons/cfg2/db/.empty | 0 .../mgo.v2/harness/daemons/cfg2/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/cfg2/run | 8 + .../mgo.v2/harness/daemons/cfg3/db/.empty | 0 .../mgo.v2/harness/daemons/cfg3/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/cfg3/run | 9 + .../mgo.v2/harness/daemons/db1/db/.empty | 0 .../mgo.v2/harness/daemons/db1/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/db1/run | 15 + .../mgo.v2/harness/daemons/db2/db/.empty | 0 .../mgo.v2/harness/daemons/db2/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/db2/run | 8 + .../mgo.v2/harness/daemons/db3/db/.empty | 0 .../mgo.v2/harness/daemons/db3/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/db3/run | 12 + .../mgo.v2/harness/daemons/rs1a/db/.empty | 0 .../mgo.v2/harness/daemons/rs1a/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs1a/run | 8 + .../mgo.v2/harness/daemons/rs1b/db/.empty | 0 .../mgo.v2/harness/daemons/rs1b/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs1b/run | 8 + .../mgo.v2/harness/daemons/rs1c/db/.empty | 0 .../mgo.v2/harness/daemons/rs1c/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs1c/run | 8 + .../mgo.v2/harness/daemons/rs2a/db/.empty | 0 .../mgo.v2/harness/daemons/rs2a/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs2a/run | 8 + .../mgo.v2/harness/daemons/rs2b/db/.empty | 0 .../mgo.v2/harness/daemons/rs2b/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs2b/run | 8 + .../mgo.v2/harness/daemons/rs2c/db/.empty | 0 .../mgo.v2/harness/daemons/rs2c/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs2c/run | 8 + .../mgo.v2/harness/daemons/rs3a/db/.empty | 0 .../mgo.v2/harness/daemons/rs3a/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs3a/run | 9 + .../mgo.v2/harness/daemons/rs3b/db/.empty | 0 .../mgo.v2/harness/daemons/rs3b/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs3b/run | 9 + .../mgo.v2/harness/daemons/rs3c/db/.empty | 0 .../mgo.v2/harness/daemons/rs3c/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs3c/run | 9 + .../mgo.v2/harness/daemons/rs4a/db/.empty | 0 .../mgo.v2/harness/daemons/rs4a/log/run | 3 + .../gopkg.in/mgo.v2/harness/daemons/rs4a/run | 8 + .../mgo.v2/harness/daemons/s1/log/run | 3 + vendor/gopkg.in/mgo.v2/harness/daemons/s1/run | 7 + .../mgo.v2/harness/daemons/s2/log/run | 3 + vendor/gopkg.in/mgo.v2/harness/daemons/s2/run | 7 + .../mgo.v2/harness/daemons/s3/log/run | 3 + vendor/gopkg.in/mgo.v2/harness/daemons/s3/run | 8 + .../mgo.v2/harness/mongojs/dropall.js | 66 + .../gopkg.in/mgo.v2/harness/mongojs/init.js | 132 + .../gopkg.in/mgo.v2/harness/mongojs/wait.js | 67 + vendor/gopkg.in/mgo.v2/harness/setup.sh | 96 + vendor/gopkg.in/mgo.v2/internal/json/LICENSE | 27 + .../mgo.v2/internal/json/bench_test.go | 223 + .../gopkg.in/mgo.v2/internal/json/decode.go | 1685 ++++++ .../mgo.v2/internal/json/decode_test.go | 1512 ++++++ .../gopkg.in/mgo.v2/internal/json/encode.go | 1256 +++++ .../mgo.v2/internal/json/encode_test.go | 613 +++ .../mgo.v2/internal/json/example_test.go | 252 + .../mgo.v2/internal/json/extension.go | 95 + .../mgo.v2/internal/json/extension_test.go | 218 + vendor/gopkg.in/mgo.v2/internal/json/fold.go | 143 + .../mgo.v2/internal/json/fold_test.go | 116 + .../gopkg.in/mgo.v2/internal/json/indent.go | 141 + .../mgo.v2/internal/json/number_test.go | 133 + .../gopkg.in/mgo.v2/internal/json/scanner.go | 697 +++ .../mgo.v2/internal/json/scanner_test.go | 316 ++ .../gopkg.in/mgo.v2/internal/json/stream.go | 510 ++ .../mgo.v2/internal/json/stream_test.go | 418 ++ .../mgo.v2/internal/json/tagkey_test.go | 115 + vendor/gopkg.in/mgo.v2/internal/json/tags.go | 44 + .../mgo.v2/internal/json/tags_test.go | 28 + .../internal/json/testdata/code.json.gz | Bin 0 -> 120432 bytes vendor/gopkg.in/mgo.v2/internal/sasl/sasl.c | 77 + vendor/gopkg.in/mgo.v2/internal/sasl/sasl.go | 138 + .../mgo.v2/internal/sasl/sasl_windows.c | 122 + .../mgo.v2/internal/sasl/sasl_windows.go | 142 + .../mgo.v2/internal/sasl/sasl_windows.h | 7 + .../mgo.v2/internal/sasl/sspi_windows.c | 96 + .../mgo.v2/internal/sasl/sspi_windows.h | 70 + .../gopkg.in/mgo.v2/internal/scram/scram.go | 266 + .../mgo.v2/internal/scram/scram_test.go | 67 + vendor/gopkg.in/mgo.v2/log.go | 133 + vendor/gopkg.in/mgo.v2/queue.go | 91 + vendor/gopkg.in/mgo.v2/queue_test.go | 101 + vendor/gopkg.in/mgo.v2/raceoff.go | 5 + vendor/gopkg.in/mgo.v2/raceon.go | 5 + vendor/gopkg.in/mgo.v2/saslimpl.go | 11 + vendor/gopkg.in/mgo.v2/saslstub.go | 11 + vendor/gopkg.in/mgo.v2/server.go | 463 ++ vendor/gopkg.in/mgo.v2/session.go | 4825 +++++++++++++++++ vendor/gopkg.in/mgo.v2/session_test.go | 4236 +++++++++++++++ vendor/gopkg.in/mgo.v2/socket.go | 707 +++ vendor/gopkg.in/mgo.v2/stats.go | 147 + vendor/gopkg.in/mgo.v2/suite_test.go | 262 + vendor/gopkg.in/mgo.v2/syscall_test.go | 15 + .../gopkg.in/mgo.v2/syscall_windows_test.go | 11 + vendor/gopkg.in/mgo.v2/txn/chaos.go | 68 + vendor/gopkg.in/mgo.v2/txn/debug.go | 109 + vendor/gopkg.in/mgo.v2/txn/dockey_test.go | 205 + vendor/gopkg.in/mgo.v2/txn/flusher.go | 985 ++++ vendor/gopkg.in/mgo.v2/txn/output.txt | 0 vendor/gopkg.in/mgo.v2/txn/sim_test.go | 388 ++ vendor/gopkg.in/mgo.v2/txn/tarjan.go | 94 + vendor/gopkg.in/mgo.v2/txn/tarjan_test.go | 44 + vendor/gopkg.in/mgo.v2/txn/txn.go | 611 +++ vendor/gopkg.in/mgo.v2/txn/txn_test.go | 778 +++ 717 files changed, 95024 insertions(+), 5 deletions(-) create mode 100644 vendor/github.com/asaskevich/govalidator/.travis.yml create mode 100644 vendor/github.com/asaskevich/govalidator/LICENSE create mode 100644 vendor/github.com/asaskevich/govalidator/README.md create mode 100644 vendor/github.com/asaskevich/govalidator/arrays.go create mode 100644 vendor/github.com/asaskevich/govalidator/arrays_test.go create mode 100644 vendor/github.com/asaskevich/govalidator/converter.go create mode 100644 vendor/github.com/asaskevich/govalidator/converter_test.go create mode 100644 vendor/github.com/asaskevich/govalidator/error.go create mode 100644 vendor/github.com/asaskevich/govalidator/error_test.go create mode 100644 vendor/github.com/asaskevich/govalidator/numerics.go create mode 100644 vendor/github.com/asaskevich/govalidator/numerics_test.go create mode 100644 vendor/github.com/asaskevich/govalidator/patterns.go create mode 100644 vendor/github.com/asaskevich/govalidator/types.go create mode 100644 vendor/github.com/asaskevich/govalidator/utils.go create mode 100644 vendor/github.com/asaskevich/govalidator/utils_test.go create mode 100644 vendor/github.com/asaskevich/govalidator/validator.go create mode 100644 vendor/github.com/asaskevich/govalidator/validator_test.go create mode 100644 vendor/github.com/asaskevich/govalidator/wercker.yml create mode 100644 vendor/github.com/go-openapi/analysis/.github/CONTRIBUTING.md create mode 100644 vendor/github.com/go-openapi/analysis/.gitignore create mode 100644 vendor/github.com/go-openapi/analysis/.travis.yml create mode 100644 vendor/github.com/go-openapi/analysis/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/go-openapi/analysis/LICENSE create mode 100644 vendor/github.com/go-openapi/analysis/README.md create mode 100644 vendor/github.com/go-openapi/analysis/analyzer.go create mode 100644 vendor/github.com/go-openapi/analysis/analyzer_test.go create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/allOf.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/bar-crud.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/definitions.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/empty-paths.json create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/external/definitions.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/external/definitions2.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/external/errors.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/external/nestedParams.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/external/nestedResponses.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/external/parameters.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/external/pathItem.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/external/responses.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/external_definitions.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/flatten.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/foo-crud.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/inline_schemas.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/nested_inline_schemas.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/no-paths.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/patterns.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/references.yml create mode 100644 vendor/github.com/go-openapi/analysis/fixtures/widget-crud.yml create mode 100644 vendor/github.com/go-openapi/analysis/flatten.go create mode 100644 vendor/github.com/go-openapi/analysis/flatten_test.go create mode 100644 vendor/github.com/go-openapi/analysis/mixin.go create mode 100644 vendor/github.com/go-openapi/analysis/mixin_test.go create mode 100644 vendor/github.com/go-openapi/analysis/schema.go create mode 100644 vendor/github.com/go-openapi/analysis/schema_test.go create mode 100644 vendor/github.com/go-openapi/errors/.github/CONTRIBUTING.md create mode 100644 vendor/github.com/go-openapi/errors/.gitignore create mode 100644 vendor/github.com/go-openapi/errors/.travis.yml create mode 100644 vendor/github.com/go-openapi/errors/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/go-openapi/errors/LICENSE create mode 100644 vendor/github.com/go-openapi/errors/README.md create mode 100644 vendor/github.com/go-openapi/errors/api.go create mode 100644 vendor/github.com/go-openapi/errors/api_test.go create mode 100644 vendor/github.com/go-openapi/errors/auth.go create mode 100644 vendor/github.com/go-openapi/errors/auth_test.go create mode 100644 vendor/github.com/go-openapi/errors/headers.go create mode 100644 vendor/github.com/go-openapi/errors/middleware.go create mode 100644 vendor/github.com/go-openapi/errors/middleware_test.go create mode 100644 vendor/github.com/go-openapi/errors/parsing.go create mode 100644 vendor/github.com/go-openapi/errors/parsing_test.go create mode 100644 vendor/github.com/go-openapi/errors/schema.go create mode 100644 vendor/github.com/go-openapi/errors/schema_test.go create mode 100644 vendor/github.com/go-openapi/loads/.drone.yml create mode 100644 vendor/github.com/go-openapi/loads/.editorconfig create mode 100644 vendor/github.com/go-openapi/loads/.github/CONTRIBUTING.md create mode 100644 vendor/github.com/go-openapi/loads/.gitignore create mode 100644 vendor/github.com/go-openapi/loads/.travis.yml create mode 100644 vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/go-openapi/loads/LICENSE create mode 100644 vendor/github.com/go-openapi/loads/README.md create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithArrayRef.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithComposition.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithDateTimeMap.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithExamples.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithInt32Map.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithInt64Map.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithMultipleProperties.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithObjectMap.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithPrimitiveArray.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithStringProperty.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithXmlAttributes.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/models.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/multipleModels.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithBooleanArray.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithByteArray.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithComplexArray.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithDateTimeArray.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithInt32Array.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithInt64Array.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithRef.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithStringArray.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleBooleanProperty.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleByteProperty.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleDateTimeProperty.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleInt32Property.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleInt64Property.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleStringProperty.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/cascadingSchemes.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/commonParameters.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/multipleMimeTypes.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/operationWithTags.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/stringPathAndBoolQueryParamResource.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/stringPathParamResource.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyComplexArrayParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyComplexParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyInt64Parameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyStringArrayParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyStringParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataComplexParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataInt64Parameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataStringArrayParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataStringParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerInt64ArrayParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerStringArrayParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerStringParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathInt64Parameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathStringArrayParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathStringParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryInt64ArrayParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryStringParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryWithComplexParameter.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithExamplePayload.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithLinkedDefinitions.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithLinkedDefinitions_part1.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithRelativeHost.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/reusableParameters.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/securityExample.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/stringPathParamResource.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/taggedResource.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/resources/vendorExtensionExamples.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/responses/complexArrayResponse.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/responses/dateTimeResponse.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/responses/int32Response.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/responses/int64Response.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/responses/multipleResponses.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/responses/stringArrayResponse.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/responses/stringResponse.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/responses/stringResponseWithHeader.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/json/responses/voidResponse.json create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/.gitkeep create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithArrayRef.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithComposition.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithDateTimeMap.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithExamples.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithInt32Map.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithInt64Map.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithMultipleProperties.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithObjectMap.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithPrimitiveArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithStringProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithXmlAttributes.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/models.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/multipleModels.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithBooleanArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithByteArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithComplexArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithDateTimeArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithInt32Array.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithInt64Array.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithRef.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithStringArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleBooleanProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleByteProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleDateTimeProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleInt32Property.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleInt64Property.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleStringProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/cascadingSchemes.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/commonParameters.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/multipleMimeTypes.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/operationWithTags.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/stringPathAndBoolQueryParamResource.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/stringPathParamResource.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyComplexArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyComplexParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyInt64Parameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyStringArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataComplexParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataInt64Parameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataStringArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerInt64ArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerStringArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathInt64Parameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathStringArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryInt64ArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryWithComplexParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithExamplePayload.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithLinkedDefinitions.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithLinkedDefinitions_part1.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithRelativeHost.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/reusableParameters.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/securityExample.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/stringPathParamResource.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/taggedResource.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/resources/vendorExtensionExamples.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/responses/complexArrayResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/responses/dateTimeResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/responses/int32Response.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/responses/int64Response.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/responses/multipleResponses.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringArrayResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringResponseWithHeader.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/responses/voidResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/1/2/3/4/swagger.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/shared/definitions/page.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/shared/something.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/.gitkeep create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithArrayRef.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithComposition.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithDateTimeMap.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithExamples.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithInt32Map.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithInt64Map.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithMultipleProperties.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithObjectMap.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithPrimitiveArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithStringProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithXmlAttributes.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/models.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/multipleModels.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithBooleanArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithByteArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithComplexArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithDateTimeArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithInt32Array.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithInt64Array.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithRef.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithStringArray.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleBooleanProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleByteProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleDateTimeProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleInt32Property.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleInt64Property.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleStringProperty.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/cascadingSchemes.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/commonParameters.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/multipleMimeTypes.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/operationWithTags.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/stringPathAndBoolQueryParamResource.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/stringPathParamResource.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyComplexArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyComplexParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyInt64Parameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyStringArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataComplexParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataInt64Parameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataStringArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerInt64ArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerStringArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathInt64Parameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathStringArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryInt64ArrayParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryStringParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryWithComplexParameter.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithExamplePayload.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithLinkedDefinitions.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithLinkedDefinitions_part1.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithRelativeHost.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/reusableParameters.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/securityExample.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/stringPathParamResource.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/taggedResource.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/vendorExtensionExamples.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/complexArrayResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/dateTimeResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/int32Response.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/int64Response.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/multipleResponses.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringArrayResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringResponseWithHeader.yaml create mode 100644 vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/voidResponse.yaml create mode 100644 vendor/github.com/go-openapi/loads/fmts/fixture_test.go create mode 100644 vendor/github.com/go-openapi/loads/fmts/yaml.go create mode 100644 vendor/github.com/go-openapi/loads/fmts/yaml_test.go create mode 100755 vendor/github.com/go-openapi/loads/hack/build-drone.sh create mode 100755 vendor/github.com/go-openapi/loads/hack/coverage create mode 100644 vendor/github.com/go-openapi/loads/json_test.go create mode 100644 vendor/github.com/go-openapi/loads/spec.go create mode 100644 vendor/github.com/go-openapi/loads/spec_test.go create mode 100644 vendor/github.com/go-openapi/runtime/.editorconfig create mode 100644 vendor/github.com/go-openapi/runtime/.github/CONTRIBUTING.md create mode 100644 vendor/github.com/go-openapi/runtime/.gitignore create mode 100644 vendor/github.com/go-openapi/runtime/.travis.yml create mode 100644 vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/go-openapi/runtime/LICENSE create mode 100644 vendor/github.com/go-openapi/runtime/README.md create mode 100644 vendor/github.com/go-openapi/runtime/authinfo_test.go create mode 100644 vendor/github.com/go-openapi/runtime/bytestream.go create mode 100644 vendor/github.com/go-openapi/runtime/bytestream_test.go create mode 100644 vendor/github.com/go-openapi/runtime/client/auth_info.go create mode 100644 vendor/github.com/go-openapi/runtime/client/auth_info_test.go create mode 100644 vendor/github.com/go-openapi/runtime/client/request.go create mode 100644 vendor/github.com/go-openapi/runtime/client/request_test.go create mode 100644 vendor/github.com/go-openapi/runtime/client/response.go create mode 100644 vendor/github.com/go-openapi/runtime/client/response_test.go create mode 100644 vendor/github.com/go-openapi/runtime/client/runtime.go create mode 100644 vendor/github.com/go-openapi/runtime/client/runtime_test.go create mode 100644 vendor/github.com/go-openapi/runtime/client_auth_info.go create mode 100644 vendor/github.com/go-openapi/runtime/client_operation.go create mode 100644 vendor/github.com/go-openapi/runtime/client_request.go create mode 100644 vendor/github.com/go-openapi/runtime/client_request_test.go create mode 100644 vendor/github.com/go-openapi/runtime/client_response.go create mode 100644 vendor/github.com/go-openapi/runtime/client_response_test.go create mode 100644 vendor/github.com/go-openapi/runtime/constants.go create mode 100644 vendor/github.com/go-openapi/runtime/discard.go create mode 100644 vendor/github.com/go-openapi/runtime/file.go create mode 100644 vendor/github.com/go-openapi/runtime/file_test.go create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/bugs/264/swagger.yml create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.crt create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.key create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.crt create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.key create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.req create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.crt create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.csr create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.key create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.p12 create mode 100644 vendor/github.com/go-openapi/runtime/fixtures/certs/serial create mode 100644 vendor/github.com/go-openapi/runtime/flagext/byte_size.go create mode 100644 vendor/github.com/go-openapi/runtime/flagext/byte_size_test.go create mode 100755 vendor/github.com/go-openapi/runtime/hack/coverage create mode 100755 vendor/github.com/go-openapi/runtime/hack/gen-self-signed-certs.sh create mode 100644 vendor/github.com/go-openapi/runtime/headers.go create mode 100644 vendor/github.com/go-openapi/runtime/headers_test.go create mode 100644 vendor/github.com/go-openapi/runtime/interfaces.go create mode 100644 vendor/github.com/go-openapi/runtime/internal/testing/data.go create mode 100644 vendor/github.com/go-openapi/runtime/internal/testing/petstore/api.go create mode 100644 vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api.go create mode 100644 vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api_test.go create mode 100644 vendor/github.com/go-openapi/runtime/json.go create mode 100644 vendor/github.com/go-openapi/runtime/json_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/body_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/context.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/context_test.go create mode 100755 vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE create mode 100755 vendor/github.com/go-openapi/runtime/middleware/denco/README.md create mode 100755 vendor/github.com/go-openapi/runtime/middleware/denco/router.go create mode 100755 vendor/github.com/go-openapi/runtime/middleware/denco/router_bench_test.go create mode 100755 vendor/github.com/go-openapi/runtime/middleware/denco/router_test.go create mode 100755 vendor/github.com/go-openapi/runtime/middleware/denco/server.go create mode 100755 vendor/github.com/go-openapi/runtime/middleware/denco/server_test.go create mode 100755 vendor/github.com/go-openapi/runtime/middleware/denco/util.go create mode 100755 vendor/github.com/go-openapi/runtime/middleware/denco/util_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/doc.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/go18.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/header/header.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/negotiate.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/negotiate_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/not_implemented.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/operation.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/operation_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/parameter.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/parameter_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/pre_go18.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/redoc.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/redoc_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/request.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/request_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/route_param_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/router.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/router_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/security.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/security_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/spec.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/spec_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/string_conversion_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/untyped/api.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/untyped/api_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/untyped_request_test.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/validation.go create mode 100644 vendor/github.com/go-openapi/runtime/middleware/validation_test.go create mode 100644 vendor/github.com/go-openapi/runtime/request.go create mode 100644 vendor/github.com/go-openapi/runtime/request_test.go create mode 100644 vendor/github.com/go-openapi/runtime/security/apikey_auth_test.go create mode 100644 vendor/github.com/go-openapi/runtime/security/authenticator.go create mode 100644 vendor/github.com/go-openapi/runtime/security/authorizer.go create mode 100644 vendor/github.com/go-openapi/runtime/security/authorizer_test.go create mode 100644 vendor/github.com/go-openapi/runtime/security/basic_auth_test.go create mode 100644 vendor/github.com/go-openapi/runtime/security/bearer_auth_test.go create mode 100644 vendor/github.com/go-openapi/runtime/statuses.go create mode 100644 vendor/github.com/go-openapi/runtime/text.go create mode 100644 vendor/github.com/go-openapi/runtime/text_test.go create mode 100644 vendor/github.com/go-openapi/runtime/values.go create mode 100644 vendor/github.com/go-openapi/runtime/xml.go create mode 100644 vendor/github.com/go-openapi/runtime/xml_test.go create mode 100644 vendor/github.com/go-openapi/runtime/yamlpc/yaml.go create mode 100644 vendor/github.com/go-openapi/runtime/yamlpc/yaml_test.go create mode 100644 vendor/github.com/go-openapi/strfmt/.editorconfig create mode 100644 vendor/github.com/go-openapi/strfmt/.github/CONTRIBUTING.md create mode 100644 vendor/github.com/go-openapi/strfmt/.gitignore create mode 100644 vendor/github.com/go-openapi/strfmt/.travis.yml create mode 100644 vendor/github.com/go-openapi/strfmt/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/go-openapi/strfmt/LICENSE create mode 100644 vendor/github.com/go-openapi/strfmt/README.md create mode 100644 vendor/github.com/go-openapi/strfmt/bson.go create mode 100644 vendor/github.com/go-openapi/strfmt/bson_test.go create mode 100644 vendor/github.com/go-openapi/strfmt/conv/date.go create mode 100644 vendor/github.com/go-openapi/strfmt/conv/date_test.go create mode 100644 vendor/github.com/go-openapi/strfmt/conv/default.go create mode 100644 vendor/github.com/go-openapi/strfmt/conv/default_test.go create mode 100644 vendor/github.com/go-openapi/strfmt/conv/duration.go create mode 100644 vendor/github.com/go-openapi/strfmt/conv/duration_test.go create mode 100644 vendor/github.com/go-openapi/strfmt/conv/time.go create mode 100644 vendor/github.com/go-openapi/strfmt/conv/time_test.go create mode 100644 vendor/github.com/go-openapi/strfmt/date.go create mode 100644 vendor/github.com/go-openapi/strfmt/date_test.go create mode 100644 vendor/github.com/go-openapi/strfmt/default.go create mode 100644 vendor/github.com/go-openapi/strfmt/default_test.go create mode 100644 vendor/github.com/go-openapi/strfmt/doc.go create mode 100644 vendor/github.com/go-openapi/strfmt/duration.go create mode 100644 vendor/github.com/go-openapi/strfmt/duration_test.go create mode 100644 vendor/github.com/go-openapi/strfmt/format.go create mode 100644 vendor/github.com/go-openapi/strfmt/format_test.go create mode 100755 vendor/github.com/go-openapi/strfmt/hack/coverage create mode 100644 vendor/github.com/go-openapi/strfmt/time.go create mode 100644 vendor/github.com/go-openapi/strfmt/time_test.go create mode 100644 vendor/github.com/go-openapi/validate/.github/CONTRIBUTING.md create mode 100644 vendor/github.com/go-openapi/validate/.gitignore create mode 100644 vendor/github.com/go-openapi/validate/.travis.yml create mode 100644 vendor/github.com/go-openapi/validate/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/go-openapi/validate/LICENSE create mode 100644 vendor/github.com/go-openapi/validate/README.md create mode 100644 vendor/github.com/go-openapi/validate/defaulter_test.go create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/123/swagger.yml create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/18/headerItems.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/18/headers.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/18/paramItems.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/18/parameters.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/18/schema.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/52/swagger.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/53/noswagger.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/6/empty-responses.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/6/no-responses.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/61/multiple-refs.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/61/unresolved-ref-for-name.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/62/swagger.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/bugs/63/swagger.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/defaulting/schema.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/additionalItems.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/additionalProperties.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/allOf.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/anyOf.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/default.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/definitions.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/dependencies.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/enum.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/format.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/items.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/maxItems.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/maxLength.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/maxProperties.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/maximum.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/minItems.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/minLength.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/minProperties.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/minimum.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/multipleOf.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/not.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/oneOf.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/optional/bignum.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/optional/ecmascript-regex.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/optional/format.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/optional/zeroTerminatedFloats.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/pattern.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/patternProperties.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/properties.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/ref.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/refRemote.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/remotes/folder/folderInteger.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/remotes/integer.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/remotes/subSchemas.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/required.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/type.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/jsonschema_suite/uniqueItems.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/local_expansion/item.yaml create mode 100644 vendor/github.com/go-openapi/validate/fixtures/local_expansion/spec.yaml create mode 100644 vendor/github.com/go-openapi/validate/fixtures/recursive_expansion/item.yaml create mode 100644 vendor/github.com/go-openapi/validate/fixtures/recursive_expansion/spec.yaml create mode 100644 vendor/github.com/go-openapi/validate/fixtures/schemas/int-enum.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/direct-circular-ancestor.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/duplicateprops.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/empty-path-param-name.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/indirect-circular-ancestor.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-header-items.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-header.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-parameter-items.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-parameter-ref.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-parameter.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-schema-additionalProperties.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-schema-allOf.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-schema-items.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-schema-patternProperties.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-schema-ref.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-default-value-schema.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-example-response-ref.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-example-response.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-formdata-body-params.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-ref.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/invalid-referenced.yml create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/nestedduplicateprops.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/recursive-circular-ancestor.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-header-items.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-header.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-parameter-items.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-parameter-ref.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-parameter.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-schema-additionalProperties.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-schema-allOf.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-schema-items.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-schema-patternProperties.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-schema-ref.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-default-value-schema.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-example-response-ref.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-example-response.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-ref.json create mode 100644 vendor/github.com/go-openapi/validate/fixtures/validation/valid-referenced.yml create mode 100644 vendor/github.com/go-openapi/validate/formats.go create mode 100644 vendor/github.com/go-openapi/validate/items_validator_test.go create mode 100644 vendor/github.com/go-openapi/validate/object_validator.go create mode 100644 vendor/github.com/go-openapi/validate/object_validator_test.go create mode 100644 vendor/github.com/go-openapi/validate/parameter_validator_test.go create mode 100644 vendor/github.com/go-openapi/validate/result.go create mode 100644 vendor/github.com/go-openapi/validate/schema.go create mode 100644 vendor/github.com/go-openapi/validate/schema_props.go create mode 100644 vendor/github.com/go-openapi/validate/slice_validator.go create mode 100644 vendor/github.com/go-openapi/validate/spec.go create mode 100644 vendor/github.com/go-openapi/validate/spec_test.go create mode 100644 vendor/github.com/go-openapi/validate/type.go create mode 100644 vendor/github.com/go-openapi/validate/type_test.go create mode 100755 vendor/github.com/go-openapi/validate/update-fixtures.sh create mode 100644 vendor/github.com/go-openapi/validate/validator.go create mode 100644 vendor/github.com/go-openapi/validate/validator_test.go create mode 100644 vendor/github.com/go-openapi/validate/values.go create mode 100644 vendor/github.com/go-openapi/validate/values_test.go create mode 100644 vendor/github.com/mitchellh/mapstructure/.travis.yml create mode 100644 vendor/github.com/mitchellh/mapstructure/LICENSE create mode 100644 vendor/github.com/mitchellh/mapstructure/README.md create mode 100644 vendor/github.com/mitchellh/mapstructure/decode_hooks.go create mode 100644 vendor/github.com/mitchellh/mapstructure/decode_hooks_test.go create mode 100644 vendor/github.com/mitchellh/mapstructure/error.go create mode 100644 vendor/github.com/mitchellh/mapstructure/mapstructure.go create mode 100644 vendor/github.com/mitchellh/mapstructure/mapstructure_benchmark_test.go create mode 100644 vendor/github.com/mitchellh/mapstructure/mapstructure_bugs_test.go create mode 100644 vendor/github.com/mitchellh/mapstructure/mapstructure_examples_test.go create mode 100644 vendor/github.com/mitchellh/mapstructure/mapstructure_test.go create mode 100644 vendor/gopkg.in/mgo.v2/.travis.yml create mode 100644 vendor/gopkg.in/mgo.v2/LICENSE create mode 100644 vendor/gopkg.in/mgo.v2/Makefile create mode 100644 vendor/gopkg.in/mgo.v2/README.md create mode 100644 vendor/gopkg.in/mgo.v2/auth.go create mode 100644 vendor/gopkg.in/mgo.v2/auth_test.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/LICENSE create mode 100644 vendor/gopkg.in/mgo.v2/bson/bson.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/bson_test.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/decimal.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/decimal_test.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/decode.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/encode.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/json.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/json_test.go create mode 100755 vendor/gopkg.in/mgo.v2/bson/specdata/update.sh create mode 100644 vendor/gopkg.in/mgo.v2/bson/specdata_test.go create mode 100644 vendor/gopkg.in/mgo.v2/bulk.go create mode 100644 vendor/gopkg.in/mgo.v2/bulk_test.go create mode 100644 vendor/gopkg.in/mgo.v2/cluster.go create mode 100644 vendor/gopkg.in/mgo.v2/cluster_test.go create mode 100644 vendor/gopkg.in/mgo.v2/dbtest/dbserver.go create mode 100644 vendor/gopkg.in/mgo.v2/dbtest/dbserver_test.go create mode 100644 vendor/gopkg.in/mgo.v2/dbtest/export_test.go create mode 100644 vendor/gopkg.in/mgo.v2/doc.go create mode 100644 vendor/gopkg.in/mgo.v2/export_test.go create mode 100644 vendor/gopkg.in/mgo.v2/gridfs.go create mode 100644 vendor/gopkg.in/mgo.v2/gridfs_test.go create mode 100644 vendor/gopkg.in/mgo.v2/harness/certs/client.crt create mode 100644 vendor/gopkg.in/mgo.v2/harness/certs/client.key create mode 100644 vendor/gopkg.in/mgo.v2/harness/certs/client.pem create mode 100644 vendor/gopkg.in/mgo.v2/harness/certs/client.req create mode 100644 vendor/gopkg.in/mgo.v2/harness/certs/server.crt create mode 100644 vendor/gopkg.in/mgo.v2/harness/certs/server.key create mode 100644 vendor/gopkg.in/mgo.v2/harness/certs/server.pem create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/.env create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/cfg1/db/.empty create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/cfg1/db/journal/tempLatencyTest create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/cfg1/db/mongod.lock create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/cfg1/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/cfg1/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/cfg2/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/cfg2/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/cfg2/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/cfg3/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/cfg3/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/cfg3/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/db1/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/db1/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/db1/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/db2/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/db2/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/db2/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/db3/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/db3/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/db3/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs1a/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs1a/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs1a/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs1b/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs1b/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs1b/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs1c/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs1c/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs1c/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs2a/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs2a/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs2a/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs2b/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs2b/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs2b/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs2c/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs2c/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs2c/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs3a/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs3a/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs3a/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs3b/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs3b/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs3b/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs3c/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs3c/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs3c/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/daemons/rs4a/db/.empty create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs4a/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/rs4a/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/s1/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/s1/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/s2/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/s2/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/s3/log/run create mode 100755 vendor/gopkg.in/mgo.v2/harness/daemons/s3/run create mode 100644 vendor/gopkg.in/mgo.v2/harness/mongojs/dropall.js create mode 100644 vendor/gopkg.in/mgo.v2/harness/mongojs/init.js create mode 100644 vendor/gopkg.in/mgo.v2/harness/mongojs/wait.js create mode 100755 vendor/gopkg.in/mgo.v2/harness/setup.sh create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/LICENSE create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/bench_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/decode.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/decode_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/encode.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/encode_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/example_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/extension.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/extension_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/fold.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/fold_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/indent.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/number_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/scanner.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/scanner_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/stream.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/stream_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/tagkey_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/tags.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/tags_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/testdata/code.json.gz create mode 100644 vendor/gopkg.in/mgo.v2/internal/sasl/sasl.c create mode 100644 vendor/gopkg.in/mgo.v2/internal/sasl/sasl.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/sasl/sasl_windows.c create mode 100644 vendor/gopkg.in/mgo.v2/internal/sasl/sasl_windows.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/sasl/sasl_windows.h create mode 100644 vendor/gopkg.in/mgo.v2/internal/sasl/sspi_windows.c create mode 100644 vendor/gopkg.in/mgo.v2/internal/sasl/sspi_windows.h create mode 100644 vendor/gopkg.in/mgo.v2/internal/scram/scram.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/scram/scram_test.go create mode 100644 vendor/gopkg.in/mgo.v2/log.go create mode 100644 vendor/gopkg.in/mgo.v2/queue.go create mode 100644 vendor/gopkg.in/mgo.v2/queue_test.go create mode 100644 vendor/gopkg.in/mgo.v2/raceoff.go create mode 100644 vendor/gopkg.in/mgo.v2/raceon.go create mode 100644 vendor/gopkg.in/mgo.v2/saslimpl.go create mode 100644 vendor/gopkg.in/mgo.v2/saslstub.go create mode 100644 vendor/gopkg.in/mgo.v2/server.go create mode 100644 vendor/gopkg.in/mgo.v2/session.go create mode 100644 vendor/gopkg.in/mgo.v2/session_test.go create mode 100644 vendor/gopkg.in/mgo.v2/socket.go create mode 100644 vendor/gopkg.in/mgo.v2/stats.go create mode 100644 vendor/gopkg.in/mgo.v2/suite_test.go create mode 100644 vendor/gopkg.in/mgo.v2/syscall_test.go create mode 100644 vendor/gopkg.in/mgo.v2/syscall_windows_test.go create mode 100644 vendor/gopkg.in/mgo.v2/txn/chaos.go create mode 100644 vendor/gopkg.in/mgo.v2/txn/debug.go create mode 100644 vendor/gopkg.in/mgo.v2/txn/dockey_test.go create mode 100644 vendor/gopkg.in/mgo.v2/txn/flusher.go create mode 100644 vendor/gopkg.in/mgo.v2/txn/output.txt create mode 100644 vendor/gopkg.in/mgo.v2/txn/sim_test.go create mode 100644 vendor/gopkg.in/mgo.v2/txn/tarjan.go create mode 100644 vendor/gopkg.in/mgo.v2/txn/tarjan_test.go create mode 100644 vendor/gopkg.in/mgo.v2/txn/txn.go create mode 100644 vendor/gopkg.in/mgo.v2/txn/txn_test.go diff --git a/glide.lock b/glide.lock index fa434f76a3..8ea7f6b87c 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: fdb328aea39579946cca5b8c84ccee838af158d65f221b472c5587a0160e80da -updated: 2017-10-30T21:04:23.594695655+05:30 +hash: 9e40ea5d44c7ba10eebc203af191d066fdd0f057f720ea4058579e7871f45f5a +updated: 2017-10-30T22:35:02.533201015+05:30 imports: - name: cloud.google.com/go version: 3b1ae45394a234c385be014e9a488f2bb6eef821 @@ -14,6 +14,8 @@ imports: - parse - name: github.com/alecthomas/units version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a +- name: github.com/asaskevich/govalidator + version: ddb193b4c7bfa1d1c1923ae05a1ee8fb0cd45cf3 - name: github.com/aws/aws-sdk-go version: 96358b8282b1a3aa66836d2f2fe66216cc419668 subpackages: @@ -102,19 +104,36 @@ imports: version: 544ad421d0a0d09c3146998a2e9e953fe2491827 subpackages: - client + - client/servers + - client/zones + - model - models - name: github.com/ghodss/yaml version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee - name: github.com/go-ini/ini version: f280b3ba517bf5fc98922624f21fb0e7a92adaec +- name: github.com/go-openapi/analysis + version: 8ed83f2ea9f00f945516462951a288eaa68bf0d6 +- name: github.com/go-openapi/errors + version: 03cfca65330da08a5a440053faf994a3c682b5bf - name: github.com/go-openapi/jsonpointer version: 46af16f9f7b149af66e5d1bd010e3574dc06de98 - name: github.com/go-openapi/jsonreference version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272 +- name: github.com/go-openapi/loads + version: c3e1ca4c0b6160cac10aeef7e8b425cc95b9c820 +- name: github.com/go-openapi/runtime + version: e8231e16de5bcda9839e03ae07c5c96a1fd82041 + subpackages: + - client - name: github.com/go-openapi/spec version: 6aced65f8501fe1217321abf0749d354824ba2ff +- name: github.com/go-openapi/strfmt + version: 610b6cacdcde6852f4de68998bd20ce1dac85b22 - name: github.com/go-openapi/swag version: 1d0bd113de87027671077d3c71eb3ac5d7dbba72 +- name: github.com/go-openapi/validate + version: b6cfc35bf312e6fb320d85ed9fc3ac408dcb8694 - name: github.com/gogo/protobuf version: e18d7aa8f8c624c915db340349aad4c49b10d173 subpackages: @@ -137,7 +156,7 @@ imports: - name: github.com/imdario/mergo version: 6633656539c1639d9d78127b7d47c622b5d7b6dc - name: github.com/infobloxopen/infoblox-go-client - version: 8e61c1bbe76f98191c205f0a4d8a60390ae17e7f + version: e2811d86bed7bb487eeb0806337b6f9e9d93d5e7 - name: github.com/jmespath/go-jmespath version: bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d - name: github.com/jonboulle/clockwork @@ -158,6 +177,8 @@ imports: version: c12348ce28de40eed0136aa2b644d0ee0650e56c subpackages: - pbutil +- name: github.com/mitchellh/mapstructure + version: 06020f85339e21b2478f756a78e295255ffa4d6a - name: github.com/pkg/errors version: f15c970de5b76fac0b59abb32d62c17cc7bed265 - name: github.com/pmezard/go-difflib @@ -264,6 +285,11 @@ imports: - urlfetch - name: gopkg.in/inf.v0 version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 +- name: gopkg.in/mgo.v2 + version: 3f83fa5005286a7fe593b055f0d7771a7dce4655 + subpackages: + - bson + - internal/json - name: gopkg.in/yaml.v2 version: 53feefa2559fb8dfa8d81baad31be332c97d6c77 - name: k8s.io/apimachinery diff --git a/glide.yaml b/glide.yaml index 1c2825e5a0..812adf05df 100644 --- a/glide.yaml +++ b/glide.yaml @@ -61,5 +61,5 @@ import: - package: github.com/infobloxopen/infoblox-go-client - package: github.com/ffledgling/pdns-go subpackages: - - client - - models + - client + - model diff --git a/vendor/github.com/asaskevich/govalidator/.travis.yml b/vendor/github.com/asaskevich/govalidator/.travis.yml new file mode 100644 index 0000000000..e29f8eef5e --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/.travis.yml @@ -0,0 +1,14 @@ +language: go + +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - tip + +notifications: + email: + - bwatas@gmail.com diff --git a/vendor/github.com/asaskevich/govalidator/LICENSE b/vendor/github.com/asaskevich/govalidator/LICENSE new file mode 100644 index 0000000000..2f9a31fadf --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Alex Saskevich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/asaskevich/govalidator/README.md b/vendor/github.com/asaskevich/govalidator/README.md new file mode 100644 index 0000000000..9d2e1357b1 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/README.md @@ -0,0 +1,423 @@ +govalidator +=========== +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/asaskevich/govalidator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![GoDoc](https://godoc.org/github.com/asaskevich/govalidator?status.png)](https://godoc.org/github.com/asaskevich/govalidator) [![Coverage Status](https://img.shields.io/coveralls/asaskevich/govalidator.svg)](https://coveralls.io/r/asaskevich/govalidator?branch=master) [![wercker status](https://app.wercker.com/status/1ec990b09ea86c910d5f08b0e02c6043/s "wercker status")](https://app.wercker.com/project/bykey/1ec990b09ea86c910d5f08b0e02c6043) +[![Build Status](https://travis-ci.org/asaskevich/govalidator.svg?branch=master)](https://travis-ci.org/asaskevich/govalidator) [![Go Report Card](https://goreportcard.com/badge/github.com/asaskevich/govalidator)](https://goreportcard.com/report/github.com/asaskevich/govalidator) [![GoSearch](http://go-search.org/badge?id=github.com%2Fasaskevich%2Fgovalidator)](http://go-search.org/view?id=github.com%2Fasaskevich%2Fgovalidator) + +A package of validators and sanitizers for strings, structs and collections. Based on [validator.js](https://github.com/chriso/validator.js). + +#### Installation +Make sure that Go is installed on your computer. +Type the following command in your terminal: + + go get github.com/asaskevich/govalidator + +or you can get specified release of the package with `gopkg.in`: + + go get gopkg.in/asaskevich/govalidator.v4 + +After it the package is ready to use. + + +#### Import package in your project +Add following line in your `*.go` file: +```go +import "github.com/asaskevich/govalidator" +``` +If you are unhappy to use long `govalidator`, you can do something like this: +```go +import ( + valid "github.com/asaskevich/govalidator" +) +``` + +#### Activate behavior to require all fields have a validation tag by default +`SetFieldsRequiredByDefault` causes validation to fail when struct fields do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). A good place to activate this is a package init function or the main() function. + +```go +import "github.com/asaskevich/govalidator" + +func init() { + govalidator.SetFieldsRequiredByDefault(true) +} +``` + +Here's some code to explain it: +```go +// this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter): +type exampleStruct struct { + Name string `` + Email string `valid:"email"` +} + +// this, however, will only fail when Email is empty or an invalid email address: +type exampleStruct2 struct { + Name string `valid:"-"` + Email string `valid:"email"` +} + +// lastly, this will only fail when Email is an invalid email address but not when it's empty: +type exampleStruct2 struct { + Name string `valid:"-"` + Email string `valid:"email,optional"` +} +``` + +#### Recent breaking changes (see [#123](https://github.com/asaskevich/govalidator/pull/123)) +##### Custom validator function signature +A context was added as the second parameter, for structs this is the object being validated – this makes dependent validation possible. +```go +import "github.com/asaskevich/govalidator" + +// old signature +func(i interface{}) bool + +// new signature +func(i interface{}, o interface{}) bool +``` + +##### Adding a custom validator +This was changed to prevent data races when accessing custom validators. +```go +import "github.com/asaskevich/govalidator" + +// before +govalidator.CustomTypeTagMap["customByteArrayValidator"] = CustomTypeValidator(func(i interface{}, o interface{}) bool { + // ... +}) + +// after +govalidator.CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { + // ... +})) +``` + +#### List of functions: +```go +func Abs(value float64) float64 +func BlackList(str, chars string) string +func ByteLength(str string, params ...string) bool +func CamelCaseToUnderscore(str string) string +func Contains(str, substring string) bool +func Count(array []interface{}, iterator ConditionIterator) int +func Each(array []interface{}, iterator Iterator) +func ErrorByField(e error, field string) string +func ErrorsByField(e error) map[string]string +func Filter(array []interface{}, iterator ConditionIterator) []interface{} +func Find(array []interface{}, iterator ConditionIterator) interface{} +func GetLine(s string, index int) (string, error) +func GetLines(s string) []string +func InRange(value, left, right float64) bool +func IsASCII(str string) bool +func IsAlpha(str string) bool +func IsAlphanumeric(str string) bool +func IsBase64(str string) bool +func IsByteLength(str string, min, max int) bool +func IsCIDR(str string) bool +func IsCreditCard(str string) bool +func IsDNSName(str string) bool +func IsDataURI(str string) bool +func IsDialString(str string) bool +func IsDivisibleBy(str, num string) bool +func IsEmail(str string) bool +func IsFilePath(str string) (bool, int) +func IsFloat(str string) bool +func IsFullWidth(str string) bool +func IsHalfWidth(str string) bool +func IsHexadecimal(str string) bool +func IsHexcolor(str string) bool +func IsHost(str string) bool +func IsIP(str string) bool +func IsIPv4(str string) bool +func IsIPv6(str string) bool +func IsISBN(str string, version int) bool +func IsISBN10(str string) bool +func IsISBN13(str string) bool +func IsISO3166Alpha2(str string) bool +func IsISO3166Alpha3(str string) bool +func IsISO693Alpha2(str string) bool +func IsISO693Alpha3b(str string) bool +func IsISO4217(str string) bool +func IsIn(str string, params ...string) bool +func IsInt(str string) bool +func IsJSON(str string) bool +func IsLatitude(str string) bool +func IsLongitude(str string) bool +func IsLowerCase(str string) bool +func IsMAC(str string) bool +func IsMongoID(str string) bool +func IsMultibyte(str string) bool +func IsNatural(value float64) bool +func IsNegative(value float64) bool +func IsNonNegative(value float64) bool +func IsNonPositive(value float64) bool +func IsNull(str string) bool +func IsNumeric(str string) bool +func IsPort(str string) bool +func IsPositive(value float64) bool +func IsPrintableASCII(str string) bool +func IsRFC3339(str string) bool +func IsRGBcolor(str string) bool +func IsRequestURI(rawurl string) bool +func IsRequestURL(rawurl string) bool +func IsSSN(str string) bool +func IsSemver(str string) bool +func IsTime(str string, format string) bool +func IsURL(str string) bool +func IsUTFDigit(str string) bool +func IsUTFLetter(str string) bool +func IsUTFLetterNumeric(str string) bool +func IsUTFNumeric(str string) bool +func IsUUID(str string) bool +func IsUUIDv3(str string) bool +func IsUUIDv4(str string) bool +func IsUUIDv5(str string) bool +func IsUpperCase(str string) bool +func IsVariableWidth(str string) bool +func IsWhole(value float64) bool +func LeftTrim(str, chars string) string +func Map(array []interface{}, iterator ResultIterator) []interface{} +func Matches(str, pattern string) bool +func NormalizeEmail(str string) (string, error) +func PadBoth(str string, padStr string, padLen int) string +func PadLeft(str string, padStr string, padLen int) string +func PadRight(str string, padStr string, padLen int) string +func Range(str string, params ...string) bool +func RemoveTags(s string) string +func ReplacePattern(str, pattern, replace string) string +func Reverse(s string) string +func RightTrim(str, chars string) string +func RuneLength(str string, params ...string) bool +func SafeFileName(str string) string +func SetFieldsRequiredByDefault(value bool) +func Sign(value float64) float64 +func StringLength(str string, params ...string) bool +func StringMatches(s string, params ...string) bool +func StripLow(str string, keepNewLines bool) string +func ToBoolean(str string) (bool, error) +func ToFloat(str string) (float64, error) +func ToInt(str string) (int64, error) +func ToJSON(obj interface{}) (string, error) +func ToString(obj interface{}) string +func Trim(str, chars string) string +func Truncate(str string, length int, ending string) string +func UnderscoreToCamelCase(s string) string +func ValidateStruct(s interface{}) (bool, error) +func WhiteList(str, chars string) string +type ConditionIterator +type CustomTypeValidator +type Error +func (e Error) Error() string +type Errors +func (es Errors) Error() string +func (es Errors) Errors() []error +type ISO3166Entry +type Iterator +type ParamValidator +type ResultIterator +type UnsupportedTypeError +func (e *UnsupportedTypeError) Error() string +type Validator +``` + +#### Examples +###### IsURL +```go +println(govalidator.IsURL(`http://user@pass:domain.com/path/page`)) +``` +###### ToString +```go +type User struct { + FirstName string + LastName string +} + +str := govalidator.ToString(&User{"John", "Juan"}) +println(str) +``` +###### Each, Map, Filter, Count for slices +Each iterates over the slice/array and calls Iterator for every item +```go +data := []interface{}{1, 2, 3, 4, 5} +var fn govalidator.Iterator = func(value interface{}, index int) { + println(value.(int)) +} +govalidator.Each(data, fn) +``` +```go +data := []interface{}{1, 2, 3, 4, 5} +var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} { + return value.(int) * 3 +} +_ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15} +``` +```go +data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} +var fn govalidator.ConditionIterator = func(value interface{}, index int) bool { + return value.(int)%2 == 0 +} +_ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10} +_ = govalidator.Count(data, fn) // result = 5 +``` +###### ValidateStruct [#2](https://github.com/asaskevich/govalidator/pull/2) +If you want to validate structs, you can use tag `valid` for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place `-` in your tag. If you need a validator that is not on the list below, you can add it like this: +```go +govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool { + return str == "duck" +}) +``` +For completely custom validators (interface-based), see below. + +Here is a list of available validators for struct fields (validator - used function): +```go +"email": IsEmail, +"url": IsURL, +"dialstring": IsDialString, +"requrl": IsRequestURL, +"requri": IsRequestURI, +"alpha": IsAlpha, +"utfletter": IsUTFLetter, +"alphanum": IsAlphanumeric, +"utfletternum": IsUTFLetterNumeric, +"numeric": IsNumeric, +"utfnumeric": IsUTFNumeric, +"utfdigit": IsUTFDigit, +"hexadecimal": IsHexadecimal, +"hexcolor": IsHexcolor, +"rgbcolor": IsRGBcolor, +"lowercase": IsLowerCase, +"uppercase": IsUpperCase, +"int": IsInt, +"float": IsFloat, +"null": IsNull, +"uuid": IsUUID, +"uuidv3": IsUUIDv3, +"uuidv4": IsUUIDv4, +"uuidv5": IsUUIDv5, +"creditcard": IsCreditCard, +"isbn10": IsISBN10, +"isbn13": IsISBN13, +"json": IsJSON, +"multibyte": IsMultibyte, +"ascii": IsASCII, +"printableascii": IsPrintableASCII, +"fullwidth": IsFullWidth, +"halfwidth": IsHalfWidth, +"variablewidth": IsVariableWidth, +"base64": IsBase64, +"datauri": IsDataURI, +"ip": IsIP, +"port": IsPort, +"ipv4": IsIPv4, +"ipv6": IsIPv6, +"dns": IsDNSName, +"host": IsHost, +"mac": IsMAC, +"latitude": IsLatitude, +"longitude": IsLongitude, +"ssn": IsSSN, +"semver": IsSemver, +"rfc3339": IsRFC3339, +"ISO3166Alpha2": IsISO3166Alpha2, +"ISO3166Alpha3": IsISO3166Alpha3, +``` +Validators with parameters + +```go +"range(min|max)": Range, +"length(min|max)": ByteLength, +"runelength(min|max)": RuneLength, +"matches(pattern)": StringMatches, +"in(string1|string2|...|stringN)": IsIn, +``` + +And here is small example of usage: +```go +type Post struct { + Title string `valid:"alphanum,required"` + Message string `valid:"duck,ascii"` + AuthorIP string `valid:"ipv4"` + Date string `valid:"-"` +} +post := &Post{ + Title: "My Example Post", + Message: "duck", + AuthorIP: "123.234.54.3", +} + +// Add your own struct validation tags +govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool { + return str == "duck" +}) + +result, err := govalidator.ValidateStruct(post) +if err != nil { + println("error: " + err.Error()) +} +println(result) +``` +###### WhiteList +```go +// Remove all characters from string ignoring characters between "a" and "z" +println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa") +``` + +###### Custom validation functions +Custom validation using your own domain specific validators is also available - here's an example of how to use it: +```go +import "github.com/asaskevich/govalidator" + +type CustomByteArray [6]byte // custom types are supported and can be validated + +type StructWithCustomByteArray struct { + ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` // multiple custom validators are possible as well and will be evaluated in sequence + Email string `valid:"email"` + CustomMinLength int `valid:"-"` +} + +govalidator.CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, context interface{}) bool { + switch v := context.(type) { // you can type switch on the context interface being validated + case StructWithCustomByteArray: + // you can check and validate against some other field in the context, + // return early or not validate against the context at all – your choice + case SomeOtherType: + // ... + default: + // expecting some other type? Throw/panic here or continue + } + + switch v := i.(type) { // type switch on the struct field being validated + case CustomByteArray: + for _, e := range v { // this validator checks that the byte array is not empty, i.e. not all zeroes + if e != 0 { + return true + } + } + } + return false +})) +govalidator.CustomTypeTagMap.Set("customMinLengthValidator", CustomTypeValidator(func(i interface{}, context interface{}) bool { + switch v := context.(type) { // this validates a field against the value in another field, i.e. dependent validation + case StructWithCustomByteArray: + return len(v.ID) >= v.CustomMinLength + } + return false +})) +``` + +#### Notes +Documentation is available here: [godoc.org](https://godoc.org/github.com/asaskevich/govalidator). +Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator). + +#### Support +If you do have a contribution for the package feel free to put up a Pull Request or open Issue. + +#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors) +* [Daniel Lohse](https://github.com/annismckenzie) +* [Attila Oláh](https://github.com/attilaolah) +* [Daniel Korner](https://github.com/Dadie) +* [Steven Wilkin](https://github.com/stevenwilkin) +* [Deiwin Sarjas](https://github.com/deiwin) +* [Noah Shibley](https://github.com/slugmobile) +* [Nathan Davies](https://github.com/nathj07) +* [Matt Sanford](https://github.com/mzsanford) +* [Simon ccl1115](https://github.com/ccl1115) diff --git a/vendor/github.com/asaskevich/govalidator/arrays.go b/vendor/github.com/asaskevich/govalidator/arrays.go new file mode 100644 index 0000000000..5bace2654d --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/arrays.go @@ -0,0 +1,58 @@ +package govalidator + +// Iterator is the function that accepts element of slice/array and its index +type Iterator func(interface{}, int) + +// ResultIterator is the function that accepts element of slice/array and its index and returns any result +type ResultIterator func(interface{}, int) interface{} + +// ConditionIterator is the function that accepts element of slice/array and its index and returns boolean +type ConditionIterator func(interface{}, int) bool + +// Each iterates over the slice and apply Iterator to every item +func Each(array []interface{}, iterator Iterator) { + for index, data := range array { + iterator(data, index) + } +} + +// Map iterates over the slice and apply ResultIterator to every item. Returns new slice as a result. +func Map(array []interface{}, iterator ResultIterator) []interface{} { + var result = make([]interface{}, len(array)) + for index, data := range array { + result[index] = iterator(data, index) + } + return result +} + +// Find iterates over the slice and apply ConditionIterator to every item. Returns first item that meet ConditionIterator or nil otherwise. +func Find(array []interface{}, iterator ConditionIterator) interface{} { + for index, data := range array { + if iterator(data, index) { + return data + } + } + return nil +} + +// Filter iterates over the slice and apply ConditionIterator to every item. Returns new slice. +func Filter(array []interface{}, iterator ConditionIterator) []interface{} { + var result = make([]interface{}, 0) + for index, data := range array { + if iterator(data, index) { + result = append(result, data) + } + } + return result +} + +// Count iterates over the slice and apply ConditionIterator to every item. Returns count of items that meets ConditionIterator. +func Count(array []interface{}, iterator ConditionIterator) int { + count := 0 + for index, data := range array { + if iterator(data, index) { + count = count + 1 + } + } + return count +} diff --git a/vendor/github.com/asaskevich/govalidator/arrays_test.go b/vendor/github.com/asaskevich/govalidator/arrays_test.go new file mode 100644 index 0000000000..1a9ac66969 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/arrays_test.go @@ -0,0 +1,116 @@ +package govalidator + +import "testing" + +func TestEach(t *testing.T) { + // TODO Maybe refactor? + t.Parallel() + acc := 0 + data := []interface{}{1, 2, 3, 4, 5} + var fn Iterator = func(value interface{}, index int) { + acc = acc + value.(int) + } + Each(data, fn) + if acc != 15 { + t.Errorf("Expected Each(..) to be %v, got %v", 15, acc) + } +} + +func ExampleEach() { + data := []interface{}{1, 2, 3, 4, 5} + var fn Iterator = func(value interface{}, index int) { + println(value.(int)) + } + Each(data, fn) +} + +func TestMap(t *testing.T) { + // TODO Maybe refactor? + t.Parallel() + data := []interface{}{1, 2, 3, 4, 5} + var fn ResultIterator = func(value interface{}, index int) interface{} { + return value.(int) * 3 + } + result := Map(data, fn) + for i, d := range result { + if d != fn(data[i], i) { + t.Errorf("Expected Map(..) to be %v, got %v", fn(data[i], i), d) + } + } +} + +func ExampleMap() { + data := []interface{}{1, 2, 3, 4, 5} + var fn ResultIterator = func(value interface{}, index int) interface{} { + return value.(int) * 3 + } + _ = Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15} +} + +func TestFind(t *testing.T) { + // TODO Maybe refactor? + t.Parallel() + findElement := 96 + data := []interface{}{1, 2, 3, 4, findElement, 5} + var fn1 ConditionIterator = func(value interface{}, index int) bool { + return value.(int) == findElement + } + var fn2 ConditionIterator = func(value interface{}, index int) bool { + value, _ = value.(string) + return value == "govalidator" + } + val1 := Find(data, fn1) + val2 := Find(data, fn2) + if val1 != findElement { + t.Errorf("Expected Find(..) to be %v, got %v", findElement, val1) + } + if val2 != nil { + t.Errorf("Expected Find(..) to be %v, got %v", nil, val2) + } +} + +func TestFilter(t *testing.T) { + // TODO Maybe refactor? + t.Parallel() + data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + answer := []interface{}{2, 4, 6, 8, 10} + var fn ConditionIterator = func(value interface{}, index int) bool { + return value.(int)%2 == 0 + } + result := Filter(data, fn) + for i := range result { + if result[i] != answer[i] { + t.Errorf("Expected Filter(..) to be %v, got %v", answer[i], result[i]) + } + } +} + +func ExampleFilter() { + data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + var fn ConditionIterator = func(value interface{}, index int) bool { + return value.(int)%2 == 0 + } + _ = Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10} +} + +func TestCount(t *testing.T) { + // TODO Maybe refactor? + t.Parallel() + data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + count := 5 + var fn ConditionIterator = func(value interface{}, index int) bool { + return value.(int)%2 == 0 + } + result := Count(data, fn) + if result != count { + t.Errorf("Expected Count(..) to be %v, got %v", count, result) + } +} + +func ExampleCount() { + data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + var fn ConditionIterator = func(value interface{}, index int) bool { + return value.(int)%2 == 0 + } + _ = Count(data, fn) // result = 5 +} diff --git a/vendor/github.com/asaskevich/govalidator/converter.go b/vendor/github.com/asaskevich/govalidator/converter.go new file mode 100644 index 0000000000..d69114c4b7 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/converter.go @@ -0,0 +1,45 @@ +package govalidator + +import ( + "encoding/json" + "fmt" + "strconv" +) + +// ToString convert the input to a string. +func ToString(obj interface{}) string { + res := fmt.Sprintf("%v", obj) + return string(res) +} + +// ToJSON convert the input to a valid JSON string +func ToJSON(obj interface{}) (string, error) { + res, err := json.Marshal(obj) + if err != nil { + res = []byte("") + } + return string(res), err +} + +// ToFloat convert the input string to a float, or 0.0 if the input is not a float. +func ToFloat(str string) (float64, error) { + res, err := strconv.ParseFloat(str, 64) + if err != nil { + res = 0.0 + } + return res, err +} + +// ToInt convert the input string to an integer, or 0 if the input is not an integer. +func ToInt(str string) (int64, error) { + res, err := strconv.ParseInt(str, 0, 64) + if err != nil { + res = 0 + } + return res, err +} + +// ToBoolean convert the input string to a boolean. +func ToBoolean(str string) (bool, error) { + return strconv.ParseBool(str) +} diff --git a/vendor/github.com/asaskevich/govalidator/converter_test.go b/vendor/github.com/asaskevich/govalidator/converter_test.go new file mode 100644 index 0000000000..ecc457be86 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/converter_test.go @@ -0,0 +1,78 @@ +package govalidator + +import ( + "fmt" + "testing" +) + +func TestToInt(t *testing.T) { + tests := []string{"1000", "-123", "abcdef", "100000000000000000000000000000000000000000000"} + expected := []int64{1000, -123, 0, 0} + for i := 0; i < len(tests); i++ { + result, _ := ToInt(tests[i]) + if result != expected[i] { + t.Log("Case ", i, ": expected ", expected[i], " when result is ", result) + t.FailNow() + } + } +} + +func TestToBoolean(t *testing.T) { + tests := []string{"true", "1", "True", "false", "0", "abcdef"} + expected := []bool{true, true, true, false, false, false} + for i := 0; i < len(tests); i++ { + res, _ := ToBoolean(tests[i]) + if res != expected[i] { + t.Log("Case ", i, ": expected ", expected[i], " when result is ", res) + t.FailNow() + } + } +} + +func toString(t *testing.T, test interface{}, expected string) { + res := ToString(test) + if res != expected { + t.Log("Case ToString: expected ", expected, " when result is ", res) + t.FailNow() + } +} + +func TestToString(t *testing.T) { + toString(t, "str123", "str123") + toString(t, 123, "123") + toString(t, 12.3, "12.3") + toString(t, true, "true") + toString(t, 1.5+10i, "(1.5+10i)") + // Sprintf function not guarantee that maps with equal keys always will be equal in string representation + //toString(t, struct{ Keys map[int]int }{Keys: map[int]int{1: 2, 3: 4}}, "{map[1:2 3:4]}") +} + +func TestToFloat(t *testing.T) { + tests := []string{"", "123", "-.01", "10.", "string", "1.23e3", ".23e10"} + expected := []float64{0, 123, -0.01, 10.0, 0, 1230, 0.23e10} + for i := 0; i < len(tests); i++ { + res, _ := ToFloat(tests[i]) + if res != expected[i] { + t.Log("Case ", i, ": expected ", expected[i], " when result is ", res) + t.FailNow() + } + } +} + +func TestToJSON(t *testing.T) { + tests := []interface{}{"test", map[string]string{"a": "b", "b": "c"}, func() error { return fmt.Errorf("Error") }} + expected := [][]string{ + {"\"test\"", ""}, + {"{\"a\":\"b\",\"b\":\"c\"}", ""}, + {"", "json: unsupported type: func() error"}, + } + for i, test := range tests { + actual, err := ToJSON(test) + if actual != expected[i][0] { + t.Errorf("Expected toJSON(%v) to return '%v', got '%v'", test, expected[i][0], actual) + } + if fmt.Sprintf("%v", err) != expected[i][1] { + t.Errorf("Expected error returned from toJSON(%v) to return '%v', got '%v'", test, expected[i][1], fmt.Sprintf("%v", err)) + } + } +} diff --git a/vendor/github.com/asaskevich/govalidator/error.go b/vendor/github.com/asaskevich/govalidator/error.go new file mode 100644 index 0000000000..b9c32079b6 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/error.go @@ -0,0 +1,36 @@ +package govalidator + +import "strings" + +// Errors is an array of multiple errors and conforms to the error interface. +type Errors []error + +// Errors returns itself. +func (es Errors) Errors() []error { + return es +} + +func (es Errors) Error() string { + var errs []string + for _, e := range es { + errs = append(errs, e.Error()) + } + return strings.Join(errs, ";") +} + +// Error encapsulates a name, an error and whether there's a custom error message or not. +type Error struct { + Name string + Err error + CustomErrorMessageExists bool + + // Validator indicates the name of the validator that failed + Validator string +} + +func (e Error) Error() string { + if e.CustomErrorMessageExists { + return e.Err.Error() + } + return e.Name + ": " + e.Err.Error() +} diff --git a/vendor/github.com/asaskevich/govalidator/error_test.go b/vendor/github.com/asaskevich/govalidator/error_test.go new file mode 100644 index 0000000000..e673f28244 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/error_test.go @@ -0,0 +1,29 @@ +package govalidator + +import ( + "fmt" + "testing" +) + +func TestErrorsToString(t *testing.T) { + t.Parallel() + customErr := &Error{Name: "Custom Error Name", Err: fmt.Errorf("stdlib error")} + customErrWithCustomErrorMessage := &Error{Name: "Custom Error Name 2", Err: fmt.Errorf("Bad stuff happened"), CustomErrorMessageExists: true} + + var tests = []struct { + param1 Errors + expected string + }{ + {Errors{}, ""}, + {Errors{fmt.Errorf("Error 1")}, "Error 1"}, + {Errors{fmt.Errorf("Error 1"), fmt.Errorf("Error 2")}, "Error 1;Error 2"}, + {Errors{customErr, fmt.Errorf("Error 2")}, "Custom Error Name: stdlib error;Error 2"}, + {Errors{fmt.Errorf("Error 123"), customErrWithCustomErrorMessage}, "Error 123;Bad stuff happened"}, + } + for _, test := range tests { + actual := test.param1.Error() + if actual != test.expected { + t.Errorf("Expected Error() to return '%v', got '%v'", test.expected, actual) + } + } +} diff --git a/vendor/github.com/asaskevich/govalidator/numerics.go b/vendor/github.com/asaskevich/govalidator/numerics.go new file mode 100644 index 0000000000..5be281f249 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/numerics.go @@ -0,0 +1,57 @@ +package govalidator + +import "math" + +// Abs returns absolute value of number +func Abs(value float64) float64 { + return math.Abs(value) +} + +// Sign returns signum of number: 1 in case of value > 0, -1 in case of value < 0, 0 otherwise +func Sign(value float64) float64 { + if value > 0 { + return 1 + } else if value < 0 { + return -1 + } else { + return 0 + } +} + +// IsNegative returns true if value < 0 +func IsNegative(value float64) bool { + return value < 0 +} + +// IsPositive returns true if value > 0 +func IsPositive(value float64) bool { + return value > 0 +} + +// IsNonNegative returns true if value >= 0 +func IsNonNegative(value float64) bool { + return value >= 0 +} + +// IsNonPositive returns true if value <= 0 +func IsNonPositive(value float64) bool { + return value <= 0 +} + +// InRange returns true if value lies between left and right border +func InRange(value, left, right float64) bool { + if left > right { + left, right = right, left + } + return value >= left && value <= right +} + +// IsWhole returns true if value is whole number +func IsWhole(value float64) bool { + return math.Remainder(value, 1) == 0 +} + +// IsNatural returns true if value is natural number (positive and whole) +func IsNatural(value float64) bool { + return IsWhole(value) && IsPositive(value) +} diff --git a/vendor/github.com/asaskevich/govalidator/numerics_test.go b/vendor/github.com/asaskevich/govalidator/numerics_test.go new file mode 100644 index 0000000000..1bad52107d --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/numerics_test.go @@ -0,0 +1,204 @@ +package govalidator + +import "testing" + +func TestAbs(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected float64 + }{ + {0, 0}, + {-1, 1}, + {10, 10}, + {3.14, 3.14}, + {-96, 96}, + {-10e-12, 10e-12}, + } + for _, test := range tests { + actual := Abs(test.param) + if actual != test.expected { + t.Errorf("Expected Abs(%v) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestSign(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected float64 + }{ + {0, 0}, + {-1, -1}, + {10, 1}, + {3.14, 1}, + {-96, -1}, + {-10e-12, -1}, + } + for _, test := range tests { + actual := Sign(test.param) + if actual != test.expected { + t.Errorf("Expected Sign(%v) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsNegative(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, false}, + {-1, true}, + {10, false}, + {3.14, false}, + {-96, true}, + {-10e-12, true}, + } + for _, test := range tests { + actual := IsNegative(test.param) + if actual != test.expected { + t.Errorf("Expected IsNegative(%v) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsNonNegative(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, true}, + {-1, false}, + {10, true}, + {3.14, true}, + {-96, false}, + {-10e-12, false}, + } + for _, test := range tests { + actual := IsNonNegative(test.param) + if actual != test.expected { + t.Errorf("Expected IsNonNegative(%v) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsPositive(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, false}, + {-1, false}, + {10, true}, + {3.14, true}, + {-96, false}, + {-10e-12, false}, + } + for _, test := range tests { + actual := IsPositive(test.param) + if actual != test.expected { + t.Errorf("Expected IsPositive(%v) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsNonPositive(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, true}, + {-1, true}, + {10, false}, + {3.14, false}, + {-96, true}, + {-10e-12, true}, + } + for _, test := range tests { + actual := IsNonPositive(test.param) + if actual != test.expected { + t.Errorf("Expected IsNonPositive(%v) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsWhole(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, true}, + {-1, true}, + {10, true}, + {3.14, false}, + {-96, true}, + {-10e-12, false}, + } + for _, test := range tests { + actual := IsWhole(test.param) + if actual != test.expected { + t.Errorf("Expected IsWhole(%v) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsNatural(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + expected bool + }{ + {0, false}, + {-1, false}, + {10, true}, + {3.14, false}, + {96, true}, + {-10e-12, false}, + } + for _, test := range tests { + actual := IsNatural(test.param) + if actual != test.expected { + t.Errorf("Expected IsNatural(%v) to be %v, got %v", test.param, test.expected, actual) + } + } +} +func TestInRange(t *testing.T) { + t.Parallel() + + var tests = []struct { + param float64 + left float64 + right float64 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {-1, 0, 0, false}, + {0, -1, 1, true}, + {0, 0, 1, true}, + {0, -1, 0, true}, + {0, 0, -1, true}, + {0, 10, 5, false}, + } + for _, test := range tests { + actual := InRange(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRange(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) + } + } +} diff --git a/vendor/github.com/asaskevich/govalidator/patterns.go b/vendor/github.com/asaskevich/govalidator/patterns.go new file mode 100644 index 0000000000..4a34e2240d --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/patterns.go @@ -0,0 +1,90 @@ +package govalidator + +import "regexp" + +// Basic regular expressions for validating strings +const ( + Email string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$" + CreditCard string = "^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$" + ISBN10 string = "^(?:[0-9]{9}X|[0-9]{10})$" + ISBN13 string = "^(?:[0-9]{13})$" + UUID3 string = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$" + UUID4 string = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" + UUID5 string = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" + UUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + Alpha string = "^[a-zA-Z]+$" + Alphanumeric string = "^[a-zA-Z0-9]+$" + Numeric string = "^[0-9]+$" + Int string = "^(?:[-+]?(?:0|[1-9][0-9]*))$" + Float string = "^(?:[-+]?(?:[0-9]+))?(?:\\.[0-9]*)?(?:[eE][\\+\\-]?(?:[0-9]+))?$" + Hexadecimal string = "^[0-9a-fA-F]+$" + Hexcolor string = "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$" + RGBcolor string = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$" + ASCII string = "^[\x00-\x7F]+$" + Multibyte string = "[^\x00-\x7F]" + FullWidth string = "[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]" + HalfWidth string = "[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]" + Base64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$" + PrintableASCII string = "^[\x20-\x7E]+$" + DataURI string = "^data:.+\\/(.+);base64$" + Latitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$" + Longitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$" + DNSName string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$` + IP string = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))` + URLSchema string = `((ftp|tcp|udp|wss?|https?):\/\/)` + URLUsername string = `(\S+(:\S*)?@)` + URLPath string = `((\/|\?|#)[^\s]*)` + URLPort string = `(:(\d{1,5}))` + URLIP string = `([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))` + URLSubdomain string = `((www\.)|([a-zA-Z0-9]([-\.][-\._a-zA-Z0-9]+)*))` + URL string = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$` + SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$` + WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$` + UnixPath string = `^(/[^/\x00]*)+/?$` + Semver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$" + tagName string = "valid" +) + +// Used by IsFilePath func +const ( + // Unknown is unresolved OS type + Unknown = iota + // Win is Windows type + Win + // Unix is *nix OS types + Unix +) + +var ( + rxEmail = regexp.MustCompile(Email) + rxCreditCard = regexp.MustCompile(CreditCard) + rxISBN10 = regexp.MustCompile(ISBN10) + rxISBN13 = regexp.MustCompile(ISBN13) + rxUUID3 = regexp.MustCompile(UUID3) + rxUUID4 = regexp.MustCompile(UUID4) + rxUUID5 = regexp.MustCompile(UUID5) + rxUUID = regexp.MustCompile(UUID) + rxAlpha = regexp.MustCompile(Alpha) + rxAlphanumeric = regexp.MustCompile(Alphanumeric) + rxNumeric = regexp.MustCompile(Numeric) + rxInt = regexp.MustCompile(Int) + rxFloat = regexp.MustCompile(Float) + rxHexadecimal = regexp.MustCompile(Hexadecimal) + rxHexcolor = regexp.MustCompile(Hexcolor) + rxRGBcolor = regexp.MustCompile(RGBcolor) + rxASCII = regexp.MustCompile(ASCII) + rxPrintableASCII = regexp.MustCompile(PrintableASCII) + rxMultibyte = regexp.MustCompile(Multibyte) + rxFullWidth = regexp.MustCompile(FullWidth) + rxHalfWidth = regexp.MustCompile(HalfWidth) + rxBase64 = regexp.MustCompile(Base64) + rxDataURI = regexp.MustCompile(DataURI) + rxLatitude = regexp.MustCompile(Latitude) + rxLongitude = regexp.MustCompile(Longitude) + rxDNSName = regexp.MustCompile(DNSName) + rxURL = regexp.MustCompile(URL) + rxSSN = regexp.MustCompile(SSN) + rxWinPath = regexp.MustCompile(WinPath) + rxUnixPath = regexp.MustCompile(UnixPath) + rxSemver = regexp.MustCompile(Semver) +) diff --git a/vendor/github.com/asaskevich/govalidator/types.go b/vendor/github.com/asaskevich/govalidator/types.go new file mode 100644 index 0000000000..9a5207c588 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/types.go @@ -0,0 +1,613 @@ +package govalidator + +import ( + "reflect" + "regexp" + "sync" +) + +// Validator is a wrapper for a validator function that returns bool and accepts string. +type Validator func(str string) bool + +// CustomTypeValidator is a wrapper for validator functions that returns bool and accepts any type. +// The second parameter should be the context (in the case of validating a struct: the whole object being validated). +type CustomTypeValidator func(i interface{}, o interface{}) bool + +// ParamValidator is a wrapper for validator functions that accepts additional parameters. +type ParamValidator func(str string, params ...string) bool +type tagOptionsMap map[string]string + +// UnsupportedTypeError is a wrapper for reflect.Type +type UnsupportedTypeError struct { + Type reflect.Type +} + +// stringValues is a slice of reflect.Value holding *reflect.StringValue. +// It implements the methods to sort by string. +type stringValues []reflect.Value + +// ParamTagMap is a map of functions accept variants parameters +var ParamTagMap = map[string]ParamValidator{ + "length": ByteLength, + "range": Range, + "runelength": RuneLength, + "stringlength": StringLength, + "matches": StringMatches, + "in": isInRaw, +} + +// ParamTagRegexMap maps param tags to their respective regexes. +var ParamTagRegexMap = map[string]*regexp.Regexp{ + "range": regexp.MustCompile("^range\\((\\d+)\\|(\\d+)\\)$"), + "length": regexp.MustCompile("^length\\((\\d+)\\|(\\d+)\\)$"), + "runelength": regexp.MustCompile("^runelength\\((\\d+)\\|(\\d+)\\)$"), + "stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"), + "in": regexp.MustCompile(`^in\((.*)\)`), + "matches": regexp.MustCompile(`^matches\((.+)\)$`), +} + +type customTypeTagMap struct { + validators map[string]CustomTypeValidator + + sync.RWMutex +} + +func (tm *customTypeTagMap) Get(name string) (CustomTypeValidator, bool) { + tm.RLock() + defer tm.RUnlock() + v, ok := tm.validators[name] + return v, ok +} + +func (tm *customTypeTagMap) Set(name string, ctv CustomTypeValidator) { + tm.Lock() + defer tm.Unlock() + tm.validators[name] = ctv +} + +// CustomTypeTagMap is a map of functions that can be used as tags for ValidateStruct function. +// Use this to validate compound or custom types that need to be handled as a whole, e.g. +// `type UUID [16]byte` (this would be handled as an array of bytes). +var CustomTypeTagMap = &customTypeTagMap{validators: make(map[string]CustomTypeValidator)} + +// TagMap is a map of functions, that can be used as tags for ValidateStruct function. +var TagMap = map[string]Validator{ + "email": IsEmail, + "url": IsURL, + "dialstring": IsDialString, + "requrl": IsRequestURL, + "requri": IsRequestURI, + "alpha": IsAlpha, + "utfletter": IsUTFLetter, + "alphanum": IsAlphanumeric, + "utfletternum": IsUTFLetterNumeric, + "numeric": IsNumeric, + "utfnumeric": IsUTFNumeric, + "utfdigit": IsUTFDigit, + "hexadecimal": IsHexadecimal, + "hexcolor": IsHexcolor, + "rgbcolor": IsRGBcolor, + "lowercase": IsLowerCase, + "uppercase": IsUpperCase, + "int": IsInt, + "float": IsFloat, + "null": IsNull, + "uuid": IsUUID, + "uuidv3": IsUUIDv3, + "uuidv4": IsUUIDv4, + "uuidv5": IsUUIDv5, + "creditcard": IsCreditCard, + "isbn10": IsISBN10, + "isbn13": IsISBN13, + "json": IsJSON, + "multibyte": IsMultibyte, + "ascii": IsASCII, + "printableascii": IsPrintableASCII, + "fullwidth": IsFullWidth, + "halfwidth": IsHalfWidth, + "variablewidth": IsVariableWidth, + "base64": IsBase64, + "datauri": IsDataURI, + "ip": IsIP, + "port": IsPort, + "ipv4": IsIPv4, + "ipv6": IsIPv6, + "dns": IsDNSName, + "host": IsHost, + "mac": IsMAC, + "latitude": IsLatitude, + "longitude": IsLongitude, + "ssn": IsSSN, + "semver": IsSemver, + "rfc3339": IsRFC3339, + "ISO3166Alpha2": IsISO3166Alpha2, + "ISO3166Alpha3": IsISO3166Alpha3, + "ISO4217": IsISO4217, +} + +// ISO3166Entry stores country codes +type ISO3166Entry struct { + EnglishShortName string + FrenchShortName string + Alpha2Code string + Alpha3Code string + Numeric string +} + +//ISO3166List based on https://www.iso.org/obp/ui/#search/code/ Code Type "Officially Assigned Codes" +var ISO3166List = []ISO3166Entry{ + {"Afghanistan", "Afghanistan (l')", "AF", "AFG", "004"}, + {"Albania", "Albanie (l')", "AL", "ALB", "008"}, + {"Antarctica", "Antarctique (l')", "AQ", "ATA", "010"}, + {"Algeria", "Algérie (l')", "DZ", "DZA", "012"}, + {"American Samoa", "Samoa américaines (les)", "AS", "ASM", "016"}, + {"Andorra", "Andorre (l')", "AD", "AND", "020"}, + {"Angola", "Angola (l')", "AO", "AGO", "024"}, + {"Antigua and Barbuda", "Antigua-et-Barbuda", "AG", "ATG", "028"}, + {"Azerbaijan", "Azerbaïdjan (l')", "AZ", "AZE", "031"}, + {"Argentina", "Argentine (l')", "AR", "ARG", "032"}, + {"Australia", "Australie (l')", "AU", "AUS", "036"}, + {"Austria", "Autriche (l')", "AT", "AUT", "040"}, + {"Bahamas (the)", "Bahamas (les)", "BS", "BHS", "044"}, + {"Bahrain", "Bahreïn", "BH", "BHR", "048"}, + {"Bangladesh", "Bangladesh (le)", "BD", "BGD", "050"}, + {"Armenia", "Arménie (l')", "AM", "ARM", "051"}, + {"Barbados", "Barbade (la)", "BB", "BRB", "052"}, + {"Belgium", "Belgique (la)", "BE", "BEL", "056"}, + {"Bermuda", "Bermudes (les)", "BM", "BMU", "060"}, + {"Bhutan", "Bhoutan (le)", "BT", "BTN", "064"}, + {"Bolivia (Plurinational State of)", "Bolivie (État plurinational de)", "BO", "BOL", "068"}, + {"Bosnia and Herzegovina", "Bosnie-Herzégovine (la)", "BA", "BIH", "070"}, + {"Botswana", "Botswana (le)", "BW", "BWA", "072"}, + {"Bouvet Island", "Bouvet (l'Île)", "BV", "BVT", "074"}, + {"Brazil", "Brésil (le)", "BR", "BRA", "076"}, + {"Belize", "Belize (le)", "BZ", "BLZ", "084"}, + {"British Indian Ocean Territory (the)", "Indien (le Territoire britannique de l'océan)", "IO", "IOT", "086"}, + {"Solomon Islands", "Salomon (Îles)", "SB", "SLB", "090"}, + {"Virgin Islands (British)", "Vierges britanniques (les Îles)", "VG", "VGB", "092"}, + {"Brunei Darussalam", "Brunéi Darussalam (le)", "BN", "BRN", "096"}, + {"Bulgaria", "Bulgarie (la)", "BG", "BGR", "100"}, + {"Myanmar", "Myanmar (le)", "MM", "MMR", "104"}, + {"Burundi", "Burundi (le)", "BI", "BDI", "108"}, + {"Belarus", "Bélarus (le)", "BY", "BLR", "112"}, + {"Cambodia", "Cambodge (le)", "KH", "KHM", "116"}, + {"Cameroon", "Cameroun (le)", "CM", "CMR", "120"}, + {"Canada", "Canada (le)", "CA", "CAN", "124"}, + {"Cabo Verde", "Cabo Verde", "CV", "CPV", "132"}, + {"Cayman Islands (the)", "Caïmans (les Îles)", "KY", "CYM", "136"}, + {"Central African Republic (the)", "République centrafricaine (la)", "CF", "CAF", "140"}, + {"Sri Lanka", "Sri Lanka", "LK", "LKA", "144"}, + {"Chad", "Tchad (le)", "TD", "TCD", "148"}, + {"Chile", "Chili (le)", "CL", "CHL", "152"}, + {"China", "Chine (la)", "CN", "CHN", "156"}, + {"Taiwan (Province of China)", "Taïwan (Province de Chine)", "TW", "TWN", "158"}, + {"Christmas Island", "Christmas (l'Île)", "CX", "CXR", "162"}, + {"Cocos (Keeling) Islands (the)", "Cocos (les Îles)/ Keeling (les Îles)", "CC", "CCK", "166"}, + {"Colombia", "Colombie (la)", "CO", "COL", "170"}, + {"Comoros (the)", "Comores (les)", "KM", "COM", "174"}, + {"Mayotte", "Mayotte", "YT", "MYT", "175"}, + {"Congo (the)", "Congo (le)", "CG", "COG", "178"}, + {"Congo (the Democratic Republic of the)", "Congo (la République démocratique du)", "CD", "COD", "180"}, + {"Cook Islands (the)", "Cook (les Îles)", "CK", "COK", "184"}, + {"Costa Rica", "Costa Rica (le)", "CR", "CRI", "188"}, + {"Croatia", "Croatie (la)", "HR", "HRV", "191"}, + {"Cuba", "Cuba", "CU", "CUB", "192"}, + {"Cyprus", "Chypre", "CY", "CYP", "196"}, + {"Czech Republic (the)", "tchèque (la République)", "CZ", "CZE", "203"}, + {"Benin", "Bénin (le)", "BJ", "BEN", "204"}, + {"Denmark", "Danemark (le)", "DK", "DNK", "208"}, + {"Dominica", "Dominique (la)", "DM", "DMA", "212"}, + {"Dominican Republic (the)", "dominicaine (la République)", "DO", "DOM", "214"}, + {"Ecuador", "Équateur (l')", "EC", "ECU", "218"}, + {"El Salvador", "El Salvador", "SV", "SLV", "222"}, + {"Equatorial Guinea", "Guinée équatoriale (la)", "GQ", "GNQ", "226"}, + {"Ethiopia", "Éthiopie (l')", "ET", "ETH", "231"}, + {"Eritrea", "Érythrée (l')", "ER", "ERI", "232"}, + {"Estonia", "Estonie (l')", "EE", "EST", "233"}, + {"Faroe Islands (the)", "Féroé (les Îles)", "FO", "FRO", "234"}, + {"Falkland Islands (the) [Malvinas]", "Falkland (les Îles)/Malouines (les Îles)", "FK", "FLK", "238"}, + {"South Georgia and the South Sandwich Islands", "Géorgie du Sud-et-les Îles Sandwich du Sud (la)", "GS", "SGS", "239"}, + {"Fiji", "Fidji (les)", "FJ", "FJI", "242"}, + {"Finland", "Finlande (la)", "FI", "FIN", "246"}, + {"Åland Islands", "Åland(les Îles)", "AX", "ALA", "248"}, + {"France", "France (la)", "FR", "FRA", "250"}, + {"French Guiana", "Guyane française (la )", "GF", "GUF", "254"}, + {"French Polynesia", "Polynésie française (la)", "PF", "PYF", "258"}, + {"French Southern Territories (the)", "Terres australes françaises (les)", "TF", "ATF", "260"}, + {"Djibouti", "Djibouti", "DJ", "DJI", "262"}, + {"Gabon", "Gabon (le)", "GA", "GAB", "266"}, + {"Georgia", "Géorgie (la)", "GE", "GEO", "268"}, + {"Gambia (the)", "Gambie (la)", "GM", "GMB", "270"}, + {"Palestine, State of", "Palestine, État de", "PS", "PSE", "275"}, + {"Germany", "Allemagne (l')", "DE", "DEU", "276"}, + {"Ghana", "Ghana (le)", "GH", "GHA", "288"}, + {"Gibraltar", "Gibraltar", "GI", "GIB", "292"}, + {"Kiribati", "Kiribati", "KI", "KIR", "296"}, + {"Greece", "Grèce (la)", "GR", "GRC", "300"}, + {"Greenland", "Groenland (le)", "GL", "GRL", "304"}, + {"Grenada", "Grenade (la)", "GD", "GRD", "308"}, + {"Guadeloupe", "Guadeloupe (la)", "GP", "GLP", "312"}, + {"Guam", "Guam", "GU", "GUM", "316"}, + {"Guatemala", "Guatemala (le)", "GT", "GTM", "320"}, + {"Guinea", "Guinée (la)", "GN", "GIN", "324"}, + {"Guyana", "Guyana (le)", "GY", "GUY", "328"}, + {"Haiti", "Haïti", "HT", "HTI", "332"}, + {"Heard Island and McDonald Islands", "Heard-et-Îles MacDonald (l'Île)", "HM", "HMD", "334"}, + {"Holy See (the)", "Saint-Siège (le)", "VA", "VAT", "336"}, + {"Honduras", "Honduras (le)", "HN", "HND", "340"}, + {"Hong Kong", "Hong Kong", "HK", "HKG", "344"}, + {"Hungary", "Hongrie (la)", "HU", "HUN", "348"}, + {"Iceland", "Islande (l')", "IS", "ISL", "352"}, + {"India", "Inde (l')", "IN", "IND", "356"}, + {"Indonesia", "Indonésie (l')", "ID", "IDN", "360"}, + {"Iran (Islamic Republic of)", "Iran (République Islamique d')", "IR", "IRN", "364"}, + {"Iraq", "Iraq (l')", "IQ", "IRQ", "368"}, + {"Ireland", "Irlande (l')", "IE", "IRL", "372"}, + {"Israel", "Israël", "IL", "ISR", "376"}, + {"Italy", "Italie (l')", "IT", "ITA", "380"}, + {"Côte d'Ivoire", "Côte d'Ivoire (la)", "CI", "CIV", "384"}, + {"Jamaica", "Jamaïque (la)", "JM", "JAM", "388"}, + {"Japan", "Japon (le)", "JP", "JPN", "392"}, + {"Kazakhstan", "Kazakhstan (le)", "KZ", "KAZ", "398"}, + {"Jordan", "Jordanie (la)", "JO", "JOR", "400"}, + {"Kenya", "Kenya (le)", "KE", "KEN", "404"}, + {"Korea (the Democratic People's Republic of)", "Corée (la République populaire démocratique de)", "KP", "PRK", "408"}, + {"Korea (the Republic of)", "Corée (la République de)", "KR", "KOR", "410"}, + {"Kuwait", "Koweït (le)", "KW", "KWT", "414"}, + {"Kyrgyzstan", "Kirghizistan (le)", "KG", "KGZ", "417"}, + {"Lao People's Democratic Republic (the)", "Lao, République démocratique populaire", "LA", "LAO", "418"}, + {"Lebanon", "Liban (le)", "LB", "LBN", "422"}, + {"Lesotho", "Lesotho (le)", "LS", "LSO", "426"}, + {"Latvia", "Lettonie (la)", "LV", "LVA", "428"}, + {"Liberia", "Libéria (le)", "LR", "LBR", "430"}, + {"Libya", "Libye (la)", "LY", "LBY", "434"}, + {"Liechtenstein", "Liechtenstein (le)", "LI", "LIE", "438"}, + {"Lithuania", "Lituanie (la)", "LT", "LTU", "440"}, + {"Luxembourg", "Luxembourg (le)", "LU", "LUX", "442"}, + {"Macao", "Macao", "MO", "MAC", "446"}, + {"Madagascar", "Madagascar", "MG", "MDG", "450"}, + {"Malawi", "Malawi (le)", "MW", "MWI", "454"}, + {"Malaysia", "Malaisie (la)", "MY", "MYS", "458"}, + {"Maldives", "Maldives (les)", "MV", "MDV", "462"}, + {"Mali", "Mali (le)", "ML", "MLI", "466"}, + {"Malta", "Malte", "MT", "MLT", "470"}, + {"Martinique", "Martinique (la)", "MQ", "MTQ", "474"}, + {"Mauritania", "Mauritanie (la)", "MR", "MRT", "478"}, + {"Mauritius", "Maurice", "MU", "MUS", "480"}, + {"Mexico", "Mexique (le)", "MX", "MEX", "484"}, + {"Monaco", "Monaco", "MC", "MCO", "492"}, + {"Mongolia", "Mongolie (la)", "MN", "MNG", "496"}, + {"Moldova (the Republic of)", "Moldova , République de", "MD", "MDA", "498"}, + {"Montenegro", "Monténégro (le)", "ME", "MNE", "499"}, + {"Montserrat", "Montserrat", "MS", "MSR", "500"}, + {"Morocco", "Maroc (le)", "MA", "MAR", "504"}, + {"Mozambique", "Mozambique (le)", "MZ", "MOZ", "508"}, + {"Oman", "Oman", "OM", "OMN", "512"}, + {"Namibia", "Namibie (la)", "NA", "NAM", "516"}, + {"Nauru", "Nauru", "NR", "NRU", "520"}, + {"Nepal", "Népal (le)", "NP", "NPL", "524"}, + {"Netherlands (the)", "Pays-Bas (les)", "NL", "NLD", "528"}, + {"Curaçao", "Curaçao", "CW", "CUW", "531"}, + {"Aruba", "Aruba", "AW", "ABW", "533"}, + {"Sint Maarten (Dutch part)", "Saint-Martin (partie néerlandaise)", "SX", "SXM", "534"}, + {"Bonaire, Sint Eustatius and Saba", "Bonaire, Saint-Eustache et Saba", "BQ", "BES", "535"}, + {"New Caledonia", "Nouvelle-Calédonie (la)", "NC", "NCL", "540"}, + {"Vanuatu", "Vanuatu (le)", "VU", "VUT", "548"}, + {"New Zealand", "Nouvelle-Zélande (la)", "NZ", "NZL", "554"}, + {"Nicaragua", "Nicaragua (le)", "NI", "NIC", "558"}, + {"Niger (the)", "Niger (le)", "NE", "NER", "562"}, + {"Nigeria", "Nigéria (le)", "NG", "NGA", "566"}, + {"Niue", "Niue", "NU", "NIU", "570"}, + {"Norfolk Island", "Norfolk (l'Île)", "NF", "NFK", "574"}, + {"Norway", "Norvège (la)", "NO", "NOR", "578"}, + {"Northern Mariana Islands (the)", "Mariannes du Nord (les Îles)", "MP", "MNP", "580"}, + {"United States Minor Outlying Islands (the)", "Îles mineures éloignées des États-Unis (les)", "UM", "UMI", "581"}, + {"Micronesia (Federated States of)", "Micronésie (États fédérés de)", "FM", "FSM", "583"}, + {"Marshall Islands (the)", "Marshall (Îles)", "MH", "MHL", "584"}, + {"Palau", "Palaos (les)", "PW", "PLW", "585"}, + {"Pakistan", "Pakistan (le)", "PK", "PAK", "586"}, + {"Panama", "Panama (le)", "PA", "PAN", "591"}, + {"Papua New Guinea", "Papouasie-Nouvelle-Guinée (la)", "PG", "PNG", "598"}, + {"Paraguay", "Paraguay (le)", "PY", "PRY", "600"}, + {"Peru", "Pérou (le)", "PE", "PER", "604"}, + {"Philippines (the)", "Philippines (les)", "PH", "PHL", "608"}, + {"Pitcairn", "Pitcairn", "PN", "PCN", "612"}, + {"Poland", "Pologne (la)", "PL", "POL", "616"}, + {"Portugal", "Portugal (le)", "PT", "PRT", "620"}, + {"Guinea-Bissau", "Guinée-Bissau (la)", "GW", "GNB", "624"}, + {"Timor-Leste", "Timor-Leste (le)", "TL", "TLS", "626"}, + {"Puerto Rico", "Porto Rico", "PR", "PRI", "630"}, + {"Qatar", "Qatar (le)", "QA", "QAT", "634"}, + {"Réunion", "Réunion (La)", "RE", "REU", "638"}, + {"Romania", "Roumanie (la)", "RO", "ROU", "642"}, + {"Russian Federation (the)", "Russie (la Fédération de)", "RU", "RUS", "643"}, + {"Rwanda", "Rwanda (le)", "RW", "RWA", "646"}, + {"Saint Barthélemy", "Saint-Barthélemy", "BL", "BLM", "652"}, + {"Saint Helena, Ascension and Tristan da Cunha", "Sainte-Hélène, Ascension et Tristan da Cunha", "SH", "SHN", "654"}, + {"Saint Kitts and Nevis", "Saint-Kitts-et-Nevis", "KN", "KNA", "659"}, + {"Anguilla", "Anguilla", "AI", "AIA", "660"}, + {"Saint Lucia", "Sainte-Lucie", "LC", "LCA", "662"}, + {"Saint Martin (French part)", "Saint-Martin (partie française)", "MF", "MAF", "663"}, + {"Saint Pierre and Miquelon", "Saint-Pierre-et-Miquelon", "PM", "SPM", "666"}, + {"Saint Vincent and the Grenadines", "Saint-Vincent-et-les Grenadines", "VC", "VCT", "670"}, + {"San Marino", "Saint-Marin", "SM", "SMR", "674"}, + {"Sao Tome and Principe", "Sao Tomé-et-Principe", "ST", "STP", "678"}, + {"Saudi Arabia", "Arabie saoudite (l')", "SA", "SAU", "682"}, + {"Senegal", "Sénégal (le)", "SN", "SEN", "686"}, + {"Serbia", "Serbie (la)", "RS", "SRB", "688"}, + {"Seychelles", "Seychelles (les)", "SC", "SYC", "690"}, + {"Sierra Leone", "Sierra Leone (la)", "SL", "SLE", "694"}, + {"Singapore", "Singapour", "SG", "SGP", "702"}, + {"Slovakia", "Slovaquie (la)", "SK", "SVK", "703"}, + {"Viet Nam", "Viet Nam (le)", "VN", "VNM", "704"}, + {"Slovenia", "Slovénie (la)", "SI", "SVN", "705"}, + {"Somalia", "Somalie (la)", "SO", "SOM", "706"}, + {"South Africa", "Afrique du Sud (l')", "ZA", "ZAF", "710"}, + {"Zimbabwe", "Zimbabwe (le)", "ZW", "ZWE", "716"}, + {"Spain", "Espagne (l')", "ES", "ESP", "724"}, + {"South Sudan", "Soudan du Sud (le)", "SS", "SSD", "728"}, + {"Sudan (the)", "Soudan (le)", "SD", "SDN", "729"}, + {"Western Sahara*", "Sahara occidental (le)*", "EH", "ESH", "732"}, + {"Suriname", "Suriname (le)", "SR", "SUR", "740"}, + {"Svalbard and Jan Mayen", "Svalbard et l'Île Jan Mayen (le)", "SJ", "SJM", "744"}, + {"Swaziland", "Swaziland (le)", "SZ", "SWZ", "748"}, + {"Sweden", "Suède (la)", "SE", "SWE", "752"}, + {"Switzerland", "Suisse (la)", "CH", "CHE", "756"}, + {"Syrian Arab Republic", "République arabe syrienne (la)", "SY", "SYR", "760"}, + {"Tajikistan", "Tadjikistan (le)", "TJ", "TJK", "762"}, + {"Thailand", "Thaïlande (la)", "TH", "THA", "764"}, + {"Togo", "Togo (le)", "TG", "TGO", "768"}, + {"Tokelau", "Tokelau (les)", "TK", "TKL", "772"}, + {"Tonga", "Tonga (les)", "TO", "TON", "776"}, + {"Trinidad and Tobago", "Trinité-et-Tobago (la)", "TT", "TTO", "780"}, + {"United Arab Emirates (the)", "Émirats arabes unis (les)", "AE", "ARE", "784"}, + {"Tunisia", "Tunisie (la)", "TN", "TUN", "788"}, + {"Turkey", "Turquie (la)", "TR", "TUR", "792"}, + {"Turkmenistan", "Turkménistan (le)", "TM", "TKM", "795"}, + {"Turks and Caicos Islands (the)", "Turks-et-Caïcos (les Îles)", "TC", "TCA", "796"}, + {"Tuvalu", "Tuvalu (les)", "TV", "TUV", "798"}, + {"Uganda", "Ouganda (l')", "UG", "UGA", "800"}, + {"Ukraine", "Ukraine (l')", "UA", "UKR", "804"}, + {"Macedonia (the former Yugoslav Republic of)", "Macédoine (l'ex‑République yougoslave de)", "MK", "MKD", "807"}, + {"Egypt", "Égypte (l')", "EG", "EGY", "818"}, + {"United Kingdom of Great Britain and Northern Ireland (the)", "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord (le)", "GB", "GBR", "826"}, + {"Guernsey", "Guernesey", "GG", "GGY", "831"}, + {"Jersey", "Jersey", "JE", "JEY", "832"}, + {"Isle of Man", "Île de Man", "IM", "IMN", "833"}, + {"Tanzania, United Republic of", "Tanzanie, République-Unie de", "TZ", "TZA", "834"}, + {"United States of America (the)", "États-Unis d'Amérique (les)", "US", "USA", "840"}, + {"Virgin Islands (U.S.)", "Vierges des États-Unis (les Îles)", "VI", "VIR", "850"}, + {"Burkina Faso", "Burkina Faso (le)", "BF", "BFA", "854"}, + {"Uruguay", "Uruguay (l')", "UY", "URY", "858"}, + {"Uzbekistan", "Ouzbékistan (l')", "UZ", "UZB", "860"}, + {"Venezuela (Bolivarian Republic of)", "Venezuela (République bolivarienne du)", "VE", "VEN", "862"}, + {"Wallis and Futuna", "Wallis-et-Futuna", "WF", "WLF", "876"}, + {"Samoa", "Samoa (le)", "WS", "WSM", "882"}, + {"Yemen", "Yémen (le)", "YE", "YEM", "887"}, + {"Zambia", "Zambie (la)", "ZM", "ZMB", "894"}, +} + +// ISO4217List is the list of ISO currency codes +var ISO4217List = []string{ + "AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN", + "BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BOV", "BRL", "BSD", "BTN", "BWP", "BYN", "BZD", + "CAD", "CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU", "CRC", "CUC", "CUP", "CVE", "CZK", + "DJF", "DKK", "DOP", "DZD", + "EGP", "ERN", "ETB", "EUR", + "FJD", "FKP", + "GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD", + "HKD", "HNL", "HRK", "HTG", "HUF", + "IDR", "ILS", "INR", "IQD", "IRR", "ISK", + "JMD", "JOD", "JPY", + "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT", + "LAK", "LBP", "LKR", "LRD", "LSL", "LYD", + "MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRO", "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZN", + "NAD", "NGN", "NIO", "NOK", "NPR", "NZD", + "OMR", + "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG", + "QAR", + "RON", "RSD", "RUB", "RWF", + "SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLL", "SOS", "SRD", "SSP", "STD", "SVC", "SYP", "SZL", + "THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS", + "UAH", "UGX", "USD", "USN", "UYI", "UYU", "UZS", + "VEF", "VND", "VUV", + "WST", + "XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XOF", "XPD", "XPF", "XPT", "XSU", "XTS", "XUA", "XXX", + "YER", + "ZAR", "ZMW", "ZWL", +} + +// ISO693Entry stores ISO language codes +type ISO693Entry struct { + Alpha3bCode string + Alpha2Code string + English string +} + +//ISO693List based on http://data.okfn.org/data/core/language-codes/r/language-codes-3b2.json +var ISO693List = []ISO693Entry{ + {Alpha3bCode: "aar", Alpha2Code: "aa", English: "Afar"}, + {Alpha3bCode: "abk", Alpha2Code: "ab", English: "Abkhazian"}, + {Alpha3bCode: "afr", Alpha2Code: "af", English: "Afrikaans"}, + {Alpha3bCode: "aka", Alpha2Code: "ak", English: "Akan"}, + {Alpha3bCode: "alb", Alpha2Code: "sq", English: "Albanian"}, + {Alpha3bCode: "amh", Alpha2Code: "am", English: "Amharic"}, + {Alpha3bCode: "ara", Alpha2Code: "ar", English: "Arabic"}, + {Alpha3bCode: "arg", Alpha2Code: "an", English: "Aragonese"}, + {Alpha3bCode: "arm", Alpha2Code: "hy", English: "Armenian"}, + {Alpha3bCode: "asm", Alpha2Code: "as", English: "Assamese"}, + {Alpha3bCode: "ava", Alpha2Code: "av", English: "Avaric"}, + {Alpha3bCode: "ave", Alpha2Code: "ae", English: "Avestan"}, + {Alpha3bCode: "aym", Alpha2Code: "ay", English: "Aymara"}, + {Alpha3bCode: "aze", Alpha2Code: "az", English: "Azerbaijani"}, + {Alpha3bCode: "bak", Alpha2Code: "ba", English: "Bashkir"}, + {Alpha3bCode: "bam", Alpha2Code: "bm", English: "Bambara"}, + {Alpha3bCode: "baq", Alpha2Code: "eu", English: "Basque"}, + {Alpha3bCode: "bel", Alpha2Code: "be", English: "Belarusian"}, + {Alpha3bCode: "ben", Alpha2Code: "bn", English: "Bengali"}, + {Alpha3bCode: "bih", Alpha2Code: "bh", English: "Bihari languages"}, + {Alpha3bCode: "bis", Alpha2Code: "bi", English: "Bislama"}, + {Alpha3bCode: "bos", Alpha2Code: "bs", English: "Bosnian"}, + {Alpha3bCode: "bre", Alpha2Code: "br", English: "Breton"}, + {Alpha3bCode: "bul", Alpha2Code: "bg", English: "Bulgarian"}, + {Alpha3bCode: "bur", Alpha2Code: "my", English: "Burmese"}, + {Alpha3bCode: "cat", Alpha2Code: "ca", English: "Catalan; Valencian"}, + {Alpha3bCode: "cha", Alpha2Code: "ch", English: "Chamorro"}, + {Alpha3bCode: "che", Alpha2Code: "ce", English: "Chechen"}, + {Alpha3bCode: "chi", Alpha2Code: "zh", English: "Chinese"}, + {Alpha3bCode: "chu", Alpha2Code: "cu", English: "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic"}, + {Alpha3bCode: "chv", Alpha2Code: "cv", English: "Chuvash"}, + {Alpha3bCode: "cor", Alpha2Code: "kw", English: "Cornish"}, + {Alpha3bCode: "cos", Alpha2Code: "co", English: "Corsican"}, + {Alpha3bCode: "cre", Alpha2Code: "cr", English: "Cree"}, + {Alpha3bCode: "cze", Alpha2Code: "cs", English: "Czech"}, + {Alpha3bCode: "dan", Alpha2Code: "da", English: "Danish"}, + {Alpha3bCode: "div", Alpha2Code: "dv", English: "Divehi; Dhivehi; Maldivian"}, + {Alpha3bCode: "dut", Alpha2Code: "nl", English: "Dutch; Flemish"}, + {Alpha3bCode: "dzo", Alpha2Code: "dz", English: "Dzongkha"}, + {Alpha3bCode: "eng", Alpha2Code: "en", English: "English"}, + {Alpha3bCode: "epo", Alpha2Code: "eo", English: "Esperanto"}, + {Alpha3bCode: "est", Alpha2Code: "et", English: "Estonian"}, + {Alpha3bCode: "ewe", Alpha2Code: "ee", English: "Ewe"}, + {Alpha3bCode: "fao", Alpha2Code: "fo", English: "Faroese"}, + {Alpha3bCode: "fij", Alpha2Code: "fj", English: "Fijian"}, + {Alpha3bCode: "fin", Alpha2Code: "fi", English: "Finnish"}, + {Alpha3bCode: "fre", Alpha2Code: "fr", English: "French"}, + {Alpha3bCode: "fry", Alpha2Code: "fy", English: "Western Frisian"}, + {Alpha3bCode: "ful", Alpha2Code: "ff", English: "Fulah"}, + {Alpha3bCode: "geo", Alpha2Code: "ka", English: "Georgian"}, + {Alpha3bCode: "ger", Alpha2Code: "de", English: "German"}, + {Alpha3bCode: "gla", Alpha2Code: "gd", English: "Gaelic; Scottish Gaelic"}, + {Alpha3bCode: "gle", Alpha2Code: "ga", English: "Irish"}, + {Alpha3bCode: "glg", Alpha2Code: "gl", English: "Galician"}, + {Alpha3bCode: "glv", Alpha2Code: "gv", English: "Manx"}, + {Alpha3bCode: "gre", Alpha2Code: "el", English: "Greek, Modern (1453-)"}, + {Alpha3bCode: "grn", Alpha2Code: "gn", English: "Guarani"}, + {Alpha3bCode: "guj", Alpha2Code: "gu", English: "Gujarati"}, + {Alpha3bCode: "hat", Alpha2Code: "ht", English: "Haitian; Haitian Creole"}, + {Alpha3bCode: "hau", Alpha2Code: "ha", English: "Hausa"}, + {Alpha3bCode: "heb", Alpha2Code: "he", English: "Hebrew"}, + {Alpha3bCode: "her", Alpha2Code: "hz", English: "Herero"}, + {Alpha3bCode: "hin", Alpha2Code: "hi", English: "Hindi"}, + {Alpha3bCode: "hmo", Alpha2Code: "ho", English: "Hiri Motu"}, + {Alpha3bCode: "hrv", Alpha2Code: "hr", English: "Croatian"}, + {Alpha3bCode: "hun", Alpha2Code: "hu", English: "Hungarian"}, + {Alpha3bCode: "ibo", Alpha2Code: "ig", English: "Igbo"}, + {Alpha3bCode: "ice", Alpha2Code: "is", English: "Icelandic"}, + {Alpha3bCode: "ido", Alpha2Code: "io", English: "Ido"}, + {Alpha3bCode: "iii", Alpha2Code: "ii", English: "Sichuan Yi; Nuosu"}, + {Alpha3bCode: "iku", Alpha2Code: "iu", English: "Inuktitut"}, + {Alpha3bCode: "ile", Alpha2Code: "ie", English: "Interlingue; Occidental"}, + {Alpha3bCode: "ina", Alpha2Code: "ia", English: "Interlingua (International Auxiliary Language Association)"}, + {Alpha3bCode: "ind", Alpha2Code: "id", English: "Indonesian"}, + {Alpha3bCode: "ipk", Alpha2Code: "ik", English: "Inupiaq"}, + {Alpha3bCode: "ita", Alpha2Code: "it", English: "Italian"}, + {Alpha3bCode: "jav", Alpha2Code: "jv", English: "Javanese"}, + {Alpha3bCode: "jpn", Alpha2Code: "ja", English: "Japanese"}, + {Alpha3bCode: "kal", Alpha2Code: "kl", English: "Kalaallisut; Greenlandic"}, + {Alpha3bCode: "kan", Alpha2Code: "kn", English: "Kannada"}, + {Alpha3bCode: "kas", Alpha2Code: "ks", English: "Kashmiri"}, + {Alpha3bCode: "kau", Alpha2Code: "kr", English: "Kanuri"}, + {Alpha3bCode: "kaz", Alpha2Code: "kk", English: "Kazakh"}, + {Alpha3bCode: "khm", Alpha2Code: "km", English: "Central Khmer"}, + {Alpha3bCode: "kik", Alpha2Code: "ki", English: "Kikuyu; Gikuyu"}, + {Alpha3bCode: "kin", Alpha2Code: "rw", English: "Kinyarwanda"}, + {Alpha3bCode: "kir", Alpha2Code: "ky", English: "Kirghiz; Kyrgyz"}, + {Alpha3bCode: "kom", Alpha2Code: "kv", English: "Komi"}, + {Alpha3bCode: "kon", Alpha2Code: "kg", English: "Kongo"}, + {Alpha3bCode: "kor", Alpha2Code: "ko", English: "Korean"}, + {Alpha3bCode: "kua", Alpha2Code: "kj", English: "Kuanyama; Kwanyama"}, + {Alpha3bCode: "kur", Alpha2Code: "ku", English: "Kurdish"}, + {Alpha3bCode: "lao", Alpha2Code: "lo", English: "Lao"}, + {Alpha3bCode: "lat", Alpha2Code: "la", English: "Latin"}, + {Alpha3bCode: "lav", Alpha2Code: "lv", English: "Latvian"}, + {Alpha3bCode: "lim", Alpha2Code: "li", English: "Limburgan; Limburger; Limburgish"}, + {Alpha3bCode: "lin", Alpha2Code: "ln", English: "Lingala"}, + {Alpha3bCode: "lit", Alpha2Code: "lt", English: "Lithuanian"}, + {Alpha3bCode: "ltz", Alpha2Code: "lb", English: "Luxembourgish; Letzeburgesch"}, + {Alpha3bCode: "lub", Alpha2Code: "lu", English: "Luba-Katanga"}, + {Alpha3bCode: "lug", Alpha2Code: "lg", English: "Ganda"}, + {Alpha3bCode: "mac", Alpha2Code: "mk", English: "Macedonian"}, + {Alpha3bCode: "mah", Alpha2Code: "mh", English: "Marshallese"}, + {Alpha3bCode: "mal", Alpha2Code: "ml", English: "Malayalam"}, + {Alpha3bCode: "mao", Alpha2Code: "mi", English: "Maori"}, + {Alpha3bCode: "mar", Alpha2Code: "mr", English: "Marathi"}, + {Alpha3bCode: "may", Alpha2Code: "ms", English: "Malay"}, + {Alpha3bCode: "mlg", Alpha2Code: "mg", English: "Malagasy"}, + {Alpha3bCode: "mlt", Alpha2Code: "mt", English: "Maltese"}, + {Alpha3bCode: "mon", Alpha2Code: "mn", English: "Mongolian"}, + {Alpha3bCode: "nau", Alpha2Code: "na", English: "Nauru"}, + {Alpha3bCode: "nav", Alpha2Code: "nv", English: "Navajo; Navaho"}, + {Alpha3bCode: "nbl", Alpha2Code: "nr", English: "Ndebele, South; South Ndebele"}, + {Alpha3bCode: "nde", Alpha2Code: "nd", English: "Ndebele, North; North Ndebele"}, + {Alpha3bCode: "ndo", Alpha2Code: "ng", English: "Ndonga"}, + {Alpha3bCode: "nep", Alpha2Code: "ne", English: "Nepali"}, + {Alpha3bCode: "nno", Alpha2Code: "nn", English: "Norwegian Nynorsk; Nynorsk, Norwegian"}, + {Alpha3bCode: "nob", Alpha2Code: "nb", English: "Bokmål, Norwegian; Norwegian Bokmål"}, + {Alpha3bCode: "nor", Alpha2Code: "no", English: "Norwegian"}, + {Alpha3bCode: "nya", Alpha2Code: "ny", English: "Chichewa; Chewa; Nyanja"}, + {Alpha3bCode: "oci", Alpha2Code: "oc", English: "Occitan (post 1500); Provençal"}, + {Alpha3bCode: "oji", Alpha2Code: "oj", English: "Ojibwa"}, + {Alpha3bCode: "ori", Alpha2Code: "or", English: "Oriya"}, + {Alpha3bCode: "orm", Alpha2Code: "om", English: "Oromo"}, + {Alpha3bCode: "oss", Alpha2Code: "os", English: "Ossetian; Ossetic"}, + {Alpha3bCode: "pan", Alpha2Code: "pa", English: "Panjabi; Punjabi"}, + {Alpha3bCode: "per", Alpha2Code: "fa", English: "Persian"}, + {Alpha3bCode: "pli", Alpha2Code: "pi", English: "Pali"}, + {Alpha3bCode: "pol", Alpha2Code: "pl", English: "Polish"}, + {Alpha3bCode: "por", Alpha2Code: "pt", English: "Portuguese"}, + {Alpha3bCode: "pus", Alpha2Code: "ps", English: "Pushto; Pashto"}, + {Alpha3bCode: "que", Alpha2Code: "qu", English: "Quechua"}, + {Alpha3bCode: "roh", Alpha2Code: "rm", English: "Romansh"}, + {Alpha3bCode: "rum", Alpha2Code: "ro", English: "Romanian; Moldavian; Moldovan"}, + {Alpha3bCode: "run", Alpha2Code: "rn", English: "Rundi"}, + {Alpha3bCode: "rus", Alpha2Code: "ru", English: "Russian"}, + {Alpha3bCode: "sag", Alpha2Code: "sg", English: "Sango"}, + {Alpha3bCode: "san", Alpha2Code: "sa", English: "Sanskrit"}, + {Alpha3bCode: "sin", Alpha2Code: "si", English: "Sinhala; Sinhalese"}, + {Alpha3bCode: "slo", Alpha2Code: "sk", English: "Slovak"}, + {Alpha3bCode: "slv", Alpha2Code: "sl", English: "Slovenian"}, + {Alpha3bCode: "sme", Alpha2Code: "se", English: "Northern Sami"}, + {Alpha3bCode: "smo", Alpha2Code: "sm", English: "Samoan"}, + {Alpha3bCode: "sna", Alpha2Code: "sn", English: "Shona"}, + {Alpha3bCode: "snd", Alpha2Code: "sd", English: "Sindhi"}, + {Alpha3bCode: "som", Alpha2Code: "so", English: "Somali"}, + {Alpha3bCode: "sot", Alpha2Code: "st", English: "Sotho, Southern"}, + {Alpha3bCode: "spa", Alpha2Code: "es", English: "Spanish; Castilian"}, + {Alpha3bCode: "srd", Alpha2Code: "sc", English: "Sardinian"}, + {Alpha3bCode: "srp", Alpha2Code: "sr", English: "Serbian"}, + {Alpha3bCode: "ssw", Alpha2Code: "ss", English: "Swati"}, + {Alpha3bCode: "sun", Alpha2Code: "su", English: "Sundanese"}, + {Alpha3bCode: "swa", Alpha2Code: "sw", English: "Swahili"}, + {Alpha3bCode: "swe", Alpha2Code: "sv", English: "Swedish"}, + {Alpha3bCode: "tah", Alpha2Code: "ty", English: "Tahitian"}, + {Alpha3bCode: "tam", Alpha2Code: "ta", English: "Tamil"}, + {Alpha3bCode: "tat", Alpha2Code: "tt", English: "Tatar"}, + {Alpha3bCode: "tel", Alpha2Code: "te", English: "Telugu"}, + {Alpha3bCode: "tgk", Alpha2Code: "tg", English: "Tajik"}, + {Alpha3bCode: "tgl", Alpha2Code: "tl", English: "Tagalog"}, + {Alpha3bCode: "tha", Alpha2Code: "th", English: "Thai"}, + {Alpha3bCode: "tib", Alpha2Code: "bo", English: "Tibetan"}, + {Alpha3bCode: "tir", Alpha2Code: "ti", English: "Tigrinya"}, + {Alpha3bCode: "ton", Alpha2Code: "to", English: "Tonga (Tonga Islands)"}, + {Alpha3bCode: "tsn", Alpha2Code: "tn", English: "Tswana"}, + {Alpha3bCode: "tso", Alpha2Code: "ts", English: "Tsonga"}, + {Alpha3bCode: "tuk", Alpha2Code: "tk", English: "Turkmen"}, + {Alpha3bCode: "tur", Alpha2Code: "tr", English: "Turkish"}, + {Alpha3bCode: "twi", Alpha2Code: "tw", English: "Twi"}, + {Alpha3bCode: "uig", Alpha2Code: "ug", English: "Uighur; Uyghur"}, + {Alpha3bCode: "ukr", Alpha2Code: "uk", English: "Ukrainian"}, + {Alpha3bCode: "urd", Alpha2Code: "ur", English: "Urdu"}, + {Alpha3bCode: "uzb", Alpha2Code: "uz", English: "Uzbek"}, + {Alpha3bCode: "ven", Alpha2Code: "ve", English: "Venda"}, + {Alpha3bCode: "vie", Alpha2Code: "vi", English: "Vietnamese"}, + {Alpha3bCode: "vol", Alpha2Code: "vo", English: "Volapük"}, + {Alpha3bCode: "wel", Alpha2Code: "cy", English: "Welsh"}, + {Alpha3bCode: "wln", Alpha2Code: "wa", English: "Walloon"}, + {Alpha3bCode: "wol", Alpha2Code: "wo", English: "Wolof"}, + {Alpha3bCode: "xho", Alpha2Code: "xh", English: "Xhosa"}, + {Alpha3bCode: "yid", Alpha2Code: "yi", English: "Yiddish"}, + {Alpha3bCode: "yor", Alpha2Code: "yo", English: "Yoruba"}, + {Alpha3bCode: "zha", Alpha2Code: "za", English: "Zhuang; Chuang"}, + {Alpha3bCode: "zul", Alpha2Code: "zu", English: "Zulu"}, +} diff --git a/vendor/github.com/asaskevich/govalidator/utils.go b/vendor/github.com/asaskevich/govalidator/utils.go new file mode 100644 index 0000000000..888c12751c --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/utils.go @@ -0,0 +1,262 @@ +package govalidator + +import ( + "errors" + "fmt" + "html" + "math" + "path" + "regexp" + "strings" + "unicode" + "unicode/utf8" +) + +// Contains check if the string contains the substring. +func Contains(str, substring string) bool { + return strings.Contains(str, substring) +} + +// Matches check if string matches the pattern (pattern is regular expression) +// In case of error return false +func Matches(str, pattern string) bool { + match, _ := regexp.MatchString(pattern, str) + return match +} + +// LeftTrim trim characters from the left-side of the input. +// If second argument is empty, it's will be remove leading spaces. +func LeftTrim(str, chars string) string { + if chars == "" { + return strings.TrimLeftFunc(str, unicode.IsSpace) + } + r, _ := regexp.Compile("^[" + chars + "]+") + return r.ReplaceAllString(str, "") +} + +// RightTrim trim characters from the right-side of the input. +// If second argument is empty, it's will be remove spaces. +func RightTrim(str, chars string) string { + if chars == "" { + return strings.TrimRightFunc(str, unicode.IsSpace) + } + r, _ := regexp.Compile("[" + chars + "]+$") + return r.ReplaceAllString(str, "") +} + +// Trim trim characters from both sides of the input. +// If second argument is empty, it's will be remove spaces. +func Trim(str, chars string) string { + return LeftTrim(RightTrim(str, chars), chars) +} + +// WhiteList remove characters that do not appear in the whitelist. +func WhiteList(str, chars string) string { + pattern := "[^" + chars + "]+" + r, _ := regexp.Compile(pattern) + return r.ReplaceAllString(str, "") +} + +// BlackList remove characters that appear in the blacklist. +func BlackList(str, chars string) string { + pattern := "[" + chars + "]+" + r, _ := regexp.Compile(pattern) + return r.ReplaceAllString(str, "") +} + +// StripLow remove characters with a numerical value < 32 and 127, mostly control characters. +// If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD). +func StripLow(str string, keepNewLines bool) string { + chars := "" + if keepNewLines { + chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F" + } else { + chars = "\x00-\x1F\x7F" + } + return BlackList(str, chars) +} + +// ReplacePattern replace regular expression pattern in string +func ReplacePattern(str, pattern, replace string) string { + r, _ := regexp.Compile(pattern) + return r.ReplaceAllString(str, replace) +} + +// Escape replace <, >, & and " with HTML entities. +var Escape = html.EscapeString + +func addSegment(inrune, segment []rune) []rune { + if len(segment) == 0 { + return inrune + } + if len(inrune) != 0 { + inrune = append(inrune, '_') + } + inrune = append(inrune, segment...) + return inrune +} + +// UnderscoreToCamelCase converts from underscore separated form to camel case form. +// Ex.: my_func => MyFunc +func UnderscoreToCamelCase(s string) string { + return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1) +} + +// CamelCaseToUnderscore converts from camel case form to underscore separated form. +// Ex.: MyFunc => my_func +func CamelCaseToUnderscore(str string) string { + var output []rune + var segment []rune + for _, r := range str { + if !unicode.IsLower(r) { + output = addSegment(output, segment) + segment = nil + } + segment = append(segment, unicode.ToLower(r)) + } + output = addSegment(output, segment) + return string(output) +} + +// Reverse return reversed string +func Reverse(s string) string { + r := []rune(s) + for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 { + r[i], r[j] = r[j], r[i] + } + return string(r) +} + +// GetLines split string by "\n" and return array of lines +func GetLines(s string) []string { + return strings.Split(s, "\n") +} + +// GetLine return specified line of multiline string +func GetLine(s string, index int) (string, error) { + lines := GetLines(s) + if index < 0 || index >= len(lines) { + return "", errors.New("line index out of bounds") + } + return lines[index], nil +} + +// RemoveTags remove all tags from HTML string +func RemoveTags(s string) string { + return ReplacePattern(s, "<[^>]*>", "") +} + +// SafeFileName return safe string that can be used in file names +func SafeFileName(str string) string { + name := strings.ToLower(str) + name = path.Clean(path.Base(name)) + name = strings.Trim(name, " ") + separators, err := regexp.Compile(`[ &_=+:]`) + if err == nil { + name = separators.ReplaceAllString(name, "-") + } + legal, err := regexp.Compile(`[^[:alnum:]-.]`) + if err == nil { + name = legal.ReplaceAllString(name, "") + } + for strings.Contains(name, "--") { + name = strings.Replace(name, "--", "-", -1) + } + return name +} + +// NormalizeEmail canonicalize an email address. +// The local part of the email address is lowercased for all domains; the hostname is always lowercased and +// the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail). +// Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and +// are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are +// normalized to @gmail.com. +func NormalizeEmail(str string) (string, error) { + if !IsEmail(str) { + return "", fmt.Errorf("%s is not an email", str) + } + parts := strings.Split(str, "@") + parts[0] = strings.ToLower(parts[0]) + parts[1] = strings.ToLower(parts[1]) + if parts[1] == "gmail.com" || parts[1] == "googlemail.com" { + parts[1] = "gmail.com" + parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0] + } + return strings.Join(parts, "@"), nil +} + +// Truncate a string to the closest length without breaking words. +func Truncate(str string, length int, ending string) string { + var aftstr, befstr string + if len(str) > length { + words := strings.Fields(str) + before, present := 0, 0 + for i := range words { + befstr = aftstr + before = present + aftstr = aftstr + words[i] + " " + present = len(aftstr) + if present > length && i != 0 { + if (length - before) < (present - length) { + return Trim(befstr, " /\\.,\"'#!?&@+-") + ending + } + return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending + } + } + } + + return str +} + +// PadLeft pad left side of string if size of string is less then indicated pad length +func PadLeft(str string, padStr string, padLen int) string { + return buildPadStr(str, padStr, padLen, true, false) +} + +// PadRight pad right side of string if size of string is less then indicated pad length +func PadRight(str string, padStr string, padLen int) string { + return buildPadStr(str, padStr, padLen, false, true) +} + +// PadBoth pad sides of string if size of string is less then indicated pad length +func PadBoth(str string, padStr string, padLen int) string { + return buildPadStr(str, padStr, padLen, true, true) +} + +// PadString either left, right or both sides, not the padding string can be unicode and more then one +// character +func buildPadStr(str string, padStr string, padLen int, padLeft bool, padRight bool) string { + + // When padded length is less then the current string size + if padLen < utf8.RuneCountInString(str) { + return str + } + + padLen -= utf8.RuneCountInString(str) + + targetLen := padLen + + targetLenLeft := targetLen + targetLenRight := targetLen + if padLeft && padRight { + targetLenLeft = padLen / 2 + targetLenRight = padLen - targetLenLeft + } + + strToRepeatLen := utf8.RuneCountInString(padStr) + + repeatTimes := int(math.Ceil(float64(targetLen) / float64(strToRepeatLen))) + repeatedString := strings.Repeat(padStr, repeatTimes) + + leftSide := "" + if padLeft { + leftSide = repeatedString[0:targetLenLeft] + } + + rightSide := "" + if padRight { + rightSide = repeatedString[0:targetLenRight] + } + + return leftSide + str + rightSide +} diff --git a/vendor/github.com/asaskevich/govalidator/utils_test.go b/vendor/github.com/asaskevich/govalidator/utils_test.go new file mode 100644 index 0000000000..154f315945 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/utils_test.go @@ -0,0 +1,500 @@ +package govalidator + +import ( + "reflect" + "testing" +) + +func TestContains(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected bool + }{ + {"abacada", "", true}, + {"abacada", "ritir", false}, + {"abacada", "a", true}, + {"abacada", "aca", true}, + } + for _, test := range tests { + actual := Contains(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected Contains(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +func TestMatches(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected bool + }{ + {"123456789", "[0-9]+", true}, + {"abacada", "cab$", false}, + {"111222333", "((111|222|333)+)+", true}, + {"abacaba", "((123+]", false}, + } + for _, test := range tests { + actual := Matches(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected Matches(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +func TestLeftTrim(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected string + }{ + {" \r\n\tfoo \r\n\t ", "", "foo \r\n\t "}, + {"010100201000", "01", "201000"}, + } + for _, test := range tests { + actual := LeftTrim(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected LeftTrim(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +func TestRightTrim(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected string + }{ + {" \r\n\tfoo \r\n\t ", "", " \r\n\tfoo"}, + {"010100201000", "01", "0101002"}, + } + for _, test := range tests { + actual := RightTrim(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected RightTrim(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +func TestTrim(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected string + }{ + {" \r\n\tfoo \r\n\t ", "", "foo"}, + {"010100201000", "01", "2"}, + {"1234567890987654321", "1-8", "909"}, + } + for _, test := range tests { + actual := Trim(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected Trim(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +// This small example illustrate how to work with Trim function. +func ExampleTrim() { + // Remove from left and right spaces and "\r", "\n", "\t" characters + println(Trim(" \r\r\ntext\r \t\n", "") == "text") + // Remove from left and right characters that are between "1" and "8". + // "1-8" is like full list "12345678". + println(Trim("1234567890987654321", "1-8") == "909") +} + +func TestWhiteList(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected string + }{ + {"abcdef", "abc", "abc"}, + {"aaaaaaaaaabbbbbbbbbb", "abc", "aaaaaaaaaabbbbbbbbbb"}, + {"a1b2c3", "abc", "abc"}, + {" ", "abc", ""}, + {"a3a43a5a4a3a2a23a4a5a4a3a4", "a-z", "aaaaaaaaaaaa"}, + } + for _, test := range tests { + actual := WhiteList(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected WhiteList(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +// This small example illustrate how to work with WhiteList function. +func ExampleWhiteList() { + // Remove all characters from string ignoring characters between "a" and "z" + println(WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa") +} + +func TestBlackList(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected string + }{ + {"abcdef", "abc", "def"}, + {"aaaaaaaaaabbbbbbbbbb", "abc", ""}, + {"a1b2c3", "abc", "123"}, + {" ", "abc", " "}, + {"a3a43a5a4a3a2a23a4a5a4a3a4", "a-z", "34354322345434"}, + } + for _, test := range tests { + actual := BlackList(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected BlackList(%q,%q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +func TestStripLow(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 bool + expected string + }{ + {"foo\x00", false, "foo"}, + {"\x7Ffoo\x02", false, "foo"}, + {"\x01\x09", false, ""}, + {"foo\x0A\x0D", false, "foo"}, + {"perch\u00e9", false, "perch\u00e9"}, + {"\u20ac", false, "\u20ac"}, + {"\u2206\x0A", false, "\u2206"}, + {"foo\x0A\x0D", true, "foo\x0A\x0D"}, + {"\x03foo\x0A\x0D", true, "foo\x0A\x0D"}, + } + for _, test := range tests { + actual := StripLow(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected StripLow(%q,%t) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +func TestReplacePattern(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + param3 string + expected string + }{ + {"ab123ba", "[0-9]+", "aca", "abacaba"}, + {"abacaba", "[0-9]+", "aca", "abacaba"}, + {"httpftp://github.comio", "(ftp|io)", "", "http://github.com"}, + {"aaaaaaaaaa", "a", "", ""}, + {"http123123ftp://git534543hub.comio", "(ftp|io|[0-9]+)", "", "http://github.com"}, + } + for _, test := range tests { + actual := ReplacePattern(test.param1, test.param2, test.param3) + if actual != test.expected { + t.Errorf("Expected ReplacePattern(%q,%q,%q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) + } + } +} + +// This small example illustrate how to work with ReplacePattern function. +func ExampleReplacePattern() { + // Replace in "http123123ftp://git534543hub.comio" following (pattern "(ftp|io|[0-9]+)"): + // - Sequence "ftp". + // - Sequence "io". + // - Sequence of digits. + // with empty string. + println(ReplacePattern("http123123ftp://git534543hub.comio", "(ftp|io|[0-9]+)", "") == "http://github.com") +} + +func TestEscape(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected string + }{ + {`foo&bar`, "<img alt="foo&bar">"}, + } + for _, test := range tests { + actual := Escape(test.param) + if actual != test.expected { + t.Errorf("Expected Escape(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestUnderscoreToCamelCase(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected string + }{ + {"a_b_c", "ABC"}, + {"my_func", "MyFunc"}, + {"1ab_cd", "1abCd"}, + } + for _, test := range tests { + actual := UnderscoreToCamelCase(test.param) + if actual != test.expected { + t.Errorf("Expected UnderscoreToCamelCase(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestCamelCaseToUnderscore(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected string + }{ + {"MyFunc", "my_func"}, + {"ABC", "a_b_c"}, + {"1B", "1_b"}, + } + for _, test := range tests { + actual := CamelCaseToUnderscore(test.param) + if actual != test.expected { + t.Errorf("Expected CamelCaseToUnderscore(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestReverse(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected string + }{ + {"abc", "cba"}, + {"カタカナ", "ナカタカ"}, + } + for _, test := range tests { + actual := Reverse(test.param) + if actual != test.expected { + t.Errorf("Expected Reverse(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestGetLines(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected []string + }{ + {"abc", []string{"abc"}}, + {"a\nb\nc", []string{"a", "b", "c"}}, + } + for _, test := range tests { + actual := GetLines(test.param) + if !reflect.DeepEqual(actual, test.expected) { + t.Errorf("Expected GetLines(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestGetLine(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 int + expected string + }{ + {"abc", 0, "abc"}, + {"a\nb\nc", 0, "a"}, + {"abc", -1, ""}, + {"abacaba\n", 1, ""}, + {"abc", 3, ""}, + } + for _, test := range tests { + actual, _ := GetLine(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected GetLine(%q, %d) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +func TestRemoveTags(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected string + }{ + {"abc", "abc"}, + {"", ""}, + {"

Text

", "Text"}, + {`Link`, "Link"}, + } + for _, test := range tests { + actual := RemoveTags(test.param) + if actual != test.expected { + t.Errorf("Expected RemoveTags(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestSafeFileName(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected string + }{ + {"abc", "abc"}, + {"123456789 '_-?ASDF@£$%£%^é.html", "123456789-asdf.html"}, + {"ReadMe.md", "readme.md"}, + {"file:///c:/test.go", "test.go"}, + {"../../../Hello World!.txt", "hello-world.txt"}, + } + for _, test := range tests { + actual := SafeFileName(test.param) + if actual != test.expected { + t.Errorf("Expected SafeFileName(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestNormalizeEmail(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected string + }{ + {`test@me.com`, `test@me.com`}, + {`some.name@gmail.com`, `somename@gmail.com`}, + {`some.name@googlemail.com`, `somename@gmail.com`}, + {`some.name+extension@gmail.com`, `somename@gmail.com`}, + {`some.name+extension@googlemail.com`, `somename@gmail.com`}, + {`some.name.middlename+extension@gmail.com`, `somenamemiddlename@gmail.com`}, + {`some.name.middlename+extension@googlemail.com`, `somenamemiddlename@gmail.com`}, + {`some.name.midd.lena.me.+extension@gmail.com`, `somenamemiddlename@gmail.com`}, + {`some.name.midd.lena.me.+extension@googlemail.com`, `somenamemiddlename@gmail.com`}, + {`some.name+extension@unknown.com`, `some.name+extension@unknown.com`}, + {`hans@m端ller.com`, `hans@m端ller.com`}, + {`hans`, ``}, + } + for _, test := range tests { + actual, err := NormalizeEmail(test.param) + if actual != test.expected { + t.Errorf("Expected NormalizeEmail(%q) to be %v, got %v, err %v", test.param, test.expected, actual, err) + } + } +} + +func TestTruncate(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 int + param3 string + expected string + }{ + {`Lorem ipsum dolor sit amet, consectetur adipiscing elit.`, 25, `...`, `Lorem ipsum dolor sit amet...`}, + {`Measuring programming progress by lines of code is like measuring aircraft building progress by weight.`, 35, ` new born babies!`, `Measuring programming progress by new born babies!`}, + {`Testestestestestestestestestest testestestestestestestestest`, 7, `...`, `Testestestestestestestestestest...`}, + {`Testing`, 7, `...`, `Testing`}, + } + for _, test := range tests { + actual := Truncate(test.param1, test.param2, test.param3) + if actual != test.expected { + t.Errorf("Expected Truncate(%q, %d, %q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) + } + } +} + +func TestPadLeft(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + param3 int + expected string + }{ + {"こんにちは", "xyz", 12, "xyzxyzxこんにちは"}, + {"こんにちは", "xyz", 11, "xyzxyzこんにちは"}, + {"abc", "x", 5, "xxabc"}, + {"abc", "xyz", 5, "xyabc"}, + {"abcde", "xyz", 5, "abcde"}, + {"abcde", "xyz", 4, "abcde"}, + } + for _, test := range tests { + actual := PadLeft(test.param1, test.param2, test.param3) + if actual != test.expected { + t.Errorf("Expected PadLeft(%q,%q,%q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) + } + } +} + +func TestPadRight(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + param3 int + expected string + }{ + {"こんにちは", "xyz", 12, "こんにちはxyzxyzx"}, + {"こんにちは", "xyz", 11, "こんにちはxyzxyz"}, + {"abc", "x", 5, "abcxx"}, + {"abc", "xyz", 5, "abcxy"}, + {"abcde", "xyz", 5, "abcde"}, + {"abcde", "xyz", 4, "abcde"}, + } + for _, test := range tests { + actual := PadRight(test.param1, test.param2, test.param3) + if actual != test.expected { + t.Errorf("Expected PadRight(%q,%q,%q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) + } + } +} + +func TestPadBoth(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + param3 int + expected string + }{ + {"こんにちは", "xyz", 12, "xyzこんにちはxyzx"}, + {"こんにちは", "xyz", 11, "xyzこんにちはxyz"}, + {"abc", "x", 5, "xabcx"}, + {"abc", "xyz", 5, "xabcx"}, + {"abcde", "xyz", 5, "abcde"}, + {"abcde", "xyz", 4, "abcde"}, + } + for _, test := range tests { + actual := PadBoth(test.param1, test.param2, test.param3) + if actual != test.expected { + t.Errorf("Expected PadBoth(%q,%q,%q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) + } + } +} diff --git a/vendor/github.com/asaskevich/govalidator/validator.go b/vendor/github.com/asaskevich/govalidator/validator.go new file mode 100644 index 0000000000..f35de47a40 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/validator.go @@ -0,0 +1,1061 @@ +// Package govalidator is package of validators and sanitizers for strings, structs and collections. +package govalidator + +import ( + "encoding/json" + "fmt" + "net" + "net/url" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "time" + "unicode" + "unicode/utf8" +) + +var ( + fieldsRequiredByDefault bool + notNumberRegexp = regexp.MustCompile("[^0-9]+") + whiteSpacesAndMinus = regexp.MustCompile("[\\s-]+") + paramsRegexp = regexp.MustCompile("\\(.*\\)$") +) + +const maxURLRuneCount = 2083 +const minURLRuneCount = 3 + +// SetFieldsRequiredByDefault causes validation to fail when struct fields +// do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). +// This struct definition will fail govalidator.ValidateStruct() (and the field values do not matter): +// type exampleStruct struct { +// Name string `` +// Email string `valid:"email"` +// This, however, will only fail when Email is empty or an invalid email address: +// type exampleStruct2 struct { +// Name string `valid:"-"` +// Email string `valid:"email"` +// Lastly, this will only fail when Email is an invalid email address but not when it's empty: +// type exampleStruct2 struct { +// Name string `valid:"-"` +// Email string `valid:"email,optional"` +func SetFieldsRequiredByDefault(value bool) { + fieldsRequiredByDefault = value +} + +// IsEmail check if the string is an email. +func IsEmail(str string) bool { + // TODO uppercase letters are not supported + return rxEmail.MatchString(str) +} + +// IsURL check if the string is an URL. +func IsURL(str string) bool { + if str == "" || utf8.RuneCountInString(str) >= maxURLRuneCount || len(str) <= minURLRuneCount || strings.HasPrefix(str, ".") { + return false + } + u, err := url.Parse(str) + if err != nil { + return false + } + if strings.HasPrefix(u.Host, ".") { + return false + } + if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) { + return false + } + return rxURL.MatchString(str) + +} + +// IsRequestURL check if the string rawurl, assuming +// it was received in an HTTP request, is a valid +// URL confirm to RFC 3986 +func IsRequestURL(rawurl string) bool { + url, err := url.ParseRequestURI(rawurl) + if err != nil { + return false //Couldn't even parse the rawurl + } + if len(url.Scheme) == 0 { + return false //No Scheme found + } + return true +} + +// IsRequestURI check if the string rawurl, assuming +// it was received in an HTTP request, is an +// absolute URI or an absolute path. +func IsRequestURI(rawurl string) bool { + _, err := url.ParseRequestURI(rawurl) + return err == nil +} + +// IsAlpha check if the string contains only letters (a-zA-Z). Empty string is valid. +func IsAlpha(str string) bool { + if IsNull(str) { + return true + } + return rxAlpha.MatchString(str) +} + +//IsUTFLetter check if the string contains only unicode letter characters. +//Similar to IsAlpha but for all languages. Empty string is valid. +func IsUTFLetter(str string) bool { + if IsNull(str) { + return true + } + + for _, c := range str { + if !unicode.IsLetter(c) { + return false + } + } + return true + +} + +// IsAlphanumeric check if the string contains only letters and numbers. Empty string is valid. +func IsAlphanumeric(str string) bool { + if IsNull(str) { + return true + } + return rxAlphanumeric.MatchString(str) +} + +// IsUTFLetterNumeric check if the string contains only unicode letters and numbers. Empty string is valid. +func IsUTFLetterNumeric(str string) bool { + if IsNull(str) { + return true + } + for _, c := range str { + if !unicode.IsLetter(c) && !unicode.IsNumber(c) { //letters && numbers are ok + return false + } + } + return true + +} + +// IsNumeric check if the string contains only numbers. Empty string is valid. +func IsNumeric(str string) bool { + if IsNull(str) { + return true + } + return rxNumeric.MatchString(str) +} + +// IsUTFNumeric check if the string contains only unicode numbers of any kind. +// Numbers can be 0-9 but also Fractions ¾,Roman Ⅸ and Hangzhou 〩. Empty string is valid. +func IsUTFNumeric(str string) bool { + if IsNull(str) { + return true + } + if strings.IndexAny(str, "+-") > 0 { + return false + } + if len(str) > 1 { + str = strings.TrimPrefix(str, "-") + str = strings.TrimPrefix(str, "+") + } + for _, c := range str { + if unicode.IsNumber(c) == false { //numbers && minus sign are ok + return false + } + } + return true + +} + +// IsUTFDigit check if the string contains only unicode radix-10 decimal digits. Empty string is valid. +func IsUTFDigit(str string) bool { + if IsNull(str) { + return true + } + if strings.IndexAny(str, "+-") > 0 { + return false + } + if len(str) > 1 { + str = strings.TrimPrefix(str, "-") + str = strings.TrimPrefix(str, "+") + } + for _, c := range str { + if !unicode.IsDigit(c) { //digits && minus sign are ok + return false + } + } + return true + +} + +// IsHexadecimal check if the string is a hexadecimal number. +func IsHexadecimal(str string) bool { + return rxHexadecimal.MatchString(str) +} + +// IsHexcolor check if the string is a hexadecimal color. +func IsHexcolor(str string) bool { + return rxHexcolor.MatchString(str) +} + +// IsRGBcolor check if the string is a valid RGB color in form rgb(RRR, GGG, BBB). +func IsRGBcolor(str string) bool { + return rxRGBcolor.MatchString(str) +} + +// IsLowerCase check if the string is lowercase. Empty string is valid. +func IsLowerCase(str string) bool { + if IsNull(str) { + return true + } + return str == strings.ToLower(str) +} + +// IsUpperCase check if the string is uppercase. Empty string is valid. +func IsUpperCase(str string) bool { + if IsNull(str) { + return true + } + return str == strings.ToUpper(str) +} + +// IsInt check if the string is an integer. Empty string is valid. +func IsInt(str string) bool { + if IsNull(str) { + return true + } + return rxInt.MatchString(str) +} + +// IsFloat check if the string is a float. +func IsFloat(str string) bool { + return str != "" && rxFloat.MatchString(str) +} + +// IsDivisibleBy check if the string is a number that's divisible by another. +// If second argument is not valid integer or zero, it's return false. +// Otherwise, if first argument is not valid integer or zero, it's return true (Invalid string converts to zero). +func IsDivisibleBy(str, num string) bool { + f, _ := ToFloat(str) + p := int64(f) + q, _ := ToInt(num) + if q == 0 { + return false + } + return (p == 0) || (p%q == 0) +} + +// IsNull check if the string is null. +func IsNull(str string) bool { + return len(str) == 0 +} + +// IsByteLength check if the string's length (in bytes) falls in a range. +func IsByteLength(str string, min, max int) bool { + return len(str) >= min && len(str) <= max +} + +// IsUUIDv3 check if the string is a UUID version 3. +func IsUUIDv3(str string) bool { + return rxUUID3.MatchString(str) +} + +// IsUUIDv4 check if the string is a UUID version 4. +func IsUUIDv4(str string) bool { + return rxUUID4.MatchString(str) +} + +// IsUUIDv5 check if the string is a UUID version 5. +func IsUUIDv5(str string) bool { + return rxUUID5.MatchString(str) +} + +// IsUUID check if the string is a UUID (version 3, 4 or 5). +func IsUUID(str string) bool { + return rxUUID.MatchString(str) +} + +// IsCreditCard check if the string is a credit card. +func IsCreditCard(str string) bool { + sanitized := notNumberRegexp.ReplaceAllString(str, "") + if !rxCreditCard.MatchString(sanitized) { + return false + } + var sum int64 + var digit string + var tmpNum int64 + var shouldDouble bool + for i := len(sanitized) - 1; i >= 0; i-- { + digit = sanitized[i:(i + 1)] + tmpNum, _ = ToInt(digit) + if shouldDouble { + tmpNum *= 2 + if tmpNum >= 10 { + sum += ((tmpNum % 10) + 1) + } else { + sum += tmpNum + } + } else { + sum += tmpNum + } + shouldDouble = !shouldDouble + } + + if sum%10 == 0 { + return true + } + return false +} + +// IsISBN10 check if the string is an ISBN version 10. +func IsISBN10(str string) bool { + return IsISBN(str, 10) +} + +// IsISBN13 check if the string is an ISBN version 13. +func IsISBN13(str string) bool { + return IsISBN(str, 13) +} + +// IsISBN check if the string is an ISBN (version 10 or 13). +// If version value is not equal to 10 or 13, it will be check both variants. +func IsISBN(str string, version int) bool { + sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "") + var checksum int32 + var i int32 + if version == 10 { + if !rxISBN10.MatchString(sanitized) { + return false + } + for i = 0; i < 9; i++ { + checksum += (i + 1) * int32(sanitized[i]-'0') + } + if sanitized[9] == 'X' { + checksum += 10 * 10 + } else { + checksum += 10 * int32(sanitized[9]-'0') + } + if checksum%11 == 0 { + return true + } + return false + } else if version == 13 { + if !rxISBN13.MatchString(sanitized) { + return false + } + factor := []int32{1, 3} + for i = 0; i < 12; i++ { + checksum += factor[i%2] * int32(sanitized[i]-'0') + } + if (int32(sanitized[12]-'0'))-((10-(checksum%10))%10) == 0 { + return true + } + return false + } + return IsISBN(str, 10) || IsISBN(str, 13) +} + +// IsJSON check if the string is valid JSON (note: uses json.Unmarshal). +func IsJSON(str string) bool { + var js json.RawMessage + return json.Unmarshal([]byte(str), &js) == nil +} + +// IsMultibyte check if the string contains one or more multibyte chars. Empty string is valid. +func IsMultibyte(str string) bool { + if IsNull(str) { + return true + } + return rxMultibyte.MatchString(str) +} + +// IsASCII check if the string contains ASCII chars only. Empty string is valid. +func IsASCII(str string) bool { + if IsNull(str) { + return true + } + return rxASCII.MatchString(str) +} + +// IsPrintableASCII check if the string contains printable ASCII chars only. Empty string is valid. +func IsPrintableASCII(str string) bool { + if IsNull(str) { + return true + } + return rxPrintableASCII.MatchString(str) +} + +// IsFullWidth check if the string contains any full-width chars. Empty string is valid. +func IsFullWidth(str string) bool { + if IsNull(str) { + return true + } + return rxFullWidth.MatchString(str) +} + +// IsHalfWidth check if the string contains any half-width chars. Empty string is valid. +func IsHalfWidth(str string) bool { + if IsNull(str) { + return true + } + return rxHalfWidth.MatchString(str) +} + +// IsVariableWidth check if the string contains a mixture of full and half-width chars. Empty string is valid. +func IsVariableWidth(str string) bool { + if IsNull(str) { + return true + } + return rxHalfWidth.MatchString(str) && rxFullWidth.MatchString(str) +} + +// IsBase64 check if a string is base64 encoded. +func IsBase64(str string) bool { + return rxBase64.MatchString(str) +} + +// IsFilePath check is a string is Win or Unix file path and returns it's type. +func IsFilePath(str string) (bool, int) { + if rxWinPath.MatchString(str) { + //check windows path limit see: + // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath + if len(str[3:]) > 32767 { + return false, Win + } + return true, Win + } else if rxUnixPath.MatchString(str) { + return true, Unix + } + return false, Unknown +} + +// IsDataURI checks if a string is base64 encoded data URI such as an image +func IsDataURI(str string) bool { + dataURI := strings.Split(str, ",") + if !rxDataURI.MatchString(dataURI[0]) { + return false + } + return IsBase64(dataURI[1]) +} + +// IsISO3166Alpha2 checks if a string is valid two-letter country code +func IsISO3166Alpha2(str string) bool { + for _, entry := range ISO3166List { + if str == entry.Alpha2Code { + return true + } + } + return false +} + +// IsISO3166Alpha3 checks if a string is valid three-letter country code +func IsISO3166Alpha3(str string) bool { + for _, entry := range ISO3166List { + if str == entry.Alpha3Code { + return true + } + } + return false +} + +// IsISO693Alpha2 checks if a string is valid two-letter language code +func IsISO693Alpha2(str string) bool { + for _, entry := range ISO693List { + if str == entry.Alpha2Code { + return true + } + } + return false +} + +// IsISO693Alpha3b checks if a string is valid three-letter language code +func IsISO693Alpha3b(str string) bool { + for _, entry := range ISO693List { + if str == entry.Alpha3bCode { + return true + } + } + return false +} + +// IsDNSName will validate the given string as a DNS name +func IsDNSName(str string) bool { + if str == "" || len(strings.Replace(str, ".", "", -1)) > 255 { + // constraints already violated + return false + } + return !IsIP(str) && rxDNSName.MatchString(str) +} + +// IsDialString validates the given string for usage with the various Dial() functions +func IsDialString(str string) bool { + + if h, p, err := net.SplitHostPort(str); err == nil && h != "" && p != "" && (IsDNSName(h) || IsIP(h)) && IsPort(p) { + return true + } + + return false +} + +// IsIP checks if a string is either IP version 4 or 6. +func IsIP(str string) bool { + return net.ParseIP(str) != nil +} + +// IsPort checks if a string represents a valid port +func IsPort(str string) bool { + if i, err := strconv.Atoi(str); err == nil && i > 0 && i < 65536 { + return true + } + return false +} + +// IsIPv4 check if the string is an IP version 4. +func IsIPv4(str string) bool { + ip := net.ParseIP(str) + return ip != nil && strings.Contains(str, ".") +} + +// IsIPv6 check if the string is an IP version 6. +func IsIPv6(str string) bool { + ip := net.ParseIP(str) + return ip != nil && strings.Contains(str, ":") +} + +// IsCIDR check if the string is an valid CIDR notiation (IPV4 & IPV6) +func IsCIDR(str string) bool { + _, _, err := net.ParseCIDR(str) + return err == nil +} + +// IsMAC check if a string is valid MAC address. +// Possible MAC formats: +// 01:23:45:67:89:ab +// 01:23:45:67:89:ab:cd:ef +// 01-23-45-67-89-ab +// 01-23-45-67-89-ab-cd-ef +// 0123.4567.89ab +// 0123.4567.89ab.cdef +func IsMAC(str string) bool { + _, err := net.ParseMAC(str) + return err == nil +} + +// IsHost checks if the string is a valid IP (both v4 and v6) or a valid DNS name +func IsHost(str string) bool { + return IsIP(str) || IsDNSName(str) +} + +// IsMongoID check if the string is a valid hex-encoded representation of a MongoDB ObjectId. +func IsMongoID(str string) bool { + return rxHexadecimal.MatchString(str) && (len(str) == 24) +} + +// IsLatitude check if a string is valid latitude. +func IsLatitude(str string) bool { + return rxLatitude.MatchString(str) +} + +// IsLongitude check if a string is valid longitude. +func IsLongitude(str string) bool { + return rxLongitude.MatchString(str) +} + +func toJSONName(tag string) string { + if tag == "" { + return "" + } + + // JSON name always comes first. If there's no options then split[0] is + // JSON name, if JSON name is not set, then split[0] is an empty string. + split := strings.SplitN(tag, ",", 2) + return split[0] +} + +// ValidateStruct use tags for fields. +// result will be equal to `false` if there are any errors. +func ValidateStruct(s interface{}) (bool, error) { + if s == nil { + return true, nil + } + result := true + var err error + val := reflect.ValueOf(s) + if val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr { + val = val.Elem() + } + // we only accept structs + if val.Kind() != reflect.Struct { + return false, fmt.Errorf("function only accepts structs; got %s", val.Kind()) + } + var errs Errors + for i := 0; i < val.NumField(); i++ { + valueField := val.Field(i) + typeField := val.Type().Field(i) + if typeField.PkgPath != "" { + continue // Private field + } + structResult := true + if valueField.Kind() == reflect.Struct && typeField.Tag.Get(tagName) != "-" { + var err error + structResult, err = ValidateStruct(valueField.Interface()) + if err != nil { + errs = append(errs, err) + } + } + resultField, err2 := typeCheck(valueField, typeField, val, nil) + if err2 != nil { + + // Replace structure name with JSON name if there is a tag on the variable + jsonTag := toJSONName(typeField.Tag.Get("json")) + if jsonTag != "" { + switch jsonError := err2.(type) { + case Error: + jsonError.Name = jsonTag + err2 = jsonError + case Errors: + err2 = jsonError + } + } + + errs = append(errs, err2) + } + result = result && resultField && structResult + } + if len(errs) > 0 { + err = errs + } + return result, err +} + +// parseTagIntoMap parses a struct tag `valid:required~Some error message,length(2|3)` into map[string]string{"required": "Some error message", "length(2|3)": ""} +func parseTagIntoMap(tag string) tagOptionsMap { + optionsMap := make(tagOptionsMap) + options := strings.Split(tag, ",") + + for _, option := range options { + option = strings.TrimSpace(option) + + validationOptions := strings.Split(option, "~") + if !isValidTag(validationOptions[0]) { + continue + } + if len(validationOptions) == 2 { + optionsMap[validationOptions[0]] = validationOptions[1] + } else { + optionsMap[validationOptions[0]] = "" + } + } + return optionsMap +} + +func isValidTag(s string) bool { + if s == "" { + return false + } + for _, c := range s { + switch { + case strings.ContainsRune("\\'\"!#$%&()*+-./:<=>?@[]^_{|}~ ", c): + // Backslash and quote chars are reserved, but + // otherwise any punctuation chars are allowed + // in a tag name. + default: + if !unicode.IsLetter(c) && !unicode.IsDigit(c) { + return false + } + } + } + return true +} + +// IsSSN will validate the given string as a U.S. Social Security Number +func IsSSN(str string) bool { + if str == "" || len(str) != 11 { + return false + } + return rxSSN.MatchString(str) +} + +// IsSemver check if string is valid semantic version +func IsSemver(str string) bool { + return rxSemver.MatchString(str) +} + +// IsTime check if string is valid according to given format +func IsTime(str string, format string) bool { + _, err := time.Parse(format, str) + return err == nil +} + +// IsRFC3339 check if string is valid timestamp value according to RFC3339 +func IsRFC3339(str string) bool { + return IsTime(str, time.RFC3339) +} + +// IsISO4217 check if string is valid ISO currency code +func IsISO4217(str string) bool { + for _, currency := range ISO4217List { + if str == currency { + return true + } + } + + return false +} + +// ByteLength check string's length +func ByteLength(str string, params ...string) bool { + if len(params) == 2 { + min, _ := ToInt(params[0]) + max, _ := ToInt(params[1]) + return len(str) >= int(min) && len(str) <= int(max) + } + + return false +} + +// RuneLength check string's length +// Alias for StringLength +func RuneLength(str string, params ...string) bool { + return StringLength(str, params...) +} + +// StringMatches checks if a string matches a given pattern. +func StringMatches(s string, params ...string) bool { + if len(params) == 1 { + pattern := params[0] + return Matches(s, pattern) + } + return false +} + +// StringLength check string's length (including multi byte strings) +func StringLength(str string, params ...string) bool { + + if len(params) == 2 { + strLength := utf8.RuneCountInString(str) + min, _ := ToInt(params[0]) + max, _ := ToInt(params[1]) + return strLength >= int(min) && strLength <= int(max) + } + + return false +} + +// Range check string's length +func Range(str string, params ...string) bool { + if len(params) == 2 { + value, _ := ToFloat(str) + min, _ := ToFloat(params[0]) + max, _ := ToFloat(params[1]) + return InRange(value, min, max) + } + + return false +} + +func isInRaw(str string, params ...string) bool { + if len(params) == 1 { + rawParams := params[0] + + parsedParams := strings.Split(rawParams, "|") + + return IsIn(str, parsedParams...) + } + + return false +} + +// IsIn check if string str is a member of the set of strings params +func IsIn(str string, params ...string) bool { + for _, param := range params { + if str == param { + return true + } + } + + return false +} + +func checkRequired(v reflect.Value, t reflect.StructField, options tagOptionsMap) (bool, error) { + if requiredOption, isRequired := options["required"]; isRequired { + if len(requiredOption) > 0 { + return false, Error{t.Name, fmt.Errorf(requiredOption), true, "required"} + } + return false, Error{t.Name, fmt.Errorf("non zero value required"), false, "required"} + } else if _, isOptional := options["optional"]; fieldsRequiredByDefault && !isOptional { + return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false, "required"} + } + // not required and empty is valid + return true, nil +} + +func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options tagOptionsMap) (isValid bool, resultErr error) { + if !v.IsValid() { + return false, nil + } + + tag := t.Tag.Get(tagName) + + // Check if the field should be ignored + switch tag { + case "": + if !fieldsRequiredByDefault { + return true, nil + } + return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false, "required"} + case "-": + return true, nil + } + + isRootType := false + if options == nil { + isRootType = true + options = parseTagIntoMap(tag) + } + + if isEmptyValue(v) { + // an empty value is not validated, check only required + return checkRequired(v, t, options) + } + + var customTypeErrors Errors + for validatorName, customErrorMessage := range options { + if validatefunc, ok := CustomTypeTagMap.Get(validatorName); ok { + delete(options, validatorName) + + if result := validatefunc(v.Interface(), o.Interface()); !result { + if len(customErrorMessage) > 0 { + customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf(customErrorMessage), CustomErrorMessageExists: true, Validator: stripParams(validatorName)}) + continue + } + customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), validatorName), CustomErrorMessageExists: false, Validator: stripParams(validatorName)}) + } + } + } + + if len(customTypeErrors.Errors()) > 0 { + return false, customTypeErrors + } + + if isRootType { + // Ensure that we've checked the value by all specified validators before report that the value is valid + defer func() { + delete(options, "optional") + delete(options, "required") + + if isValid && resultErr == nil && len(options) != 0 { + for validator := range options { + isValid = false + resultErr = Error{t.Name, fmt.Errorf( + "The following validator is invalid or can't be applied to the field: %q", validator), false, stripParams(validator)} + return + } + } + }() + } + + switch v.Kind() { + case reflect.Bool, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, + reflect.Float32, reflect.Float64, + reflect.String: + // for each tag option check the map of validator functions + for validatorSpec, customErrorMessage := range options { + var negate bool + validator := validatorSpec + customMsgExists := len(customErrorMessage) > 0 + + // Check whether the tag looks like '!something' or 'something' + if validator[0] == '!' { + validator = validator[1:] + negate = true + } + + // Check for param validators + for key, value := range ParamTagRegexMap { + ps := value.FindStringSubmatch(validator) + if len(ps) == 0 { + continue + } + + validatefunc, ok := ParamTagMap[key] + if !ok { + continue + } + + delete(options, validatorSpec) + + switch v.Kind() { + case reflect.String: + field := fmt.Sprint(v) // make value into string, then validate with regex + if result := validatefunc(field, ps[1:]...); (!result && !negate) || (result && negate) { + if customMsgExists { + return false, Error{t.Name, fmt.Errorf(customErrorMessage), customMsgExists, stripParams(validatorSpec)} + } + if negate { + return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec)} + } + return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec)} + } + default: + // type not yet supported, fail + return false, Error{t.Name, fmt.Errorf("Validator %s doesn't support kind %s", validator, v.Kind()), false, stripParams(validatorSpec)} + } + } + + if validatefunc, ok := TagMap[validator]; ok { + delete(options, validatorSpec) + + switch v.Kind() { + case reflect.String: + field := fmt.Sprint(v) // make value into string, then validate with regex + if result := validatefunc(field); !result && !negate || result && negate { + if customMsgExists { + return false, Error{t.Name, fmt.Errorf(customErrorMessage), customMsgExists, stripParams(validatorSpec)} + } + if negate { + return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec)} + } + return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec)} + } + default: + //Not Yet Supported Types (Fail here!) + err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", validator, v.Kind(), v) + return false, Error{t.Name, err, false, stripParams(validatorSpec)} + } + } + } + return true, nil + case reflect.Map: + if v.Type().Key().Kind() != reflect.String { + return false, &UnsupportedTypeError{v.Type()} + } + var sv stringValues + sv = v.MapKeys() + sort.Sort(sv) + result := true + for _, k := range sv { + var resultItem bool + var err error + if v.MapIndex(k).Kind() != reflect.Struct { + resultItem, err = typeCheck(v.MapIndex(k), t, o, options) + if err != nil { + return false, err + } + } else { + resultItem, err = ValidateStruct(v.MapIndex(k).Interface()) + if err != nil { + return false, err + } + } + result = result && resultItem + } + return result, nil + case reflect.Slice, reflect.Array: + result := true + for i := 0; i < v.Len(); i++ { + var resultItem bool + var err error + if v.Index(i).Kind() != reflect.Struct { + resultItem, err = typeCheck(v.Index(i), t, o, options) + if err != nil { + return false, err + } + } else { + resultItem, err = ValidateStruct(v.Index(i).Interface()) + if err != nil { + return false, err + } + } + result = result && resultItem + } + return result, nil + case reflect.Interface: + // If the value is an interface then encode its element + if v.IsNil() { + return true, nil + } + return ValidateStruct(v.Interface()) + case reflect.Ptr: + // If the value is a pointer then check its element + if v.IsNil() { + return true, nil + } + return typeCheck(v.Elem(), t, o, options) + case reflect.Struct: + return ValidateStruct(v.Interface()) + default: + return false, &UnsupportedTypeError{v.Type()} + } +} + +func stripParams(validatorString string) string { + return paramsRegexp.ReplaceAllString(validatorString, "") +} + +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.String, reflect.Array: + return v.Len() == 0 + case reflect.Map, reflect.Slice: + return v.Len() == 0 || v.IsNil() + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + + return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) +} + +// ErrorByField returns error for specified field of the struct +// validated by ValidateStruct or empty string if there are no errors +// or this field doesn't exists or doesn't have any errors. +func ErrorByField(e error, field string) string { + if e == nil { + return "" + } + return ErrorsByField(e)[field] +} + +// ErrorsByField returns map of errors of the struct validated +// by ValidateStruct or empty map if there are no errors. +func ErrorsByField(e error) map[string]string { + m := make(map[string]string) + if e == nil { + return m + } + // prototype for ValidateStruct + + switch e.(type) { + case Error: + m[e.(Error).Name] = e.(Error).Err.Error() + case Errors: + for _, item := range e.(Errors).Errors() { + n := ErrorsByField(item) + for k, v := range n { + m[k] = v + } + } + } + + return m +} + +// Error returns string equivalent for reflect.Type +func (e *UnsupportedTypeError) Error() string { + return "validator: unsupported type: " + e.Type.String() +} + +func (sv stringValues) Len() int { return len(sv) } +func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } +func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) } +func (sv stringValues) get(i int) string { return sv[i].String() } diff --git a/vendor/github.com/asaskevich/govalidator/validator_test.go b/vendor/github.com/asaskevich/govalidator/validator_test.go new file mode 100644 index 0000000000..32a5d01967 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/validator_test.go @@ -0,0 +1,2949 @@ +package govalidator + +import ( + "fmt" + "strings" + "testing" + "time" +) + +func init() { + CustomTypeTagMap.Set("customFalseValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { + return false + })) + CustomTypeTagMap.Set("customTrueValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { + return true + })) +} + +func TestIsAlpha(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"abc", true}, + {"소주", false}, + {"ABC", true}, + {"FoObAr", true}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", true}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", false}, //UTF-8(ASCII): 0 + {"123", false}, + {"0123", false}, + {"-00123", false}, + {"0", false}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", false}, + {"ix", true}, + {"۳۵۶۰", false}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := IsAlpha(test.param) + if actual != test.expected { + t.Errorf("Expected IsAlpha(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsUTFLetter(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"", true}, + {"abc", true}, + {"소주", true}, + {"ABC", true}, + {"FoObAr", true}, + {"소aBC", true}, + {"소", true}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", true}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", false}, //UTF-8(ASCII): 0 + {"123", false}, + {"0123", false}, + {"-00123", false}, + {"0", false}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", true}, + {"ix", true}, + {"۳۵۶۰", false}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := IsUTFLetter(test.param) + if actual != test.expected { + t.Errorf("Expected IsUTFLetter(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsAlphanumeric(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc123", true}, + {"ABC111", true}, + {"abc1", true}, + {"abc〩", false}, + {"abc", true}, + {"소주", false}, + {"ABC", true}, + {"FoObAr", true}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", true}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", false}, + {"0", true}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", false}, + {"ix", true}, + {"۳۵۶۰", false}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := IsAlphanumeric(test.param) + if actual != test.expected { + t.Errorf("Expected IsAlphanumeric(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsUTFLetterNumeric(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", true}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", true}, + {"abc〩", true}, + {"abc", true}, + {"소주", true}, + {"ABC", true}, + {"FoObAr", true}, + {"소aBC", true}, + {"소", true}, + {"달기&Co.", false}, + {"〩Hours", true}, + {"\ufff0", false}, + {"\u0070", true}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", false}, + {"0", true}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"-1¾", false}, + {"1¾", true}, + {"〥〩", true}, + {"모자", true}, + {"ix", true}, + {"۳۵۶۰", true}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := IsUTFLetterNumeric(test.param) + if actual != test.expected { + t.Errorf("Expected IsUTFLetterNumeric(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsNumeric(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"abc", false}, + {"소주", false}, + {"ABC", false}, + {"FoObAr", false}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", false}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", false}, + {"+00123", false}, + {"0", true}, + {"-0", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"12𐅪3", false}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", false}, + {"ix", false}, + {"۳۵۶۰", false}, + {"1--", false}, + {"1-1", false}, + {"-", false}, + {"--", false}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", false}, + } + for _, test := range tests { + actual := IsNumeric(test.param) + if actual != test.expected { + t.Errorf("Expected IsNumeric(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsUTFNumeric(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"\n", false}, + {"\r", false}, + {"Ⅸ", true}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"abc", false}, + {"소주", false}, + {"ABC", false}, + {"FoObAr", false}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", false}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", true}, + {"0", true}, + {"-0", true}, + {"--0", false}, + {"-0-", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"12𐅪3", true}, + {"-1¾", true}, + {"1¾", true}, + {"〥〩", true}, + {"모자", false}, + {"ix", false}, + {"۳۵۶۰", true}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", true}, + } + for _, test := range tests { + actual := IsUTFNumeric(test.param) + if actual != test.expected { + t.Errorf("Expected IsUTFNumeric(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsUTFDigit(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + + {"\n", false}, + {"\r", false}, + {"Ⅸ", false}, + {"", true}, + {" fooo ", false}, + {"abc!!!", false}, + {"abc1", false}, + {"abc〩", false}, + {"abc", false}, + {"소주", false}, + {"ABC", false}, + {"FoObAr", false}, + {"소aBC", false}, + {"소", false}, + {"달기&Co.", false}, + {"〩Hours", false}, + {"\ufff0", false}, + {"\u0070", false}, //UTF-8(ASCII): p + {"\u0026", false}, //UTF-8(ASCII): & + {"\u0030", true}, //UTF-8(ASCII): 0 + {"123", true}, + {"0123", true}, + {"-00123", true}, + {"0", true}, + {"-0", true}, + {"--0", false}, + {"-0-", false}, + {"123.123", false}, + {" ", false}, + {".", false}, + {"12𐅪3", false}, + {"1483920", true}, + {"", true}, + {"۳۵۶۰", true}, + {"-29", true}, + {"-1¾", false}, + {"1¾", false}, + {"〥〩", false}, + {"모자", false}, + {"ix", false}, + {"۳۵۶۰", true}, + {"1++", false}, + {"1+1", false}, + {"+", false}, + {"++", false}, + {"+1", true}, + } + for _, test := range tests { + actual := IsUTFDigit(test.param) + if actual != test.expected { + t.Errorf("Expected IsUTFDigit(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsLowerCase(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"abc123", true}, + {"abc", true}, + {"a b c", true}, + {"abcß", true}, + {"abcẞ", false}, + {"ABCẞ", false}, + {"tr竪s 端ber", true}, + {"fooBar", false}, + {"123ABC", false}, + {"ABC123", false}, + {"ABC", false}, + {"S T R", false}, + {"fooBar", false}, + {"abacaba123", true}, + } + for _, test := range tests { + actual := IsLowerCase(test.param) + if actual != test.expected { + t.Errorf("Expected IsLowerCase(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsUpperCase(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"abc123", false}, + {"abc", false}, + {"a b c", false}, + {"abcß", false}, + {"abcẞ", false}, + {"ABCẞ", true}, + {"tr竪s 端ber", false}, + {"fooBar", false}, + {"123ABC", true}, + {"ABC123", true}, + {"ABC", true}, + {"S T R", true}, + {"fooBar", false}, + {"abacaba123", false}, + } + for _, test := range tests { + actual := IsUpperCase(test.param) + if actual != test.expected { + t.Errorf("Expected IsUpperCase(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsInt(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"-2147483648", true}, //Signed 32 Bit Min Int + {"2147483647", true}, //Signed 32 Bit Max Int + {"-2147483649", true}, //Signed 32 Bit Min Int - 1 + {"2147483648", true}, //Signed 32 Bit Max Int + 1 + {"4294967295", true}, //Unsigned 32 Bit Max Int + {"4294967296", true}, //Unsigned 32 Bit Max Int + 1 + {"-9223372036854775808", true}, //Signed 64 Bit Min Int + {"9223372036854775807", true}, //Signed 64 Bit Max Int + {"-9223372036854775809", true}, //Signed 64 Bit Min Int - 1 + {"9223372036854775808", true}, //Signed 64 Bit Max Int + 1 + {"18446744073709551615", true}, //Unsigned 64 Bit Max Int + {"18446744073709551616", true}, //Unsigned 64 Bit Max Int + 1 + {"", true}, + {"123", true}, + {"0", true}, + {"-0", true}, + {"+0", true}, + {"01", false}, + {"123.123", false}, + {" ", false}, + {"000", false}, + } + for _, test := range tests { + actual := IsInt(test.param) + if actual != test.expected { + t.Errorf("Expected IsInt(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsEmail(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"foo@bar.com", true}, + {"x@x.x", true}, + {"foo@bar.com.au", true}, + {"foo+bar@bar.com", true}, + {"foo@bar.coffee", true}, + {"foo@bar.coffee..coffee", false}, + {"foo@bar.bar.coffee", true}, + {"foo@bar.中文网", true}, + {"invalidemail@", false}, + {"invalid.com", false}, + {"@invalid.com", false}, + {"test|123@m端ller.com", true}, + {"hans@m端ller.com", true}, + {"hans.m端ller@test.com", true}, + {"NathAn.daVIeS@DomaIn.cOM", true}, + {"NATHAN.DAVIES@DOMAIN.CO.UK", true}, + } + for _, test := range tests { + actual := IsEmail(test.param) + if actual != test.expected { + t.Errorf("Expected IsEmail(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsURL(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"http://foo.bar#com", true}, + {"http://foobar.com", true}, + {"https://foobar.com", true}, + {"foobar.com", true}, + {"http://foobar.coffee/", true}, + {"http://foobar.中文网/", true}, + {"http://foobar.org/", true}, + {"http://foobar.ORG", true}, + {"http://foobar.org:8080/", true}, + {"ftp://foobar.ru/", true}, + {"ftp.foo.bar", true}, + {"http://user:pass@www.foobar.com/", true}, + {"http://user:pass@www.foobar.com/path/file", true}, + {"http://127.0.0.1/", true}, + {"http://duckduckgo.com/?q=%2F", true}, + {"http://localhost:3000/", true}, + {"http://foobar.com/?foo=bar#baz=qux", true}, + {"http://foobar.com?foo=bar", true}, + {"http://www.xn--froschgrn-x9a.net/", true}, + {"http://foobar.com/a-", true}, + {"http://foobar.پاکستان/", true}, + {"http://foobar.c_o_m", false}, + {"", false}, + {"xyz://foobar.com", false}, + // {"invalid.", false}, is it false like "localhost."? + {".com", false}, + {"rtmp://foobar.com", false}, + {"http://www.foo_bar.com/", false}, + {"http://localhost:3000/", true}, + {"http://foobar.com#baz=qux", true}, + {"http://foobar.com/t$-_.+!*\\'(),", true}, + {"http://www.foobar.com/~foobar", true}, + {"http://www.-foobar.com/", false}, + {"http://www.foo---bar.com/", false}, + {"http://r6---snnvoxuioq6.googlevideo.com", true}, + {"mailto:someone@example.com", true}, + {"irc://irc.server.org/channel", false}, + {"irc://#channel@network", true}, + {"/abs/test/dir", false}, + {"./rel/test/dir", false}, + {"http://foo^bar.org", false}, + {"http://foo&*bar.org", false}, + {"http://foo&bar.org", false}, + {"http://foo bar.org", false}, + {"http://foo.bar.org", true}, + {"http://www.foo.bar.org", true}, + {"http://www.foo.co.uk", true}, + {"foo", false}, + {"http://.foo.com", false}, + {"http://,foo.com", false}, + {",foo.com", false}, + {"http://myservice.:9093/", true}, + // according to issues #62 #66 + {"https://pbs.twimg.com/profile_images/560826135676588032/j8fWrmYY_normal.jpeg", true}, + // according to #125 + {"http://prometheus-alertmanager.service.q:9093", true}, + {"https://www.logn-123-123.url.with.sigle.letter.d:12345/url/path/foo?bar=zzz#user", true}, + {"http://me.example.com", true}, + {"http://www.me.example.com", true}, + {"https://farm6.static.flickr.com", true}, + {"https://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5", true}, + {"google", false}, + // According to #87 + {"http://hyphenated-host-name.example.co.in", true}, + {"http://cant-end-with-hyphen-.example.com", false}, + {"http://-cant-start-with-hyphen.example.com", false}, + {"http://www.domain-can-have-dashes.com", true}, + {"http://m.abcd.com/test.html", true}, + {"http://m.abcd.com/a/b/c/d/test.html?args=a&b=c", true}, + {"http://[::1]:9093", true}, + {"http://[::1]:909388", false}, + {"1200::AB00:1234::2552:7777:1313", false}, + {"http://[2001:db8:a0b:12f0::1]/index.html", true}, + {"http://[1200:0000:AB00:1234:0000:2552:7777:1313]", true}, + {"http://user:pass@[::1]:9093/a/b/c/?a=v#abc", true}, + {"https://127.0.0.1/a/b/c?a=v&c=11d", true}, + {"https://foo_bar.example.com", true}, + {"http://foo_bar.example.com", true}, + {"http://foo_bar_fizz_buzz.example.com", true}, + {"http://_cant_start_with_underescore", false}, + {"http://cant_end_with_underescore_", false}, + {"foo_bar.example.com", true}, + {"foo_bar_fizz_buzz.example.com", true}, + {"http://hello_world.example.com", true}, + } + for _, test := range tests { + actual := IsURL(test.param) + if actual != test.expected { + t.Errorf("Expected IsURL(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsRequestURL(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"http://foo.bar/#com", true}, + {"http://foobar.com", true}, + {"https://foobar.com", true}, + {"foobar.com", false}, + {"http://foobar.coffee/", true}, + {"http://foobar.中文网/", true}, + {"http://foobar.org/", true}, + {"http://foobar.org:8080/", true}, + {"ftp://foobar.ru/", true}, + {"http://user:pass@www.foobar.com/", true}, + {"http://127.0.0.1/", true}, + {"http://duckduckgo.com/?q=%2F", true}, + {"http://localhost:3000/", true}, + {"http://foobar.com/?foo=bar#baz=qux", true}, + {"http://foobar.com?foo=bar", true}, + {"http://www.xn--froschgrn-x9a.net/", true}, + {"", false}, + {"xyz://foobar.com", true}, + {"invalid.", false}, + {".com", false}, + {"rtmp://foobar.com", true}, + {"http://www.foo_bar.com/", true}, + {"http://localhost:3000/", true}, + {"http://foobar.com/#baz=qux", true}, + {"http://foobar.com/t$-_.+!*\\'(),", true}, + {"http://www.foobar.com/~foobar", true}, + {"http://www.-foobar.com/", true}, + {"http://www.foo---bar.com/", true}, + {"mailto:someone@example.com", true}, + {"irc://irc.server.org/channel", true}, + {"irc://#channel@network", true}, + {"/abs/test/dir", false}, + {"./rel/test/dir", false}, + } + for _, test := range tests { + actual := IsRequestURL(test.param) + if actual != test.expected { + t.Errorf("Expected IsRequestURL(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsRequestURI(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"http://foo.bar/#com", true}, + {"http://foobar.com", true}, + {"https://foobar.com", true}, + {"foobar.com", false}, + {"http://foobar.coffee/", true}, + {"http://foobar.中文网/", true}, + {"http://foobar.org/", true}, + {"http://foobar.org:8080/", true}, + {"ftp://foobar.ru/", true}, + {"http://user:pass@www.foobar.com/", true}, + {"http://127.0.0.1/", true}, + {"http://duckduckgo.com/?q=%2F", true}, + {"http://localhost:3000/", true}, + {"http://foobar.com/?foo=bar#baz=qux", true}, + {"http://foobar.com?foo=bar", true}, + {"http://www.xn--froschgrn-x9a.net/", true}, + {"xyz://foobar.com", true}, + {"invalid.", false}, + {".com", false}, + {"rtmp://foobar.com", true}, + {"http://www.foo_bar.com/", true}, + {"http://localhost:3000/", true}, + {"http://foobar.com/#baz=qux", true}, + {"http://foobar.com/t$-_.+!*\\'(),", true}, + {"http://www.foobar.com/~foobar", true}, + {"http://www.-foobar.com/", true}, + {"http://www.foo---bar.com/", true}, + {"mailto:someone@example.com", true}, + {"irc://irc.server.org/channel", true}, + {"irc://#channel@network", true}, + {"/abs/test/dir", true}, + {"./rel/test/dir", false}, + } + for _, test := range tests { + actual := IsRequestURI(test.param) + if actual != test.expected { + t.Errorf("Expected IsRequestURI(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsFloat(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {" ", false}, + {"-.123", false}, + {"abacaba", false}, + {"1f", false}, + {"-1f", false}, + {"+1f", false}, + {"123", true}, + {"123.", true}, + {"123.123", true}, + {"-123.123", true}, + {"+123.123", true}, + {"0.123", true}, + {"-0.123", true}, + {"+0.123", true}, + {".0", true}, + {"01.123", true}, + {"-0.22250738585072011e-307", true}, + {"+0.22250738585072011e-307", true}, + } + for _, test := range tests { + actual := IsFloat(test.param) + if actual != test.expected { + t.Errorf("Expected IsFloat(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsHexadecimal(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"abcdefg", false}, + {"", false}, + {"..", false}, + {"deadBEEF", true}, + {"ff0044", true}, + } + for _, test := range tests { + actual := IsHexadecimal(test.param) + if actual != test.expected { + t.Errorf("Expected IsHexadecimal(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsHexcolor(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"#ff", false}, + {"fff0", false}, + {"#ff12FG", false}, + {"CCccCC", true}, + {"fff", true}, + {"#f00", true}, + } + for _, test := range tests { + actual := IsHexcolor(test.param) + if actual != test.expected { + t.Errorf("Expected IsHexcolor(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsRGBcolor(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"rgb(0,31,255)", true}, + {"rgb(1,349,275)", false}, + {"rgb(01,31,255)", false}, + {"rgb(0.6,31,255)", false}, + {"rgba(0,31,255)", false}, + {"rgb(0, 31, 255)", true}, + } + for _, test := range tests { + actual := IsRGBcolor(test.param) + if actual != test.expected { + t.Errorf("Expected IsRGBcolor(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsNull(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"abacaba", false}, + {"", true}, + } + for _, test := range tests { + actual := IsNull(test.param) + if actual != test.expected { + t.Errorf("Expected IsNull(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsDivisibleBy(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 string + expected bool + }{ + {"4", "2", true}, + {"100", "10", true}, + {"", "1", true}, + {"123", "foo", false}, + {"123", "0", false}, + } + for _, test := range tests { + actual := IsDivisibleBy(test.param1, test.param2) + if actual != test.expected { + t.Errorf("Expected IsDivisibleBy(%q, %q) to be %v, got %v", test.param1, test.param2, test.expected, actual) + } + } +} + +// This small example illustrate how to work with IsDivisibleBy function. +func ExampleIsDivisibleBy() { + println("1024 is divisible by 64: ", IsDivisibleBy("1024", "64")) +} + +func TestIsByteLength(t *testing.T) { + t.Parallel() + + var tests = []struct { + param1 string + param2 int + param3 int + expected bool + }{ + {"abacaba", 100, -1, false}, + {"abacaba", 1, 3, false}, + {"abacaba", 1, 7, true}, + {"abacaba", 0, 8, true}, + {"\ufff0", 1, 1, false}, + } + for _, test := range tests { + actual := IsByteLength(test.param1, test.param2, test.param3) + if actual != test.expected { + t.Errorf("Expected IsByteLength(%q, %q, %q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) + } + } +} + +func TestIsJSON(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"145", true}, + {"asdf", false}, + {"123:f00", false}, + {"{\"Name\":\"Alice\",\"Body\":\"Hello\",\"Time\":1294706395881547000}", true}, + {"{}", true}, + {"{\"Key\":{\"Key\":{\"Key\":123}}}", true}, + {"[]", true}, + {"null", true}, + } + for _, test := range tests { + actual := IsJSON(test.param) + if actual != test.expected { + t.Errorf("Expected IsJSON(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsMultibyte(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"abc", false}, + {"123", false}, + {"<>@;.-=", false}, + {"ひらがな・カタカナ、.漢字", true}, + {"あいうえお foobar", true}, + {"test@example.com", true}, + {"test@example.com", true}, + {"1234abcDExyz", true}, + {"カタカナ", true}, + } + for _, test := range tests { + actual := IsMultibyte(test.param) + if actual != test.expected { + t.Errorf("Expected IsMultibyte(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsASCII(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"foobar", false}, + {"xyz098", false}, + {"123456", false}, + {"カタカナ", false}, + {"foobar", true}, + {"0987654321", true}, + {"test@example.com", true}, + {"1234abcDEF", true}, + {"", true}, + } + for _, test := range tests { + actual := IsASCII(test.param) + if actual != test.expected { + t.Errorf("Expected IsASCII(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsPrintableASCII(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"foobar", false}, + {"xyz098", false}, + {"123456", false}, + {"カタカナ", false}, + {"foobar", true}, + {"0987654321", true}, + {"test@example.com", true}, + {"1234abcDEF", true}, + {"newline\n", false}, + {"\x19test\x7F", false}, + } + for _, test := range tests { + actual := IsPrintableASCII(test.param) + if actual != test.expected { + t.Errorf("Expected IsPrintableASCII(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsFullWidth(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"abc", false}, + {"abc123", false}, + {"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", false}, + {"ひらがな・カタカナ、.漢字", true}, + {"3ー0 a@com", true}, + {"Fカタカナ゙ᆲ", true}, + {"Good=Parts", true}, + {"", true}, + } + for _, test := range tests { + actual := IsFullWidth(test.param) + if actual != test.expected { + t.Errorf("Expected IsFullWidth(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsHalfWidth(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"あいうえお", false}, + {"0011", false}, + {"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", true}, + {"l-btn_02--active", true}, + {"abc123い", true}, + {"カタカナ゙ᆲ←", true}, + {"", true}, + } + for _, test := range tests { + actual := IsHalfWidth(test.param) + if actual != test.expected { + t.Errorf("Expected IsHalfWidth(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsVariableWidth(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", true}, + {"ひらがなカタカナ漢字ABCDE", true}, + {"3ー0123", true}, + {"Fカタカナ゙ᆲ", true}, + {"", true}, + {"Good=Parts", true}, + {"abc", false}, + {"abc123", false}, + {"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", false}, + {"ひらがな・カタカナ、.漢字", false}, + {"123456", false}, + {"カタカナ゙ᆲ", false}, + } + for _, test := range tests { + actual := IsVariableWidth(test.param) + if actual != test.expected { + t.Errorf("Expected IsVariableWidth(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsUUID(t *testing.T) { + t.Parallel() + + // Tests without version + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false}, + {"a987fbc94bed3078cf079141ba07c9f3", false}, + {"934859", false}, + {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false}, + {"aaaaaaaa-1111-1111-aaag-111111111111", false}, + {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, + } + for _, test := range tests { + actual := IsUUID(test.param) + if actual != test.expected { + t.Errorf("Expected IsUUID(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // UUID ver. 3 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"412452646", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false}, + {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, + } + for _, test := range tests { + actual := IsUUIDv3(test.param) + if actual != test.expected { + t.Errorf("Expected IsUUIDv3(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // UUID ver. 4 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false}, + {"934859", false}, + {"57b73598-8764-4ad0-a76a-679bb6640eb1", true}, + {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true}, + } + for _, test := range tests { + actual := IsUUIDv4(test.param) + if actual != test.expected { + t.Errorf("Expected IsUUIDv4(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // UUID ver. 5 + tests = []struct { + param string + expected bool + }{ + + {"", false}, + {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"9c858901-8a57-4791-81fe-4c455b099bc9", false}, + {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, + {"987fbc97-4bed-5078-af07-9141ba07c9f3", true}, + {"987fbc97-4bed-5078-9f07-9141ba07c9f3", true}, + } + for _, test := range tests { + actual := IsUUIDv5(test.param) + if actual != test.expected { + t.Errorf("Expected IsUUIDv5(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsCreditCard(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"foo", false}, + {"5398228707871528", false}, + {"375556917985515", true}, + {"36050234196908", true}, + {"4716461583322103", true}, + {"4716-2210-5188-5662", true}, + {"4929 7226 5379 7141", true}, + {"5398228707871527", true}, + } + for _, test := range tests { + actual := IsCreditCard(test.param) + if actual != test.expected { + t.Errorf("Expected IsCreditCard(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsISBN(t *testing.T) { + t.Parallel() + + // Without version + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"foo", false}, + {"3836221195", true}, + {"1-61729-085-8", true}, + {"3 423 21412 0", true}, + {"3 401 01319 X", true}, + {"9784873113685", true}, + {"978-4-87311-368-5", true}, + {"978 3401013190", true}, + {"978-3-8362-2119-1", true}, + } + for _, test := range tests { + actual := IsISBN(test.param, -1) + if actual != test.expected { + t.Errorf("Expected IsISBN(%q, -1) to be %v, got %v", test.param, test.expected, actual) + } + } + + // ISBN 10 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"foo", false}, + {"3423214121", false}, + {"978-3836221191", false}, + {"3-423-21412-1", false}, + {"3 423 21412 1", false}, + {"3836221195", true}, + {"1-61729-085-8", true}, + {"3 423 21412 0", true}, + {"3 401 01319 X", true}, + } + for _, test := range tests { + actual := IsISBN10(test.param) + if actual != test.expected { + t.Errorf("Expected IsISBN10(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // ISBN 13 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"foo", false}, + {"3-8362-2119-5", false}, + {"01234567890ab", false}, + {"978 3 8362 2119 0", false}, + {"9784873113685", true}, + {"978-4-87311-368-5", true}, + {"978 3401013190", true}, + {"978-3-8362-2119-1", true}, + } + for _, test := range tests { + actual := IsISBN13(test.param) + if actual != test.expected { + t.Errorf("Expected IsISBN13(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsDataURI(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true}, + {"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true}, + {"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, + {"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" + + "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" + + "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" + + "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" + + "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" + + "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true}, + {"data:image/png;base64,12345", false}, + {"", false}, + {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, + } + for _, test := range tests { + actual := IsDataURI(test.param) + if actual != test.expected { + t.Errorf("Expected IsDataURI(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsBase64(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true}, + {"Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true}, + {"U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", true}, + {"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" + + "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" + + "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" + + "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" + + "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" + + "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true}, + {"12345", false}, + {"", false}, + {"Vml2YW11cyBmZXJtZtesting123", false}, + } + for _, test := range tests { + actual := IsBase64(test.param) + if actual != test.expected { + t.Errorf("Expected IsBase64(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsISO3166Alpha2(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"ABCD", false}, + {"A", false}, + {"AC", false}, + {"AP", false}, + {"GER", false}, + {"NU", true}, + {"DE", true}, + {"JP", true}, + {"JPN", false}, + {"ZWE", false}, + {"GER", false}, + {"DEU", false}, + } + for _, test := range tests { + actual := IsISO3166Alpha2(test.param) + if actual != test.expected { + t.Errorf("Expected IsISO3166Alpha2(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsISO3166Alpha3(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"ABCD", false}, + {"A", false}, + {"AC", false}, + {"AP", false}, + {"NU", false}, + {"DE", false}, + {"JP", false}, + {"ZWE", true}, + {"JPN", true}, + {"GER", false}, + {"DEU", true}, + } + for _, test := range tests { + actual := IsISO3166Alpha3(test.param) + if actual != test.expected { + t.Errorf("Expected IsISO3166Alpha3(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsISO693Alpha2(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"abcd", false}, + {"a", false}, + {"ac", false}, + {"ap", false}, + {"de", true}, + {"DE", false}, + {"mk", true}, + {"mac", false}, + {"sw", true}, + {"SW", false}, + {"ger", false}, + {"deu", false}, + } + for _, test := range tests { + actual := IsISO693Alpha2(test.param) + if actual != test.expected { + t.Errorf("Expected IsISO693Alpha2(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsISO693Alpha3b(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"abcd", false}, + {"a", false}, + {"ac", false}, + {"ap", false}, + {"de", false}, + {"DE", false}, + {"mkd", false}, + {"mac", true}, + {"sw", false}, + {"SW", false}, + {"ger", true}, + {"deu", false}, + } + for _, test := range tests { + actual := IsISO693Alpha3b(test.param) + if actual != test.expected { + t.Errorf("Expected IsISO693Alpha3b(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsIP(t *testing.T) { + t.Parallel() + + // Without version + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"127.0.0.1", true}, + {"0.0.0.0", true}, + {"255.255.255.255", true}, + {"1.2.3.4", true}, + {"::1", true}, + {"2001:db8:0000:1:1:1:1:1", true}, + {"300.0.0.0", false}, + } + for _, test := range tests { + actual := IsIP(test.param) + if actual != test.expected { + t.Errorf("Expected IsIP(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // IPv4 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"127.0.0.1", true}, + {"0.0.0.0", true}, + {"255.255.255.255", true}, + {"1.2.3.4", true}, + {"::1", false}, + {"2001:db8:0000:1:1:1:1:1", false}, + {"300.0.0.0", false}, + } + for _, test := range tests { + actual := IsIPv4(test.param) + if actual != test.expected { + t.Errorf("Expected IsIPv4(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + // IPv6 + tests = []struct { + param string + expected bool + }{ + {"", false}, + {"127.0.0.1", false}, + {"0.0.0.0", false}, + {"255.255.255.255", false}, + {"1.2.3.4", false}, + {"::1", true}, + {"2001:db8:0000:1:1:1:1:1", true}, + {"300.0.0.0", false}, + } + for _, test := range tests { + actual := IsIPv6(test.param) + if actual != test.expected { + t.Errorf("Expected IsIPv6(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsPort(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"1", true}, + {"65535", true}, + {"0", false}, + {"65536", false}, + {"65538", false}, + } + + for _, test := range tests { + actual := IsPort(test.param) + if actual != test.expected { + t.Errorf("Expected IsPort(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsDNSName(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"localhost", true}, + {"a.bc", true}, + {"a.b.", true}, + {"a.b..", false}, + {"localhost.local", true}, + {"localhost.localdomain.intern", true}, + {"l.local.intern", true}, + {"ru.link.n.svpncloud.com", true}, + {"-localhost", false}, + {"localhost.-localdomain", false}, + {"localhost.localdomain.-int", false}, + {"_localhost", true}, + {"localhost._localdomain", true}, + {"localhost.localdomain._int", true}, + {"lÖcalhost", false}, + {"localhost.lÖcaldomain", false}, + {"localhost.localdomain.üntern", false}, + {"__", true}, + {"localhost/", false}, + {"127.0.0.1", false}, + {"[::1]", false}, + {"50.50.50.50", false}, + {"localhost.localdomain.intern:65535", false}, + {"漢字汉字", false}, + {"www.jubfvq1v3p38i51622y0dvmdk1mymowjyeu26gbtw9andgynj1gg8z3msb1kl5z6906k846pj3sulm4kiyk82ln5teqj9nsht59opr0cs5ssltx78lfyvml19lfq1wp4usbl0o36cmiykch1vywbttcus1p9yu0669h8fj4ll7a6bmop505908s1m83q2ec2qr9nbvql2589adma3xsq2o38os2z3dmfh2tth4is4ixyfasasasefqwe4t2ub2fz1rme.de", false}, + } + + for _, test := range tests { + actual := IsDNSName(test.param) + if actual != test.expected { + t.Errorf("Expected IsDNS(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsHost(t *testing.T) { + t.Parallel() + var tests = []struct { + param string + expected bool + }{ + {"localhost", true}, + {"localhost.localdomain", true}, + {"2001:db8:0000:1:1:1:1:1", true}, + {"::1", true}, + {"play.golang.org", true}, + {"localhost.localdomain.intern:65535", false}, + {"-[::1]", false}, + {"-localhost", false}, + {".localhost", false}, + } + for _, test := range tests { + actual := IsHost(test.param) + if actual != test.expected { + t.Errorf("Expected IsHost(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + +} + +func TestIsDialString(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"localhost.local:1", true}, + {"localhost.localdomain:9090", true}, + {"localhost.localdomain.intern:65535", true}, + {"127.0.0.1:30000", true}, + {"[::1]:80", true}, + {"[1200::AB00:1234::2552:7777:1313]:22", false}, + {"-localhost:1", false}, + {"localhost.-localdomain:9090", false}, + {"localhost.localdomain.-int:65535", false}, + {"localhost.loc:100000", false}, + {"漢字汉字:2", false}, + {"www.jubfvq1v3p38i51622y0dvmdk1mymowjyeu26gbtw9andgynj1gg8z3msb1kl5z6906k846pj3sulm4kiyk82ln5teqj9nsht59opr0cs5ssltx78lfyvml19lfq1wp4usbl0o36cmiykch1vywbttcus1p9yu0669h8fj4ll7a6bmop505908s1m83q2ec2qr9nbvql2589adma3xsq2o38os2z3dmfh2tth4is4ixyfasasasefqwe4t2ub2fz1rme.de:20000", false}, + } + + for _, test := range tests { + actual := IsDialString(test.param) + if actual != test.expected { + t.Errorf("Expected IsDialString(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsMAC(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"3D:F2:C9:A6:B3:4F", true}, + {"3D-F2-C9-A6-B3:4F", false}, + {"123", false}, + {"", false}, + {"abacaba", false}, + } + for _, test := range tests { + actual := IsMAC(test.param) + if actual != test.expected { + t.Errorf("Expected IsMAC(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestFilePath(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + osType int + }{ + {"c:\\" + strings.Repeat("a", 32767), true, Win}, //See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath + {"c:\\" + strings.Repeat("a", 32768), false, Win}, + {"c:\\path\\file (x86)\bar", true, Win}, + {"c:\\path\\file", true, Win}, + {"c:\\path\\file:exe", false, Unknown}, + {"C:\\", true, Win}, + {"c:\\path\\file\\", true, Win}, + {"c:/path/file/", false, Unknown}, + {"/path/file/", true, Unix}, + {"/path/file:SAMPLE/", true, Unix}, + {"/path/file:/.txt", true, Unix}, + {"/path", true, Unix}, + {"/path/__bc/file.txt", true, Unix}, + {"/path/a--ac/file.txt", true, Unix}, + {"/_path/file.txt", true, Unix}, + {"/path/__bc/file.txt", true, Unix}, + {"/path/a--ac/file.txt", true, Unix}, + {"/__path/--file.txt", true, Unix}, + {"/path/a bc", true, Unix}, + } + for _, test := range tests { + actual, osType := IsFilePath(test.param) + if actual != test.expected || osType != test.osType { + t.Errorf("Expected IsFilePath(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsLatitude(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"-90.000", true}, + {"+90", true}, + {"47.1231231", true}, + {"+99.9", false}, + {"108", false}, + } + for _, test := range tests { + actual := IsLatitude(test.param) + if actual != test.expected { + t.Errorf("Expected IsLatitude(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsLongitude(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"-180.000", true}, + {"180.1", false}, + {"+73.234", true}, + {"+382.3811", false}, + {"23.11111111", true}, + } + for _, test := range tests { + actual := IsLongitude(test.param) + if actual != test.expected { + t.Errorf("Expected IsLongitude(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsSSN(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"00-90-8787", false}, + {"66690-76", false}, + {"191 60 2869", true}, + {"191-60-2869", true}, + } + for _, test := range tests { + actual := IsSSN(test.param) + if actual != test.expected { + t.Errorf("Expected IsSSN(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsMongoID(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"507f1f77bcf86cd799439011", true}, + {"507f1f77bcf86cd7994390", false}, + {"507f1f77bcf86cd79943901z", false}, + {"507f1f77bcf86cd799439011 ", false}, + {"", false}, + } + for _, test := range tests { + actual := IsMongoID(test.param) + if actual != test.expected { + t.Errorf("Expected IsMongoID(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsSemver(t *testing.T) { + t.Parallel() + var tests = []struct { + param string + expected bool + }{ + {"v1.0.0", true}, + {"1.0.0", true}, + {"1.1.01", false}, + {"1.01.0", false}, + {"01.1.0", false}, + {"v1.1.01", false}, + {"v1.01.0", false}, + {"v01.1.0", false}, + {"1.0.0-alpha", true}, + {"1.0.0-alpha.1", true}, + {"1.0.0-0.3.7", true}, + {"1.0.0-0.03.7", false}, + {"1.0.0-00.3.7", false}, + {"1.0.0-x.7.z.92", true}, + {"1.0.0-alpha+001", true}, + {"1.0.0+20130313144700", true}, + {"1.0.0-beta+exp.sha.5114f85", true}, + {"1.0.0-beta+exp.sha.05114f85", true}, + {"1.0.0-+beta", false}, + {"1.0.0-b+-9+eta", false}, + {"v+1.8.0-b+-9+eta", false}, + } + for _, test := range tests { + actual := IsSemver(test.param) + if actual != test.expected { + t.Errorf("Expected IsSemver(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsTime(t *testing.T) { + t.Parallel() + var tests = []struct { + param string + format string + expected bool + }{ + {"2016-12-31 11:00", time.RFC3339, false}, + {"2016-12-31 11:00:00", time.RFC3339, false}, + {"2016-12-31T11:00", time.RFC3339, false}, + {"2016-12-31T11:00:00", time.RFC3339, false}, + {"2016-12-31T11:00:00Z", time.RFC3339, true}, + {"2016-12-31T11:00:00+01:00", time.RFC3339, true}, + {"2016-12-31T11:00:00-01:00", time.RFC3339, true}, + {"2016-12-31T11:00:00.05Z", time.RFC3339, true}, + {"2016-12-31T11:00:00.05-01:00", time.RFC3339, true}, + {"2016-12-31T11:00:00.05+01:00", time.RFC3339, true}, + } + for _, test := range tests { + actual := IsTime(test.param, test.format) + if actual != test.expected { + t.Errorf("Expected IsTime(%q, time.RFC3339) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsRFC3339(t *testing.T) { + t.Parallel() + var tests = []struct { + param string + expected bool + }{ + {"2016-12-31 11:00", false}, + {"2016-12-31 11:00:00", false}, + {"2016-12-31T11:00", false}, + {"2016-12-31T11:00:00", false}, + {"2016-12-31T11:00:00Z", true}, + {"2016-12-31T11:00:00+01:00", true}, + {"2016-12-31T11:00:00-01:00", true}, + {"2016-12-31T11:00:00.05Z", true}, + {"2016-12-31T11:00:00.05-01:00", true}, + {"2016-12-31T11:00:00.05+01:00", true}, + } + for _, test := range tests { + actual := IsRFC3339(test.param) + if actual != test.expected { + t.Errorf("Expected IsRFC3339(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsISO4217(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"ABCD", false}, + {"A", false}, + {"ZZZ", false}, + {"usd", false}, + {"USD", true}, + } + for _, test := range tests { + actual := IsISO4217(test.param) + if actual != test.expected { + t.Errorf("Expected IsISO4217(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestByteLength(t *testing.T) { + t.Parallel() + + var tests = []struct { + value string + min string + max string + expected bool + }{ + {"123456", "0", "100", true}, + {"1239999", "0", "0", false}, + {"1239asdfasf99", "100", "200", false}, + {"1239999asdff29", "10", "30", true}, + {"你", "0", "1", false}, + } + for _, test := range tests { + actual := ByteLength(test.value, test.min, test.max) + if actual != test.expected { + t.Errorf("Expected ByteLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual) + } + } +} + +func TestRuneLength(t *testing.T) { + t.Parallel() + + var tests = []struct { + value string + min string + max string + expected bool + }{ + {"123456", "0", "100", true}, + {"1239999", "0", "0", false}, + {"1239asdfasf99", "100", "200", false}, + {"1239999asdff29", "10", "30", true}, + {"你", "0", "1", true}, + } + for _, test := range tests { + actual := RuneLength(test.value, test.min, test.max) + if actual != test.expected { + t.Errorf("Expected RuneLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual) + } + } +} + +func TestStringLength(t *testing.T) { + t.Parallel() + + var tests = []struct { + value string + min string + max string + expected bool + }{ + {"123456", "0", "100", true}, + {"1239999", "0", "0", false}, + {"1239asdfasf99", "100", "200", false}, + {"1239999asdff29", "10", "30", true}, + {"あいうえお", "0", "5", true}, + {"あいうえおか", "0", "5", false}, + {"あいうえお", "0", "0", false}, + {"あいうえ", "5", "10", false}, + } + for _, test := range tests { + actual := StringLength(test.value, test.min, test.max) + if actual != test.expected { + t.Errorf("Expected StringLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual) + } + } +} + +func TestIsIn(t *testing.T) { + t.Parallel() + + var tests = []struct { + value string + params []string + expected bool + }{ + {"PRESENT", []string{"PRESENT"}, true}, + {"PRESENT", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, true}, + {"PRÉSENTE", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, true}, + {"PRESENT", []string{}, false}, + {"PRESENT", nil, false}, + {"ABSENT", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, false}, + {"", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, false}, + } + for _, test := range tests { + actual := IsIn(test.value, test.params...) + if actual != test.expected { + t.Errorf("Expected IsIn(%s, %v) to be %v, got %v", test.value, test.params, test.expected, actual) + } + } +} + +type Address struct { + Street string `valid:"-"` + Zip string `json:"zip" valid:"numeric,required"` +} + +type User struct { + Name string `valid:"required"` + Email string `valid:"required,email"` + Password string `valid:"required"` + Age int `valid:"required,numeric,@#\u0000"` + Home *Address + Work []Address +} + +type UserValid struct { + Name string `valid:"required"` + Email string `valid:"required,email"` + Password string `valid:"required"` + Age int `valid:"required"` + Home *Address + Work []Address `valid:"required"` +} + +type PrivateStruct struct { + privateField string `valid:"required,alpha,d_k"` + NonZero int + ListInt []int + ListString []string `valid:"alpha"` + Work [2]Address + Home Address + Map map[string]Address +} + +type NegationStruct struct { + NotInt string `valid:"!int"` + Int string `valid:"int"` +} + +type LengthStruct struct { + Length string `valid:"length(10|20)"` +} + +type StringLengthStruct struct { + Length string `valid:"stringlength(10|20)"` +} + +type StringMatchesStruct struct { + StringMatches string `valid:"matches(^[0-9]{3}$)"` +} + +// TODO: this testcase should be fixed +// type StringMatchesComplexStruct struct { +// StringMatches string `valid:"matches(^\\$\\([\"']\\w+[\"']\\)$)"` +// } + +type IsInStruct struct { + IsIn string `valid:"in(PRESENT|PRÉSENTE|NOTABSENT)"` +} + +type Post struct { + Title string `valid:"alpha,required"` + Message string `valid:"ascii"` + AuthorIP string `valid:"ipv4"` +} + +type MissingValidationDeclarationStruct struct { + Name string `` + Email string `valid:"required,email"` +} + +type FieldsRequiredByDefaultButExemptStruct struct { + Name string `valid:"-"` + Email string `valid:"email"` +} + +type FieldsRequiredByDefaultButExemptOrOptionalStruct struct { + Name string `valid:"-"` + Email string `valid:"optional,email"` +} + +type MessageWithSeveralFieldsStruct struct { + Title string `valid:"length(1|10)"` + Body string `valid:"length(1|10)"` +} + +func TestValidateMissingValidationDeclarationStruct(t *testing.T) { + var tests = []struct { + param MissingValidationDeclarationStruct + expected bool + }{ + {MissingValidationDeclarationStruct{}, false}, + {MissingValidationDeclarationStruct{Name: "TEST", Email: "test@example.com"}, false}, + } + SetFieldsRequiredByDefault(true) + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } + SetFieldsRequiredByDefault(false) +} + +func TestFieldsRequiredByDefaultButExemptStruct(t *testing.T) { + var tests = []struct { + param FieldsRequiredByDefaultButExemptStruct + expected bool + }{ + {FieldsRequiredByDefaultButExemptStruct{}, false}, + {FieldsRequiredByDefaultButExemptStruct{Name: "TEST"}, false}, + {FieldsRequiredByDefaultButExemptStruct{Email: ""}, false}, + {FieldsRequiredByDefaultButExemptStruct{Email: "test@example.com"}, true}, + } + SetFieldsRequiredByDefault(true) + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } + SetFieldsRequiredByDefault(false) +} + +func TestFieldsRequiredByDefaultButExemptOrOptionalStruct(t *testing.T) { + var tests = []struct { + param FieldsRequiredByDefaultButExemptOrOptionalStruct + expected bool + }{ + {FieldsRequiredByDefaultButExemptOrOptionalStruct{}, true}, + {FieldsRequiredByDefaultButExemptOrOptionalStruct{Name: "TEST"}, true}, + {FieldsRequiredByDefaultButExemptOrOptionalStruct{Email: ""}, true}, + {FieldsRequiredByDefaultButExemptOrOptionalStruct{Email: "test@example.com"}, true}, + {FieldsRequiredByDefaultButExemptOrOptionalStruct{Email: "test@example"}, false}, + } + SetFieldsRequiredByDefault(true) + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } + SetFieldsRequiredByDefault(false) +} + +func TestInvalidValidator(t *testing.T) { + type InvalidStruct struct { + Field int `valid:"someInvalidValidator"` + } + + invalidStruct := InvalidStruct{1} + if valid, err := ValidateStruct(&invalidStruct); valid || err == nil || + err.Error() != `Field: The following validator is invalid or can't be applied to the field: "someInvalidValidator"` { + t.Errorf("Got an unexpected result for struct with invalid validator: %t %s", valid, err) + } +} + +func TestCustomValidator(t *testing.T) { + type ValidStruct struct { + Field int `valid:"customTrueValidator"` + } + + type InvalidStruct struct { + Field int `valid:"customFalseValidator~Custom validator error"` + } + + type StructWithCustomAndBuiltinValidator struct { + Field int `valid:"customTrueValidator,required"` + } + + if valid, err := ValidateStruct(&ValidStruct{Field: 1}); !valid || err != nil { + t.Errorf("Got an unexpected result for struct with custom always true validator: %t %s", valid, err) + } + + if valid, err := ValidateStruct(&InvalidStruct{Field: 1}); valid || err == nil || err.Error() != "Custom validator error" { + t.Errorf("Got an unexpected result for struct with custom always false validator: %t %s", valid, err) + } + + mixedStruct := StructWithCustomAndBuiltinValidator{} + if valid, err := ValidateStruct(&mixedStruct); valid || err == nil || err.Error() != "Field: non zero value required" { + t.Errorf("Got an unexpected result for invalid struct with custom and built-in validators: %t %s", valid, err) + } + + mixedStruct.Field = 1 + if valid, err := ValidateStruct(&mixedStruct); !valid || err != nil { + t.Errorf("Got an unexpected result for valid struct with custom and built-in validators: %t %s", valid, err) + } +} + +type CustomByteArray [6]byte + +type StructWithCustomByteArray struct { + ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` + Email string `valid:"email"` + CustomMinLength int `valid:"-"` +} + +func TestStructWithCustomByteArray(t *testing.T) { + t.Parallel() + + // add our custom byte array validator that fails when the byte array is pristine (all zeroes) + CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { + switch v := o.(type) { + case StructWithCustomByteArray: + if len(v.Email) > 0 { + if v.Email != "test@example.com" { + t.Errorf("v.Email should have been 'test@example.com' but was '%s'", v.Email) + } + } + default: + t.Errorf("Context object passed to custom validator should have been a StructWithCustomByteArray but was %T (%+v)", o, o) + } + + switch v := i.(type) { + case CustomByteArray: + for _, e := range v { // check if v is empty, i.e. all zeroes + if e != 0 { + return true + } + } + } + return false + })) + CustomTypeTagMap.Set("customMinLengthValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { + switch v := o.(type) { + case StructWithCustomByteArray: + return len(v.ID) >= v.CustomMinLength + } + return false + })) + testCustomByteArray := CustomByteArray{'1', '2', '3', '4', '5', '6'} + var tests = []struct { + param StructWithCustomByteArray + expected bool + }{ + {StructWithCustomByteArray{}, false}, + {StructWithCustomByteArray{Email: "test@example.com"}, false}, + {StructWithCustomByteArray{ID: testCustomByteArray, Email: "test@example.com"}, true}, + {StructWithCustomByteArray{ID: testCustomByteArray, Email: "test@example.com", CustomMinLength: 7}, false}, + } + SetFieldsRequiredByDefault(true) + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } + SetFieldsRequiredByDefault(false) +} + +func TestValidateNegationStruct(t *testing.T) { + var tests = []struct { + param NegationStruct + expected bool + }{ + {NegationStruct{"a1", "11"}, true}, + {NegationStruct{"email@email.email", "11"}, true}, + {NegationStruct{"123456----", "11"}, true}, + {NegationStruct{"::1", "11"}, true}, + {NegationStruct{"123.123", "11"}, true}, + {NegationStruct{"a1", "a1"}, false}, + {NegationStruct{"11", "a1"}, false}, + {NegationStruct{"11", "11"}, false}, + } + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } +} + +func TestLengthStruct(t *testing.T) { + var tests = []struct { + param interface{} + expected bool + }{ + {LengthStruct{"11111"}, false}, + {LengthStruct{"11111111111111111110000000000000000"}, false}, + {LengthStruct{"11dfffdf0099"}, true}, + } + + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } +} + +func TestStringLengthStruct(t *testing.T) { + var tests = []struct { + param interface{} + expected bool + }{ + {StringLengthStruct{"11111"}, false}, + {StringLengthStruct{"11111111111111111110000000000000000"}, false}, + {StringLengthStruct{"11dfffdf0099"}, true}, + {StringLengthStruct{"あいうえお"}, false}, + {StringLengthStruct{"あいうえおかきくけこ"}, true}, + {StringLengthStruct{"あいうえおかきくけこさしすせそたちつてと"}, true}, + {StringLengthStruct{"あいうえおかきくけこさしすせそたちつてとな"}, false}, + } + + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } +} + +func TestStringMatchesStruct(t *testing.T) { + var tests = []struct { + param interface{} + expected bool + }{ + {StringMatchesStruct{"123"}, true}, + {StringMatchesStruct{"123456"}, false}, + {StringMatchesStruct{"123abcd"}, false}, + } + + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } +} + +func TestIsInStruct(t *testing.T) { + var tests = []struct { + param interface{} + expected bool + }{ + {IsInStruct{"PRESENT"}, true}, + {IsInStruct{""}, true}, + {IsInStruct{" "}, false}, + {IsInStruct{"ABSENT"}, false}, + } + + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } +} + +func TestRequiredIsInStruct(t *testing.T) { + type RequiredIsInStruct struct { + IsIn string `valid:"in(PRESENT|PRÉSENTE|NOTABSENT),required"` + } + + var tests = []struct { + param interface{} + expected bool + }{ + {RequiredIsInStruct{"PRESENT"}, true}, + {RequiredIsInStruct{""}, false}, + {RequiredIsInStruct{" "}, false}, + {RequiredIsInStruct{"ABSENT"}, false}, + } + + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } +} + +func TestEmptyRequiredIsInStruct(t *testing.T) { + type EmptyRequiredIsInStruct struct { + IsIn string `valid:"in(),required"` + } + + var tests = []struct { + param interface{} + expected bool + }{ + {EmptyRequiredIsInStruct{"PRESENT"}, false}, + {EmptyRequiredIsInStruct{""}, false}, + {EmptyRequiredIsInStruct{" "}, false}, + {EmptyRequiredIsInStruct{"ABSENT"}, false}, + } + + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } +} + +func TestFunkyIsInStruct(t *testing.T) { + type FunkyIsInStruct struct { + IsIn string `valid:"in(PRESENT|| |PRÉSENTE|NOTABSENT)"` + } + + var tests = []struct { + param interface{} + expected bool + }{ + {FunkyIsInStruct{"PRESENT"}, true}, + {FunkyIsInStruct{""}, true}, + {FunkyIsInStruct{" "}, true}, + {FunkyIsInStruct{"ABSENT"}, false}, + } + + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } +} + +// TODO: test case broken +// func TestStringMatchesComplexStruct(t *testing.T) { +// var tests = []struct { +// param interface{} +// expected bool +// }{ +// {StringMatchesComplexStruct{"$()"}, false}, +// {StringMatchesComplexStruct{"$('AZERTY')"}, true}, +// {StringMatchesComplexStruct{`$("AZERTY")`}, true}, +// {StringMatchesComplexStruct{`$("")`}, false}, +// {StringMatchesComplexStruct{"AZERTY"}, false}, +// {StringMatchesComplexStruct{"$AZERTY"}, false}, +// } + +// for _, test := range tests { +// actual, err := ValidateStruct(test.param) +// if actual != test.expected { +// t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) +// if err != nil { +// t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) +// } +// } +// } +// } + +func TestValidateStruct(t *testing.T) { + + var tests = []struct { + param interface{} + expected bool + }{ + {User{"John", "john@yahoo.com", "123G#678", 20, &Address{"Street", "123456"}, []Address{{"Street", "123456"}, {"Street", "123456"}}}, false}, + {User{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false}, + {User{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false}, + {UserValid{"John", "john@yahoo.com", "123G#678", 20, &Address{"Street", "123456"}, []Address{{"Street", "123456"}, {"Street", "123456"}}}, true}, + {UserValid{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{}}, false}, + {UserValid{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false}, + {UserValid{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false}, + {nil, true}, + {User{"John", "john@yahoo.com", "123G#678", 0, &Address{"Street", "123456"}, []Address{}}, false}, + {"im not a struct", false}, + } + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } + + TagMap["d_k"] = Validator(func(str string) bool { + return str == "d_k" + }) + result, err := ValidateStruct(PrivateStruct{"d_k", 0, []int{1, 2}, []string{"hi", "super"}, [2]Address{{"Street", "123456"}, + {"Street", "123456"}}, Address{"Street", "123456"}, map[string]Address{"address": {"Street", "123456"}}}) + if result != true { + t.Log("Case ", 6, ": expected ", true, " when result is ", result) + t.Error(err) + t.FailNow() + } +} + +type testByteArray [8]byte +type testByteMap map[byte]byte +type testByteSlice []byte +type testStringStringMap map[string]string +type testStringIntMap map[string]int + +func TestRequired(t *testing.T) { + + testString := "foobar" + var tests = []struct { + param interface{} + expected bool + }{ + { + struct { + Pointer *string `valid:"required"` + }{}, + false, + }, + { + struct { + Pointer *string `valid:"required"` + }{ + Pointer: &testString, + }, + true, + }, + { + struct { + Addr Address `valid:"required"` + }{}, + false, + }, + { + struct { + Addr Address `valid:"required"` + }{ + Addr: Address{"", "123"}, + }, + true, + }, + { + struct { + Pointer *Address `valid:"required"` + }{}, + false, + }, + { + struct { + Pointer *Address `valid:"required"` + }{ + Pointer: &Address{"", "123"}, + }, + true, + }, + { + struct { + TestByteArray testByteArray `valid:"required"` + }{}, + false, + }, + { + struct { + TestByteArray testByteArray `valid:"required"` + }{ + testByteArray{}, + }, + false, + }, + { + struct { + TestByteArray testByteArray `valid:"required"` + }{ + testByteArray{'1', '2', '3', '4', '5', '6', '7', 'A'}, + }, + true, + }, + { + struct { + TestByteMap testByteMap `valid:"required"` + }{}, + false, + }, + { + struct { + TestByteSlice testByteSlice `valid:"required"` + }{}, + false, + }, + { + struct { + TestStringStringMap testStringStringMap `valid:"required"` + }{ + testStringStringMap{"test": "test"}, + }, + true, + }, + { + struct { + TestIntMap testStringIntMap `valid:"required"` + }{ + testStringIntMap{"test": 42}, + }, + true, + }, + } + for _, test := range tests { + actual, err := ValidateStruct(test.param) + if actual != test.expected { + t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) + if err != nil { + t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) + } + } + } +} + +func TestErrorByField(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected string + }{ + {"message", ""}, + {"Message", ""}, + {"title", ""}, + {"Title", "My123 does not validate as alpha"}, + {"AuthorIP", "123 does not validate as ipv4"}, + } + post := &Post{"My123", "duck13126", "123"} + _, err := ValidateStruct(post) + + for _, test := range tests { + actual := ErrorByField(err, test.param) + if actual != test.expected { + t.Errorf("Expected ErrorByField(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestErrorsByField(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected string + }{ + {"Title", "My123 does not validate as alpha"}, + {"AuthorIP", "123 does not validate as ipv4"}, + } + post := &Post{Title: "My123", Message: "duck13126", AuthorIP: "123"} + _, err := ValidateStruct(post) + errs := ErrorsByField(err) + if len(errs) != 2 { + t.Errorf("There should only be 2 errors but got %v", len(errs)) + } + + for _, test := range tests { + if actual, ok := errs[test.param]; !ok || actual != test.expected { + t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + tests = []struct { + param string + expected string + }{ + {"Title", ";:;message;:; does not validate as length(1|10)"}, + {"Body", ";:;message;:; does not validate as length(1|10)"}, + } + + message := &MessageWithSeveralFieldsStruct{Title: ";:;message;:;", Body: ";:;message;:;"} + _, err = ValidateStruct(message) + errs = ErrorsByField(err) + if len(errs) != 2 { + t.Errorf("There should only be 2 errors but got %v", len(errs)) + } + + for _, test := range tests { + if actual, ok := errs[test.param]; !ok || actual != test.expected { + t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + tests = []struct { + param string + expected string + }{ + {"CustomField", "An error occurred"}, + } + + err = Error{"CustomField", fmt.Errorf("An error occurred"), false, "hello"} + errs = ErrorsByField(err) + + if len(errs) != 1 { + t.Errorf("There should only be 1 errors but got %v", len(errs)) + } + + for _, test := range tests { + if actual, ok := errs[test.param]; !ok || actual != test.expected { + t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual) + } + } + + type StructWithCustomValidation struct { + Email string `valid:"email"` + ID string `valid:"falseValidation"` + } + + CustomTypeTagMap.Set("falseValidation", CustomTypeValidator(func(i interface{}, o interface{}) bool { + return false + })) + + tests = []struct { + param string + expected string + }{ + {"Email", "My123 does not validate as email"}, + {"ID", "duck13126 does not validate as falseValidation"}, + } + s := &StructWithCustomValidation{Email: "My123", ID: "duck13126"} + _, err = ValidateStruct(s) + errs = ErrorsByField(err) + if len(errs) != 2 { + t.Errorf("There should only be 2 errors but got %v", len(errs)) + } + + for _, test := range tests { + if actual, ok := errs[test.param]; !ok || actual != test.expected { + t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestValidateStructPointers(t *testing.T) { + // Struct which uses pointers for values + type UserWithPointers struct { + Name *string `valid:"-"` + Email *string `valid:"email"` + FavoriteFood *string `valid:"length(0|32)"` + Nerd *bool `valid:"-"` + } + + var tests = []struct { + param string + expected string + }{ + {"Name", ""}, + {"Email", "invalid does not validate as email"}, + {"FavoriteFood", ""}, + {"Nerd", ""}, + } + + name := "Herman" + email := "invalid" + food := "Pizza" + nerd := true + user := &UserWithPointers{&name, &email, &food, &nerd} + _, err := ValidateStruct(user) + + for _, test := range tests { + actual := ErrorByField(err, test.param) + if actual != test.expected { + t.Errorf("Expected ErrorByField(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func ExampleValidateStruct() { + type Post struct { + Title string `valid:"alphanum,required"` + Message string `valid:"duck,ascii"` + AuthorIP string `valid:"ipv4"` + } + post := &Post{"My Example Post", "duck", "123.234.54.3"} + + //Add your own struct validation tags + TagMap["duck"] = Validator(func(str string) bool { + return str == "duck" + }) + + result, err := ValidateStruct(post) + if err != nil { + println("error: " + err.Error()) + } + println(result) +} + +func TestIsCIDR(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"193.168.3.20/7", true}, + {"2001:db8::/32", true}, + {"2001:0db8:85a3:0000:0000:8a2e:0370:7334/64", true}, + {"193.138.3.20/60", false}, + {"500.323.2.23/43", false}, + {"", false}, + } + for _, test := range tests { + actual := IsCIDR(test.param) + if actual != test.expected { + t.Errorf("Expected IsCIDR(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestOptionalCustomValidators(t *testing.T) { + + CustomTypeTagMap.Set("f2", CustomTypeValidator(func(i interface{}, o interface{}) bool { + return false + })) + + var val struct { + WithCustomError string `valid:"f2~boom,optional"` + WithoutCustomError string `valid:"f2,optional"` + OptionalFirst string `valid:"optional,f2"` + } + + ok, err := ValidateStruct(val) + + if err != nil { + t.Errorf("Expected nil err with optional validation, got %v", err) + } + + if !ok { + t.Error("Expected validation to return true, got false") + } +} + +func TestJSONValidator(t *testing.T) { + + var val struct { + WithJSONName string `json:"with_json_name" valid:"-,required"` + WithoutJSONName string `valid:"-,required"` + WithJSONOmit string `json:"with_other_json_name,omitempty" valid:"-,required"` + WithJSONOption string `json:",omitempty" valid:"-,required"` + } + + _, err := ValidateStruct(val) + + if err == nil { + t.Error("Expected error but got no error") + } + + if Contains(err.Error(), "WithJSONName") { + t.Errorf("Expected error message to contain with_json_name but actual error is: %s", err.Error()) + } + + if Contains(err.Error(), "WithoutJSONName") == false { + t.Errorf("Expected error message to contain WithoutJSONName but actual error is: %s", err.Error()) + } + + if Contains(err.Error(), "omitempty") { + t.Errorf("Expected error message to not contain ',omitempty' but actual error is: %s", err.Error()) + } +} + +func TestValidatorIncludedInError(t *testing.T) { + post := Post{ + Title: "", + Message: "👍", + AuthorIP: "xyz", + } + + validatorMap := map[string]string{ + "Title": "required", + "Message": "ascii", + "AuthorIP": "ipv4", + } + + ok, errors := ValidateStruct(post) + if ok { + t.Errorf("expected validation to fail %v", ok) + } + + for _, e := range errors.(Errors) { + casted := e.(Error) + if validatorMap[casted.Name] != casted.Validator { + t.Errorf("expected validator for %s to be %s, but was %s", casted.Name, validatorMap[casted.Name], casted.Validator) + } + } + + // check to make sure that validators with arguments (like length(1|10)) don't include the arguments + // in the validator name + message := MessageWithSeveralFieldsStruct{ + Title: "", + Body: "asdfasdfasdfasdfasdf", + } + + validatorMap = map[string]string{ + "Title": "length", + "Body": "length", + } + + ok, errors = ValidateStruct(message) + if ok { + t.Errorf("expected validation to fail, %v", ok) + } + + for _, e := range errors.(Errors) { + casted := e.(Error) + if validatorMap[casted.Name] != casted.Validator { + t.Errorf("expected validator for %s to be %s, but was %s", casted.Name, validatorMap[casted.Name], casted.Validator) + } + } + + // make sure validators with custom messages don't show up in the validator string + type CustomMessage struct { + Text string `valid:"length(1|10)~Custom message"` + } + cs := CustomMessage{Text: "asdfasdfasdfasdf"} + + ok, errors = ValidateStruct(&cs) + if ok { + t.Errorf("expected validation to fail, %v", ok) + } + + validator := errors.(Errors)[0].(Error).Validator + if validator != "length" { + t.Errorf("expected validator for Text to be length, but was %s", validator) + } + +} diff --git a/vendor/github.com/asaskevich/govalidator/wercker.yml b/vendor/github.com/asaskevich/govalidator/wercker.yml new file mode 100644 index 0000000000..cac7a5fcf0 --- /dev/null +++ b/vendor/github.com/asaskevich/govalidator/wercker.yml @@ -0,0 +1,15 @@ +box: golang +build: + steps: + - setup-go-workspace + + - script: + name: go get + code: | + go version + go get -t ./... + + - script: + name: go test + code: | + go test -race ./... diff --git a/vendor/github.com/go-openapi/analysis/.github/CONTRIBUTING.md b/vendor/github.com/go-openapi/analysis/.github/CONTRIBUTING.md new file mode 100644 index 0000000000..7dea4240d7 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/.github/CONTRIBUTING.md @@ -0,0 +1,117 @@ +## Contribution Guidelines + +### Pull requests are always welcome + +We are always thrilled to receive pull requests, and do our best to +process them as fast as possible. Not sure if that typo is worth a pull +request? Do it! We will appreciate it. + +If your pull request is not accepted on the first try, don't be +discouraged! If there's a problem with the implementation, hopefully you +received feedback on what to improve. + +We're trying very hard to keep go-swagger lean and focused. We don't want it +to do everything for everybody. This means that we might decide against +incorporating a new feature. However, there might be a way to implement +that feature *on top of* go-swagger. + + +### Conventions + +Fork the repo and make changes on your fork in a feature branch: + +- If it's a bugfix branch, name it XXX-something where XXX is the number of the + issue +- If it's a feature branch, create an enhancement issue to announce your + intentions, and name it XXX-something where XXX is the number of the issue. + +Submit unit tests for your changes. Go has a great test framework built in; use +it! Take a look at existing tests for inspiration. Run the full test suite on +your branch before submitting a pull request. + +Update the documentation when creating or modifying features. Test +your documentation changes for clarity, concision, and correctness, as +well as a clean documentation build. See ``docs/README.md`` for more +information on building the docs and how docs get released. + +Write clean code. Universally formatted code promotes ease of writing, reading, +and maintenance. Always run `gofmt -s -w file.go` on each changed file before +committing your changes. Most editors have plugins that do this automatically. + +Pull requests descriptions should be as clear as possible and include a +reference to all the issues that they address. + +Pull requests must not contain commits from other users or branches. + +Commit messages must start with a capitalized and short summary (max. 50 +chars) written in the imperative, followed by an optional, more detailed +explanatory text which is separated from the summary by an empty line. + +Code review comments may be added to your pull request. Discuss, then make the +suggested modifications and push additional commits to your feature branch. Be +sure to post a comment after pushing. The new commits will show up in the pull +request automatically, but the reviewers will not be notified unless you +comment. + +Before the pull request is merged, make sure that you squash your commits into +logical units of work using `git rebase -i` and `git push -f`. After every +commit the test suite should be passing. Include documentation changes in the +same commit so that a revert would remove all traces of the feature or fix. + +Commits that fix or close an issue should include a reference like `Closes #XXX` +or `Fixes #XXX`, which will automatically close the issue when merged. + +### Sign your work + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right to +pass it on as an open-source patch. The rules are pretty simple: if you +can certify the below (from +[developercertificate.org](http://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +You can add the sign off when creating the git commit via `git commit -s`. diff --git a/vendor/github.com/go-openapi/analysis/.gitignore b/vendor/github.com/go-openapi/analysis/.gitignore new file mode 100644 index 0000000000..c96f0b231a --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/.gitignore @@ -0,0 +1,3 @@ +secrets.yml +coverage.out +.idea diff --git a/vendor/github.com/go-openapi/analysis/.travis.yml b/vendor/github.com/go-openapi/analysis/.travis.yml new file mode 100644 index 0000000000..3aa42ab3a6 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/.travis.yml @@ -0,0 +1,18 @@ +language: go +go: +- 1.7 +install: +- go get -u github.com/stretchr/testify/assert +- go get -u gopkg.in/yaml.v2 +- go get -u github.com/go-openapi/swag +- go get -u github.com/go-openapi/jsonpointer +- go get -u github.com/go-openapi/spec +- go get -u github.com/go-openapi/strfmt +- go get -u github.com/go-openapi/loads/fmts +script: +- go test -v -race -cover -coverprofile=coverage.txt -covermode=atomic ./... +after_success: +- bash <(curl -s https://codecov.io/bash) +notifications: + slack: + secure: Sf7kZf7ZGbnwWUMpffHwMu5A0cHkLK2MYY32LNTPj4+/3qC3Ghl7+9v4TSLOqOlCwdRNjOGblAq7s+GDJed6/xgRQl1JtCi1klzZNrYX4q01pgTPvvGcwbBkIYgeMaPeIRcK9OZnud7sRXdttozgTOpytps2U6Js32ip7uj5mHSg2ub0FwoSJwlS6dbezZ8+eDhoha0F/guY99BEwx8Bd+zROrT2TFGsSGOFGN6wFc7moCqTHO/YkWib13a2QNXqOxCCVBy/lt76Wp+JkeFppjHlzs/2lP3EAk13RIUAaesdEUHvIHrzCyNJEd3/+KO2DzsWOYfpktd+KBCvgaYOsoo7ubdT3IROeAegZdCgo/6xgCEsmFc9ZcqCfN5yNx2A+BZ2Vwmpws+bQ1E1+B5HDzzaiLcYfG4X2O210QVGVDLWsv1jqD+uPYeHY2WRfh5ZsIUFvaqgUEnwHwrK44/8REAhQavt1QAj5uJpsRd7CkRVPWRNK+yIky+wgbVUFEchRNmS55E7QWf+W4+4QZkQi7vUTMc9nbTUu2Es9NfvfudOpM2wZbn98fjpb/qq/nRv6Bk+ca+7XD5/IgNLMbWp2ouDdzbiHLCOfDUiHiDJhLfFZx9Bwo7ZwfzeOlbrQX66bx7xRKYmOe4DLrXhNcpbsMa8qbfxlZRCmYbubB/Y8h4= diff --git a/vendor/github.com/go-openapi/analysis/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/analysis/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..9322b065e3 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at ivan+abuse@flanders.co.nz. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/analysis/LICENSE b/vendor/github.com/go-openapi/analysis/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/go-openapi/analysis/README.md b/vendor/github.com/go-openapi/analysis/README.md new file mode 100644 index 0000000000..d32c30d455 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/README.md @@ -0,0 +1,6 @@ +# OpenAPI initiative analysis [![Build Status](https://travis-ci.org/go-openapi/analysis.svg?branch=master)](https://travis-ci.org/go-openapi/analysis) [![codecov](https://codecov.io/gh/go-openapi/analysis/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/analysis) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) + +[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/analysis/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/analysis?status.svg)](http://godoc.org/github.com/go-openapi/analysis) + + +A foundational library to analyze an OAI specification document for easier reasoning about the content. \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/analyzer.go b/vendor/github.com/go-openapi/analysis/analyzer.go new file mode 100644 index 0000000000..77323a58e3 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/analyzer.go @@ -0,0 +1,785 @@ +// 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 analysis + +import ( + "fmt" + slashpath "path" + "strconv" + "strings" + + "github.com/go-openapi/jsonpointer" + "github.com/go-openapi/spec" + "github.com/go-openapi/swag" +) + +type referenceAnalysis struct { + schemas map[string]spec.Ref + responses map[string]spec.Ref + parameters map[string]spec.Ref + items map[string]spec.Ref + headerItems map[string]spec.Ref + parameterItems map[string]spec.Ref + allRefs map[string]spec.Ref + pathItems map[string]spec.Ref +} + +func (r *referenceAnalysis) addRef(key string, ref spec.Ref) { + r.allRefs["#"+key] = ref +} + +func (r *referenceAnalysis) addItemsRef(key string, items *spec.Items, location string) { + r.items["#"+key] = items.Ref + r.addRef(key, items.Ref) + if location == "header" { + r.headerItems["#"+key] = items.Ref + } else { + r.parameterItems["#"+key] = items.Ref + } +} + +func (r *referenceAnalysis) addSchemaRef(key string, ref SchemaRef) { + r.schemas["#"+key] = ref.Schema.Ref + r.addRef(key, ref.Schema.Ref) +} + +func (r *referenceAnalysis) addResponseRef(key string, resp *spec.Response) { + r.responses["#"+key] = resp.Ref + r.addRef(key, resp.Ref) +} + +func (r *referenceAnalysis) addParamRef(key string, param *spec.Parameter) { + r.parameters["#"+key] = param.Ref + r.addRef(key, param.Ref) +} + +func (r *referenceAnalysis) addPathItemRef(key string, pathItem *spec.PathItem) { + r.pathItems["#"+key] = pathItem.Ref + r.addRef(key, pathItem.Ref) +} + +type patternAnalysis struct { + parameters map[string]string + headers map[string]string + items map[string]string + schemas map[string]string + allPatterns map[string]string +} + +func (p *patternAnalysis) addPattern(key, pattern string) { + p.allPatterns["#"+key] = pattern +} + +func (p *patternAnalysis) addParameterPattern(key, pattern string) { + p.parameters["#"+key] = pattern + p.addPattern(key, pattern) +} + +func (p *patternAnalysis) addHeaderPattern(key, pattern string) { + p.headers["#"+key] = pattern + p.addPattern(key, pattern) +} + +func (p *patternAnalysis) addItemsPattern(key, pattern string) { + p.items["#"+key] = pattern + p.addPattern(key, pattern) +} + +func (p *patternAnalysis) addSchemaPattern(key, pattern string) { + p.schemas["#"+key] = pattern + p.addPattern(key, pattern) +} + +// New takes a swagger spec object and returns an analyzed spec document. +// The analyzed document contains a number of indices that make it easier to +// reason about semantics of a swagger specification for use in code generation +// or validation etc. +func New(doc *spec.Swagger) *Spec { + a := &Spec{ + spec: doc, + consumes: make(map[string]struct{}, 150), + produces: make(map[string]struct{}, 150), + authSchemes: make(map[string]struct{}, 150), + operations: make(map[string]map[string]*spec.Operation, 150), + allSchemas: make(map[string]SchemaRef, 150), + allOfs: make(map[string]SchemaRef, 150), + references: referenceAnalysis{ + schemas: make(map[string]spec.Ref, 150), + pathItems: make(map[string]spec.Ref, 150), + responses: make(map[string]spec.Ref, 150), + parameters: make(map[string]spec.Ref, 150), + items: make(map[string]spec.Ref, 150), + headerItems: make(map[string]spec.Ref, 150), + parameterItems: make(map[string]spec.Ref, 150), + allRefs: make(map[string]spec.Ref, 150), + }, + patterns: patternAnalysis{ + parameters: make(map[string]string, 150), + headers: make(map[string]string, 150), + items: make(map[string]string, 150), + schemas: make(map[string]string, 150), + allPatterns: make(map[string]string, 150), + }, + } + a.initialize() + return a +} + +// Spec takes a swagger spec object and turns it into a registry +// with a bunch of utility methods to act on the information in the spec +type Spec struct { + spec *spec.Swagger + consumes map[string]struct{} + produces map[string]struct{} + authSchemes map[string]struct{} + operations map[string]map[string]*spec.Operation + references referenceAnalysis + patterns patternAnalysis + allSchemas map[string]SchemaRef + allOfs map[string]SchemaRef +} + +func (s *Spec) reset() { + s.consumes = make(map[string]struct{}, 150) + s.produces = make(map[string]struct{}, 150) + s.authSchemes = make(map[string]struct{}, 150) + s.operations = make(map[string]map[string]*spec.Operation, 150) + s.allSchemas = make(map[string]SchemaRef, 150) + s.allOfs = make(map[string]SchemaRef, 150) + s.references.schemas = make(map[string]spec.Ref, 150) + s.references.pathItems = make(map[string]spec.Ref, 150) + s.references.responses = make(map[string]spec.Ref, 150) + s.references.parameters = make(map[string]spec.Ref, 150) + s.references.items = make(map[string]spec.Ref, 150) + s.references.headerItems = make(map[string]spec.Ref, 150) + s.references.parameterItems = make(map[string]spec.Ref, 150) + s.references.allRefs = make(map[string]spec.Ref, 150) + s.patterns.parameters = make(map[string]string, 150) + s.patterns.headers = make(map[string]string, 150) + s.patterns.items = make(map[string]string, 150) + s.patterns.schemas = make(map[string]string, 150) + s.patterns.allPatterns = make(map[string]string, 150) +} + +func (s *Spec) reload() { + s.reset() + s.initialize() +} + +func (s *Spec) initialize() { + for _, c := range s.spec.Consumes { + s.consumes[c] = struct{}{} + } + for _, c := range s.spec.Produces { + s.produces[c] = struct{}{} + } + for _, ss := range s.spec.Security { + for k := range ss { + s.authSchemes[k] = struct{}{} + } + } + for path, pathItem := range s.AllPaths() { + s.analyzeOperations(path, &pathItem) + } + + for name, parameter := range s.spec.Parameters { + refPref := slashpath.Join("/parameters", jsonpointer.Escape(name)) + if parameter.Items != nil { + s.analyzeItems("items", parameter.Items, refPref, "parameter") + } + if parameter.In == "body" && parameter.Schema != nil { + s.analyzeSchema("schema", *parameter.Schema, refPref) + } + if parameter.Pattern != "" { + s.patterns.addParameterPattern(refPref, parameter.Pattern) + } + } + + for name, response := range s.spec.Responses { + refPref := slashpath.Join("/responses", jsonpointer.Escape(name)) + for k, v := range response.Headers { + hRefPref := slashpath.Join(refPref, "headers", k) + if v.Items != nil { + s.analyzeItems("items", v.Items, hRefPref, "header") + } + if v.Pattern != "" { + s.patterns.addHeaderPattern(hRefPref, v.Pattern) + } + } + if response.Schema != nil { + s.analyzeSchema("schema", *response.Schema, refPref) + } + } + + for name, schema := range s.spec.Definitions { + s.analyzeSchema(name, schema, "/definitions") + } + // TODO: after analyzing all things and flattening schemas etc + // resolve all the collected references to their final representations + // best put in a separate method because this could get expensive +} + +func (s *Spec) analyzeOperations(path string, pi *spec.PathItem) { + // TODO: resolve refs here? + op := pi + if pi.Ref.String() != "" { + key := slashpath.Join("/paths", jsonpointer.Escape(path)) + s.references.addPathItemRef(key, pi) + } + s.analyzeOperation("GET", path, op.Get) + s.analyzeOperation("PUT", path, op.Put) + s.analyzeOperation("POST", path, op.Post) + s.analyzeOperation("PATCH", path, op.Patch) + s.analyzeOperation("DELETE", path, op.Delete) + s.analyzeOperation("HEAD", path, op.Head) + s.analyzeOperation("OPTIONS", path, op.Options) + for i, param := range op.Parameters { + refPref := slashpath.Join("/paths", jsonpointer.Escape(path), "parameters", strconv.Itoa(i)) + if param.Ref.String() != "" { + s.references.addParamRef(refPref, ¶m) + } + if param.Pattern != "" { + s.patterns.addParameterPattern(refPref, param.Pattern) + } + if param.Items != nil { + s.analyzeItems("items", param.Items, refPref, "parameter") + } + if param.Schema != nil { + s.analyzeSchema("schema", *param.Schema, refPref) + } + } +} + +func (s *Spec) analyzeItems(name string, items *spec.Items, prefix, location string) { + if items == nil { + return + } + refPref := slashpath.Join(prefix, name) + s.analyzeItems(name, items.Items, refPref, location) + if items.Ref.String() != "" { + s.references.addItemsRef(refPref, items, location) + } + if items.Pattern != "" { + s.patterns.addItemsPattern(refPref, items.Pattern) + } +} + +func (s *Spec) analyzeOperation(method, path string, op *spec.Operation) { + if op == nil { + return + } + + for _, c := range op.Consumes { + s.consumes[c] = struct{}{} + } + for _, c := range op.Produces { + s.produces[c] = struct{}{} + } + for _, ss := range op.Security { + for k := range ss { + s.authSchemes[k] = struct{}{} + } + } + if _, ok := s.operations[method]; !ok { + s.operations[method] = make(map[string]*spec.Operation) + } + s.operations[method][path] = op + prefix := slashpath.Join("/paths", jsonpointer.Escape(path), strings.ToLower(method)) + for i, param := range op.Parameters { + refPref := slashpath.Join(prefix, "parameters", strconv.Itoa(i)) + if param.Ref.String() != "" { + s.references.addParamRef(refPref, ¶m) + } + if param.Pattern != "" { + s.patterns.addParameterPattern(refPref, param.Pattern) + } + s.analyzeItems("items", param.Items, refPref, "parameter") + if param.In == "body" && param.Schema != nil { + s.analyzeSchema("schema", *param.Schema, refPref) + } + } + if op.Responses != nil { + if op.Responses.Default != nil { + refPref := slashpath.Join(prefix, "responses", "default") + if op.Responses.Default.Ref.String() != "" { + s.references.addResponseRef(refPref, op.Responses.Default) + } + for k, v := range op.Responses.Default.Headers { + hRefPref := slashpath.Join(refPref, "headers", k) + s.analyzeItems("items", v.Items, hRefPref, "header") + if v.Pattern != "" { + s.patterns.addHeaderPattern(hRefPref, v.Pattern) + } + } + if op.Responses.Default.Schema != nil { + s.analyzeSchema("schema", *op.Responses.Default.Schema, refPref) + } + } + for k, res := range op.Responses.StatusCodeResponses { + refPref := slashpath.Join(prefix, "responses", strconv.Itoa(k)) + if res.Ref.String() != "" { + s.references.addResponseRef(refPref, &res) + } + for k, v := range res.Headers { + hRefPref := slashpath.Join(refPref, "headers", k) + s.analyzeItems("items", v.Items, hRefPref, "header") + if v.Pattern != "" { + s.patterns.addHeaderPattern(hRefPref, v.Pattern) + } + } + if res.Schema != nil { + s.analyzeSchema("schema", *res.Schema, refPref) + } + } + } +} + +func (s *Spec) analyzeSchema(name string, schema spec.Schema, prefix string) { + refURI := slashpath.Join(prefix, jsonpointer.Escape(name)) + schRef := SchemaRef{ + Name: name, + Schema: &schema, + Ref: spec.MustCreateRef("#" + refURI), + TopLevel: prefix == "/definitions", + } + + s.allSchemas["#"+refURI] = schRef + + if schema.Ref.String() != "" { + s.references.addSchemaRef(refURI, schRef) + } + if schema.Pattern != "" { + s.patterns.addSchemaPattern(refURI, schema.Pattern) + } + + for k, v := range schema.Definitions { + s.analyzeSchema(k, v, slashpath.Join(refURI, "definitions")) + } + for k, v := range schema.Properties { + s.analyzeSchema(k, v, slashpath.Join(refURI, "properties")) + } + for k, v := range schema.PatternProperties { + s.analyzeSchema(k, v, slashpath.Join(refURI, "patternProperties")) + } + for i, v := range schema.AllOf { + s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "allOf")) + } + if len(schema.AllOf) > 0 { + s.allOfs["#"+refURI] = schRef + } + for i, v := range schema.AnyOf { + s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "anyOf")) + } + for i, v := range schema.OneOf { + s.analyzeSchema(strconv.Itoa(i), v, slashpath.Join(refURI, "oneOf")) + } + if schema.Not != nil { + s.analyzeSchema("not", *schema.Not, refURI) + } + if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil { + s.analyzeSchema("additionalProperties", *schema.AdditionalProperties.Schema, refURI) + } + if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil { + s.analyzeSchema("additionalItems", *schema.AdditionalItems.Schema, refURI) + } + if schema.Items != nil { + if schema.Items.Schema != nil { + s.analyzeSchema("items", *schema.Items.Schema, refURI) + } + for i, sch := range schema.Items.Schemas { + s.analyzeSchema(strconv.Itoa(i), sch, slashpath.Join(refURI, "items")) + } + } +} + +// SecurityRequirement is a representation of a security requirement for an operation +type SecurityRequirement struct { + Name string + Scopes []string +} + +// SecurityRequirementsFor gets the security requirements for the operation +func (s *Spec) SecurityRequirementsFor(operation *spec.Operation) []SecurityRequirement { + if s.spec.Security == nil && operation.Security == nil { + return nil + } + + schemes := s.spec.Security + if operation.Security != nil { + schemes = operation.Security + } + + unique := make(map[string]SecurityRequirement) + for _, scheme := range schemes { + for k, v := range scheme { + if _, ok := unique[k]; !ok { + unique[k] = SecurityRequirement{Name: k, Scopes: v} + } + } + } + + var result []SecurityRequirement + for _, v := range unique { + result = append(result, v) + } + return result +} + +// SecurityDefinitionsFor gets the matching security definitions for a set of requirements +func (s *Spec) SecurityDefinitionsFor(operation *spec.Operation) map[string]spec.SecurityScheme { + requirements := s.SecurityRequirementsFor(operation) + if len(requirements) == 0 { + return nil + } + result := make(map[string]spec.SecurityScheme) + for _, v := range requirements { + if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok { + if definition != nil { + result[v.Name] = *definition + } + } + } + return result +} + +// ConsumesFor gets the mediatypes for the operation +func (s *Spec) ConsumesFor(operation *spec.Operation) []string { + + if len(operation.Consumes) == 0 { + cons := make(map[string]struct{}, len(s.spec.Consumes)) + for _, k := range s.spec.Consumes { + cons[k] = struct{}{} + } + return s.structMapKeys(cons) + } + + cons := make(map[string]struct{}, len(operation.Consumes)) + for _, c := range operation.Consumes { + cons[c] = struct{}{} + } + return s.structMapKeys(cons) +} + +// ProducesFor gets the mediatypes for the operation +func (s *Spec) ProducesFor(operation *spec.Operation) []string { + if len(operation.Produces) == 0 { + prod := make(map[string]struct{}, len(s.spec.Produces)) + for _, k := range s.spec.Produces { + prod[k] = struct{}{} + } + return s.structMapKeys(prod) + } + + prod := make(map[string]struct{}, len(operation.Produces)) + for _, c := range operation.Produces { + prod[c] = struct{}{} + } + return s.structMapKeys(prod) +} + +func mapKeyFromParam(param *spec.Parameter) string { + return fmt.Sprintf("%s#%s", param.In, fieldNameFromParam(param)) +} + +func fieldNameFromParam(param *spec.Parameter) string { + if nm, ok := param.Extensions.GetString("go-name"); ok { + return nm + } + return swag.ToGoName(param.Name) +} + +func (s *Spec) paramsAsMap(parameters []spec.Parameter, res map[string]spec.Parameter) { + for _, param := range parameters { + pr := param + if pr.Ref.String() != "" { + obj, _, err := pr.Ref.GetPointer().Get(s.spec) + if err != nil { + panic(err) + } + pr = obj.(spec.Parameter) + } + res[mapKeyFromParam(&pr)] = pr + } +} + +// ParametersFor the specified operation id +func (s *Spec) ParametersFor(operationID string) []spec.Parameter { + gatherParams := func(pi *spec.PathItem, op *spec.Operation) []spec.Parameter { + bag := make(map[string]spec.Parameter) + s.paramsAsMap(pi.Parameters, bag) + s.paramsAsMap(op.Parameters, bag) + + var res []spec.Parameter + for _, v := range bag { + res = append(res, v) + } + return res + } + for _, pi := range s.spec.Paths.Paths { + if pi.Get != nil && pi.Get.ID == operationID { + return gatherParams(&pi, pi.Get) + } + if pi.Head != nil && pi.Head.ID == operationID { + return gatherParams(&pi, pi.Head) + } + if pi.Options != nil && pi.Options.ID == operationID { + return gatherParams(&pi, pi.Options) + } + if pi.Post != nil && pi.Post.ID == operationID { + return gatherParams(&pi, pi.Post) + } + if pi.Patch != nil && pi.Patch.ID == operationID { + return gatherParams(&pi, pi.Patch) + } + if pi.Put != nil && pi.Put.ID == operationID { + return gatherParams(&pi, pi.Put) + } + if pi.Delete != nil && pi.Delete.ID == operationID { + return gatherParams(&pi, pi.Delete) + } + } + return nil +} + +// ParamsFor the specified method and path. Aggregates them with the defaults etc, so it's all the params that +// apply for the method and path. +func (s *Spec) ParamsFor(method, path string) map[string]spec.Parameter { + res := make(map[string]spec.Parameter) + if pi, ok := s.spec.Paths.Paths[path]; ok { + s.paramsAsMap(pi.Parameters, res) + s.paramsAsMap(s.operations[strings.ToUpper(method)][path].Parameters, res) + } + return res +} + +// OperationForName gets the operation for the given id +func (s *Spec) OperationForName(operationID string) (string, string, *spec.Operation, bool) { + for method, pathItem := range s.operations { + for path, op := range pathItem { + if operationID == op.ID { + return method, path, op, true + } + } + } + return "", "", nil, false +} + +// OperationFor the given method and path +func (s *Spec) OperationFor(method, path string) (*spec.Operation, bool) { + if mp, ok := s.operations[strings.ToUpper(method)]; ok { + op, fn := mp[path] + return op, fn + } + return nil, false +} + +// Operations gathers all the operations specified in the spec document +func (s *Spec) Operations() map[string]map[string]*spec.Operation { + return s.operations +} + +func (s *Spec) structMapKeys(mp map[string]struct{}) []string { + if len(mp) == 0 { + return nil + } + + result := make([]string, 0, len(mp)) + for k := range mp { + result = append(result, k) + } + return result +} + +// AllPaths returns all the paths in the swagger spec +func (s *Spec) AllPaths() map[string]spec.PathItem { + if s.spec == nil || s.spec.Paths == nil { + return nil + } + return s.spec.Paths.Paths +} + +// OperationIDs gets all the operation ids based on method an dpath +func (s *Spec) OperationIDs() []string { + if len(s.operations) == 0 { + return nil + } + result := make([]string, 0, len(s.operations)) + for method, v := range s.operations { + for p, o := range v { + if o.ID != "" { + result = append(result, o.ID) + } else { + result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p)) + } + } + } + return result +} + +// OperationMethodPaths gets all the operation ids based on method an dpath +func (s *Spec) OperationMethodPaths() []string { + if len(s.operations) == 0 { + return nil + } + result := make([]string, 0, len(s.operations)) + for method, v := range s.operations { + for p := range v { + result = append(result, fmt.Sprintf("%s %s", strings.ToUpper(method), p)) + } + } + return result +} + +// RequiredConsumes gets all the distinct consumes that are specified in the specification document +func (s *Spec) RequiredConsumes() []string { + return s.structMapKeys(s.consumes) +} + +// RequiredProduces gets all the distinct produces that are specified in the specification document +func (s *Spec) RequiredProduces() []string { + return s.structMapKeys(s.produces) +} + +// RequiredSecuritySchemes gets all the distinct security schemes that are specified in the swagger spec +func (s *Spec) RequiredSecuritySchemes() []string { + return s.structMapKeys(s.authSchemes) +} + +// SchemaRef is a reference to a schema +type SchemaRef struct { + Name string + Ref spec.Ref + Schema *spec.Schema + TopLevel bool +} + +// SchemasWithAllOf returns schema references to all schemas that are defined +// with an allOf key +func (s *Spec) SchemasWithAllOf() (result []SchemaRef) { + for _, v := range s.allOfs { + result = append(result, v) + } + return +} + +// AllDefinitions returns schema references for all the definitions that were discovered +func (s *Spec) AllDefinitions() (result []SchemaRef) { + for _, v := range s.allSchemas { + result = append(result, v) + } + return +} + +// AllDefinitionReferences returns json refs for all the discovered schemas +func (s *Spec) AllDefinitionReferences() (result []string) { + for _, v := range s.references.schemas { + result = append(result, v.String()) + } + return +} + +// AllParameterReferences returns json refs for all the discovered parameters +func (s *Spec) AllParameterReferences() (result []string) { + for _, v := range s.references.parameters { + result = append(result, v.String()) + } + return +} + +// AllResponseReferences returns json refs for all the discovered responses +func (s *Spec) AllResponseReferences() (result []string) { + for _, v := range s.references.responses { + result = append(result, v.String()) + } + return +} + +// AllPathItemReferences returns the references for all the items +func (s *Spec) AllPathItemReferences() (result []string) { + for _, v := range s.references.pathItems { + result = append(result, v.String()) + } + return +} + +// AllItemsReferences returns the references for all the items +func (s *Spec) AllItemsReferences() (result []string) { + for _, v := range s.references.items { + result = append(result, v.String()) + } + return +} + +// AllReferences returns all the references found in the document +func (s *Spec) AllReferences() (result []string) { + for _, v := range s.references.allRefs { + result = append(result, v.String()) + } + return +} + +// AllRefs returns all the unique references found in the document +func (s *Spec) AllRefs() (result []spec.Ref) { + set := make(map[string]struct{}) + for _, v := range s.references.allRefs { + a := v.String() + if a == "" { + continue + } + if _, ok := set[a]; !ok { + set[a] = struct{}{} + result = append(result, v) + } + } + return +} + +func cloneStringMap(source map[string]string) map[string]string { + res := make(map[string]string, len(source)) + for k, v := range source { + res[k] = v + } + return res +} + +// ParameterPatterns returns all the patterns found in parameters +// the map is cloned to avoid accidental changes +func (s *Spec) ParameterPatterns() map[string]string { + return cloneStringMap(s.patterns.parameters) +} + +// HeaderPatterns returns all the patterns found in response headers +// the map is cloned to avoid accidental changes +func (s *Spec) HeaderPatterns() map[string]string { + return cloneStringMap(s.patterns.headers) +} + +// ItemsPatterns returns all the patterns found in simple array items +// the map is cloned to avoid accidental changes +func (s *Spec) ItemsPatterns() map[string]string { + return cloneStringMap(s.patterns.items) +} + +// SchemaPatterns returns all the patterns found in schemas +// the map is cloned to avoid accidental changes +func (s *Spec) SchemaPatterns() map[string]string { + return cloneStringMap(s.patterns.schemas) +} + +// AllPatterns returns all the patterns found in the spec +// the map is cloned to avoid accidental changes +func (s *Spec) AllPatterns() map[string]string { + return cloneStringMap(s.patterns.allPatterns) +} diff --git a/vendor/github.com/go-openapi/analysis/analyzer_test.go b/vendor/github.com/go-openapi/analysis/analyzer_test.go new file mode 100644 index 0000000000..70b80d7f9d --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/analyzer_test.go @@ -0,0 +1,284 @@ +// 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 analysis + +import ( + "encoding/json" + "fmt" + "path/filepath" + "sort" + "testing" + + "github.com/go-openapi/loads/fmts" + "github.com/go-openapi/spec" + "github.com/go-openapi/swag" + "github.com/stretchr/testify/assert" +) + +func schemeNames(schemes []SecurityRequirement) []string { + var names []string + for _, v := range schemes { + names = append(names, v.Name) + } + sort.Sort(sort.StringSlice(names)) + return names +} + +func TestAnalyzer(t *testing.T) { + formatParam := spec.QueryParam("format").Typed("string", "") + + limitParam := spec.QueryParam("limit").Typed("integer", "int32") + limitParam.Extensions = spec.Extensions(map[string]interface{}{}) + limitParam.Extensions.Add("go-name", "Limit") + + skipParam := spec.QueryParam("skip").Typed("integer", "int32") + pi := spec.PathItem{} + pi.Parameters = []spec.Parameter{*limitParam} + + op := &spec.Operation{} + op.Consumes = []string{"application/x-yaml"} + op.Produces = []string{"application/x-yaml"} + op.Security = []map[string][]string{ + map[string][]string{"oauth2": []string{}}, + map[string][]string{"basic": nil}, + } + op.ID = "someOperation" + op.Parameters = []spec.Parameter{*skipParam} + pi.Get = op + + pi2 := spec.PathItem{} + pi2.Parameters = []spec.Parameter{*limitParam} + op2 := &spec.Operation{} + op2.ID = "anotherOperation" + op2.Parameters = []spec.Parameter{*skipParam} + pi2.Get = op2 + + spec := &spec.Swagger{ + SwaggerProps: spec.SwaggerProps{ + Consumes: []string{"application/json"}, + Produces: []string{"application/json"}, + Security: []map[string][]string{ + map[string][]string{"apikey": nil}, + }, + SecurityDefinitions: map[string]*spec.SecurityScheme{ + "basic": spec.BasicAuth(), + "apiKey": spec.APIKeyAuth("api_key", "query"), + "oauth2": spec.OAuth2AccessToken("http://authorize.com", "http://token.com"), + }, + Parameters: map[string]spec.Parameter{"format": *formatParam}, + Paths: &spec.Paths{ + Paths: map[string]spec.PathItem{ + "/": pi, + "/items": pi2, + }, + }, + }, + } + analyzer := New(spec) + + assert.Len(t, analyzer.consumes, 2) + assert.Len(t, analyzer.produces, 2) + assert.Len(t, analyzer.operations, 1) + assert.Equal(t, analyzer.operations["GET"]["/"], spec.Paths.Paths["/"].Get) + + expected := []string{"application/x-yaml"} + sort.Sort(sort.StringSlice(expected)) + consumes := analyzer.ConsumesFor(spec.Paths.Paths["/"].Get) + sort.Sort(sort.StringSlice(consumes)) + assert.Equal(t, expected, consumes) + + produces := analyzer.ProducesFor(spec.Paths.Paths["/"].Get) + sort.Sort(sort.StringSlice(produces)) + assert.Equal(t, expected, produces) + + expected = []string{"application/json"} + sort.Sort(sort.StringSlice(expected)) + consumes = analyzer.ConsumesFor(spec.Paths.Paths["/items"].Get) + sort.Sort(sort.StringSlice(consumes)) + assert.Equal(t, expected, consumes) + + produces = analyzer.ProducesFor(spec.Paths.Paths["/items"].Get) + sort.Sort(sort.StringSlice(produces)) + assert.Equal(t, expected, produces) + + expectedSchemes := []SecurityRequirement{SecurityRequirement{"oauth2", []string{}}, SecurityRequirement{"basic", nil}} + schemes := analyzer.SecurityRequirementsFor(spec.Paths.Paths["/"].Get) + assert.Equal(t, schemeNames(expectedSchemes), schemeNames(schemes)) + + securityDefinitions := analyzer.SecurityDefinitionsFor(spec.Paths.Paths["/"].Get) + assert.Equal(t, securityDefinitions["basic"], *spec.SecurityDefinitions["basic"]) + assert.Equal(t, securityDefinitions["oauth2"], *spec.SecurityDefinitions["oauth2"]) + + parameters := analyzer.ParamsFor("GET", "/") + assert.Len(t, parameters, 2) + + operations := analyzer.OperationIDs() + assert.Len(t, operations, 2) + + producers := analyzer.RequiredProduces() + assert.Len(t, producers, 2) + consumers := analyzer.RequiredConsumes() + assert.Len(t, consumers, 2) + authSchemes := analyzer.RequiredSecuritySchemes() + assert.Len(t, authSchemes, 3) + + ops := analyzer.Operations() + assert.Len(t, ops, 1) + assert.Len(t, ops["GET"], 2) + + op, ok := analyzer.OperationFor("get", "/") + assert.True(t, ok) + assert.NotNil(t, op) + + op, ok = analyzer.OperationFor("delete", "/") + assert.False(t, ok) + assert.Nil(t, op) +} + +func TestDefinitionAnalysis(t *testing.T) { + doc, err := loadSpec(filepath.Join("fixtures", "definitions.yml")) + if assert.NoError(t, err) { + analyzer := New(doc) + definitions := analyzer.allSchemas + // parameters + assertSchemaRefExists(t, definitions, "#/parameters/someParam/schema") + assertSchemaRefExists(t, definitions, "#/paths/~1some~1where~1{id}/parameters/1/schema") + assertSchemaRefExists(t, definitions, "#/paths/~1some~1where~1{id}/get/parameters/1/schema") + // responses + assertSchemaRefExists(t, definitions, "#/responses/someResponse/schema") + assertSchemaRefExists(t, definitions, "#/paths/~1some~1where~1{id}/get/responses/default/schema") + assertSchemaRefExists(t, definitions, "#/paths/~1some~1where~1{id}/get/responses/200/schema") + // definitions + assertSchemaRefExists(t, definitions, "#/definitions/tag") + assertSchemaRefExists(t, definitions, "#/definitions/tag/properties/id") + assertSchemaRefExists(t, definitions, "#/definitions/tag/properties/value") + assertSchemaRefExists(t, definitions, "#/definitions/tag/definitions/category") + assertSchemaRefExists(t, definitions, "#/definitions/tag/definitions/category/properties/id") + assertSchemaRefExists(t, definitions, "#/definitions/tag/definitions/category/properties/value") + assertSchemaRefExists(t, definitions, "#/definitions/withAdditionalProps") + assertSchemaRefExists(t, definitions, "#/definitions/withAdditionalProps/additionalProperties") + assertSchemaRefExists(t, definitions, "#/definitions/withAdditionalItems") + assertSchemaRefExists(t, definitions, "#/definitions/withAdditionalItems/items/0") + assertSchemaRefExists(t, definitions, "#/definitions/withAdditionalItems/items/1") + assertSchemaRefExists(t, definitions, "#/definitions/withAdditionalItems/additionalItems") + assertSchemaRefExists(t, definitions, "#/definitions/withNot") + assertSchemaRefExists(t, definitions, "#/definitions/withNot/not") + assertSchemaRefExists(t, definitions, "#/definitions/withAnyOf") + assertSchemaRefExists(t, definitions, "#/definitions/withAnyOf/anyOf/0") + assertSchemaRefExists(t, definitions, "#/definitions/withAnyOf/anyOf/1") + assertSchemaRefExists(t, definitions, "#/definitions/withAllOf") + assertSchemaRefExists(t, definitions, "#/definitions/withAllOf/allOf/0") + assertSchemaRefExists(t, definitions, "#/definitions/withAllOf/allOf/1") + allOfs := analyzer.allOfs + assert.Len(t, allOfs, 1) + assert.Contains(t, allOfs, "#/definitions/withAllOf") + } +} + +func loadSpec(path string) (*spec.Swagger, error) { + spec.PathLoader = func(path string) (json.RawMessage, error) { + ext := filepath.Ext(path) + if ext == ".yml" || ext == ".yaml" { + return fmts.YAMLDoc(path) + } + data, err := swag.LoadFromFileOrHTTP(path) + if err != nil { + return nil, err + } + return json.RawMessage(data), nil + } + data, err := fmts.YAMLDoc(path) + if err != nil { + return nil, err + } + + var sw spec.Swagger + if err := json.Unmarshal(data, &sw); err != nil { + return nil, err + } + return &sw, nil +} + +func TestReferenceAnalysis(t *testing.T) { + doc, err := loadSpec(filepath.Join("fixtures", "references.yml")) + if assert.NoError(t, err) { + definitions := New(doc).references + + // parameters + assertRefExists(t, definitions.parameters, "#/paths/~1some~1where~1{id}/parameters/0") + assertRefExists(t, definitions.parameters, "#/paths/~1some~1where~1{id}/get/parameters/0") + + // path items + assertRefExists(t, definitions.pathItems, "#/paths/~1other~1place") + + // responses + assertRefExists(t, definitions.responses, "#/paths/~1some~1where~1{id}/get/responses/404") + + // definitions + assertRefExists(t, definitions.schemas, "#/responses/notFound/schema") + assertRefExists(t, definitions.schemas, "#/paths/~1some~1where~1{id}/get/responses/200/schema") + assertRefExists(t, definitions.schemas, "#/definitions/tag/properties/audit") + + // items + assertRefExists(t, definitions.allRefs, "#/paths/~1some~1where~1{id}/get/parameters/1/items") + } +} + +func assertRefExists(t testing.TB, data map[string]spec.Ref, key string) bool { + if _, ok := data[key]; !ok { + return assert.Fail(t, fmt.Sprintf("expected %q to exist in the ref bag", key)) + } + return true +} + +func assertSchemaRefExists(t testing.TB, data map[string]SchemaRef, key string) bool { + if _, ok := data[key]; !ok { + return assert.Fail(t, fmt.Sprintf("expected %q to exist in schema ref bag", key)) + } + return true +} + +func TestPatternAnalysis(t *testing.T) { + doc, err := loadSpec(filepath.Join("fixtures", "patterns.yml")) + if assert.NoError(t, err) { + pt := New(doc).patterns + + // parameters + assertPattern(t, pt.parameters, "#/parameters/idParam", "a[A-Za-Z0-9]+") + assertPattern(t, pt.parameters, "#/paths/~1some~1where~1{id}/parameters/1", "b[A-Za-z0-9]+") + assertPattern(t, pt.parameters, "#/paths/~1some~1where~1{id}/get/parameters/0", "[abc][0-9]+") + + // responses + assertPattern(t, pt.headers, "#/responses/notFound/headers/ContentLength", "[0-9]+") + assertPattern(t, pt.headers, "#/paths/~1some~1where~1{id}/get/responses/200/headers/X-Request-Id", "d[A-Za-z0-9]+") + + // definitions + assertPattern(t, pt.schemas, "#/paths/~1other~1place/post/parameters/0/schema/properties/value", "e[A-Za-z0-9]+") + assertPattern(t, pt.schemas, "#/paths/~1other~1place/post/responses/200/schema/properties/data", "[0-9]+[abd]") + assertPattern(t, pt.schemas, "#/definitions/named", "f[A-Za-z0-9]+") + assertPattern(t, pt.schemas, "#/definitions/tag/properties/value", "g[A-Za-z0-9]+") + + // items + assertPattern(t, pt.items, "#/paths/~1some~1where~1{id}/get/parameters/1/items", "c[A-Za-z0-9]+") + assertPattern(t, pt.items, "#/paths/~1other~1place/post/responses/default/headers/Via/items", "[A-Za-z]+") + } +} + +func assertPattern(t testing.TB, data map[string]string, key, pattern string) bool { + if assert.Contains(t, data, key) { + return assert.Equal(t, pattern, data[key]) + } + return false +} diff --git a/vendor/github.com/go-openapi/analysis/fixtures/allOf.yml b/vendor/github.com/go-openapi/analysis/fixtures/allOf.yml new file mode 100644 index 0000000000..531c33aa69 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/allOf.yml @@ -0,0 +1,43 @@ +--- +swagger: "2.0" +info: + version: "0.1.0" + title: allOf analysis +paths: + "/some/where/{id}": + parameters: + - name: id + in: path + type: integer + format: int32 + - name: bodyId + in: body + schema: + type: object + get: + parameters: + - name: limit + in: query + type: integer + format: int32 + required: false + - name: body + in: body + schema: + type: object + responses: + default: + schema: + type: object + 200: + schema: + type: object +definitions: + tag: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string diff --git a/vendor/github.com/go-openapi/analysis/fixtures/bar-crud.yml b/vendor/github.com/go-openapi/analysis/fixtures/bar-crud.yml new file mode 100644 index 0000000000..90000f46bc --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/bar-crud.yml @@ -0,0 +1,180 @@ +--- +swagger: '2.0' +info: + title: bar CRUD API + version: 4.2.0 +schemes: + - http +basePath: /api +consumes: + - application/json +produces: + - application/json +paths: + /common: + get: + operationId: commonGet + summary: here to test path collisons + responses: + '200': + description: OK + schema: + $ref: "#/definitions/bar" + /bars: + post: + operationId: create + summary: Create a new bar + parameters: + - name: info + in: body + schema: + $ref: "#/definitions/bar" + responses: + '201': + description: created + schema: + $ref: "#/definitions/barId" + default: + description: error + schema: + $ref: "#/definitions/error" + /bars/{barid}: + get: + operationId: get + summary: Get a bar by id + parameters: + - $ref: "#/parameters/barid" + responses: + '200': + description: OK + schema: + $ref: "#/definitions/bar" + '401': + $ref: "#/responses/401" + '404': + $ref: "#/responses/404" + default: + description: error + schema: + $ref: "#/definitions/error" + delete: + operationId: delete + summary: delete a bar by id + parameters: + - name: barid + in: path + required: true + type: string + responses: + '200': + description: OK + '401': + description: unauthorized + schema: + $ref: "#/definitions/error" + '404': + description: resource not found + schema: + $ref: "#/definitions/error" + default: + description: error + schema: + $ref: "#/definitions/error" + post: + operationId: update + summary: update a bar by id + parameters: + - name: barid + in: path + required: true + type: string + - name: info + in: body + schema: + $ref: "#/definitions/bar" + responses: + '200': + description: OK + '401': + description: unauthorized + schema: + $ref: "#/definitions/error" + '404': + description: resource not found + schema: + $ref: "#/definitions/error" + default: + description: error + schema: + $ref: "#/definitions/error" + +definitions: + common: + type: object + required: + - id + properties: + id: + type: string + format: string + minLength: 1 + bar: + type: object + required: + - name + - description + properties: + id: + type: string + format: string + readOnly: true + name: + type: string + format: string + minLength: 1 + description: + type: string + format: string + minLength: 1 + barId: + type: object + required: + - id + properties: + id: + type: string + format: string + minLength: 1 + error: + type: object + required: + - message + properties: + code: + type: string + format: string + message: + type: string + fields: + type: string + +parameters: + common: + name: common + in: query + type: string + barid: + name: barid + in: path + required: true + type: string + +responses: + 401: + description: bar unauthorized + schema: + $ref: "#/definitions/error" + 404: + description: bar resource not found + schema: + $ref: "#/definitions/error" diff --git a/vendor/github.com/go-openapi/analysis/fixtures/definitions.yml b/vendor/github.com/go-openapi/analysis/fixtures/definitions.yml new file mode 100644 index 0000000000..63cb17a654 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/definitions.yml @@ -0,0 +1,86 @@ +--- +swagger: "2.0" +info: + version: "0.1.0" + title: Definition analysis +parameters: + someParam: + name: someParam + in: body + schema: + type: object +responses: + someResponse: + schema: + type: object +paths: + "/some/where/{id}": + parameters: + - name: id + in: path + type: integer + format: int32 + - name: bodyId + in: body + schema: + type: object + get: + parameters: + - name: limit + in: query + type: integer + format: int32 + required: false + - name: body + in: body + schema: + type: object + responses: + default: + schema: + type: object + 200: + schema: + type: object +definitions: + tag: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + definitions: + category: + type: object + properties: + id: + type: integer + format: int32 + value: + type: string + withAdditionalProps: + type: object + additionalProperties: + type: boolean + withAdditionalItems: + type: array + items: + - type: string + - type: bool + additionalItems: + type: integer + format: int32 + withNot: + type: object + not: + $ref: "#/definitions/tag" + withAnyOf: + anyOf: + - type: object + - type: string + withAllOf: + allOf: + - type: object + - type: string diff --git a/vendor/github.com/go-openapi/analysis/fixtures/empty-paths.json b/vendor/github.com/go-openapi/analysis/fixtures/empty-paths.json new file mode 100644 index 0000000000..30e6009232 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/empty-paths.json @@ -0,0 +1,8 @@ +{ + "swagger": "2.0", + "info": { + "title": "empty-paths", + "version": "79.2.1" + }, + "paths": {} +} diff --git a/vendor/github.com/go-openapi/analysis/fixtures/external/definitions.yml b/vendor/github.com/go-openapi/analysis/fixtures/external/definitions.yml new file mode 100644 index 0000000000..009cba27cb --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/external/definitions.yml @@ -0,0 +1,50 @@ +definitions: + named: + type: string + tag: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + audit: + $ref: "#/definitions/record" + record: + type: object + properties: + createdAt: + type: string + format: date-time + + nestedThing: + type: object + properties: + record: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + - allOf: + - type: string + format: date + - type: object + additionalProperties: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + properties: + value: + type: string + name: + $ref: "definitions2.yml#/coordinate" \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/fixtures/external/definitions2.yml b/vendor/github.com/go-openapi/analysis/fixtures/external/definitions2.yml new file mode 100644 index 0000000000..08f70c0ea7 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/external/definitions2.yml @@ -0,0 +1,9 @@ +coordinate: + type: object + properties: + id: + type: integer + format: int64 + createdAt: + type: string + format: date-time \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/fixtures/external/errors.yml b/vendor/github.com/go-openapi/analysis/fixtures/external/errors.yml new file mode 100644 index 0000000000..d37a1bdd40 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/external/errors.yml @@ -0,0 +1,13 @@ +error: + type: object + required: + - id + - message + properties: + id: + type: integer + format: int64 + readOnly: true + message: + type: string + readOnly: true diff --git a/vendor/github.com/go-openapi/analysis/fixtures/external/nestedParams.yml b/vendor/github.com/go-openapi/analysis/fixtures/external/nestedParams.yml new file mode 100644 index 0000000000..c11c0d8f0c --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/external/nestedParams.yml @@ -0,0 +1,35 @@ +bodyParam: + name: body + in: body + schema: + type: object + properties: + record: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + - allOf: + - type: string + format: date + - type: object + properties: + id: + type: integer + format: int64 + value: + type: string + name: + type: object + properties: + id: + type: integer + format: int64 + createdAt: + type: string + format: date-time \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/fixtures/external/nestedResponses.yml b/vendor/github.com/go-openapi/analysis/fixtures/external/nestedResponses.yml new file mode 100644 index 0000000000..2d6583c051 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/external/nestedResponses.yml @@ -0,0 +1,32 @@ +genericResponse: + type: object + properties: + record: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + - allOf: + - type: string + format: date + - type: object + properties: + id: + type: integer + format: int64 + value: + type: string + name: + type: object + properties: + id: + type: integer + format: int64 + createdAt: + type: string + format: date-time \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/fixtures/external/parameters.yml b/vendor/github.com/go-openapi/analysis/fixtures/external/parameters.yml new file mode 100644 index 0000000000..b31a4485ad --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/external/parameters.yml @@ -0,0 +1,12 @@ +parameters: + idParam: + name: id + in: path + type: integer + format: int32 + limitParam: + name: limit + in: query + type: integer + format: int32 + required: false \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/fixtures/external/pathItem.yml b/vendor/github.com/go-openapi/analysis/fixtures/external/pathItem.yml new file mode 100644 index 0000000000..22a7aa6342 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/external/pathItem.yml @@ -0,0 +1,9 @@ +get: + operationId: modelOp + summary: many model variations + description: Used to see if a codegen can render all the possible parameter variations for a header param + tags: + - testcgen + responses: + default: + description: Generic Out \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/fixtures/external/responses.yml b/vendor/github.com/go-openapi/analysis/fixtures/external/responses.yml new file mode 100644 index 0000000000..8730d64c18 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/external/responses.yml @@ -0,0 +1,4 @@ +responses: + notFound: + schema: + $ref: "errors.yml#/error" \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/fixtures/external_definitions.yml b/vendor/github.com/go-openapi/analysis/fixtures/external_definitions.yml new file mode 100644 index 0000000000..032f2f3204 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/external_definitions.yml @@ -0,0 +1,95 @@ +--- +swagger: "2.0" +info: + version: "0.1.0" + title: reference analysis + +parameters: + someParam: + name: someParam + in: body + schema: + $ref: "external/definitions.yml#/definitions/record" +responses: + someResponse: + schema: + $ref: "external/definitions.yml#/definitions/record" +paths: + "/some/where/{id}": + parameters: + - $ref: "external/parameters.yml#/parameters/idParam" + + - name: bodyId + in: body + schema: + $ref: "external/definitions.yml#/definitions/record" + get: + parameters: + - $ref: "external/parameters.yml#/parameters/limitParam" + - name: other + in: query + type: array + items: + $ref: "external/definitions.yml#/definitions/named" + - name: body + in: body + schema: + $ref: "external/definitions.yml#/definitions/record" + responses: + default: + schema: + $ref: "external/definitions.yml#/definitions/record" + 404: + $ref: "external/responses.yml#/responses/notFound" + 200: + schema: + $ref: "external/definitions.yml#/definitions/tag" + "/other/place": + $ref: "external/pathItem.yml" + +definitions: + namedAgain: + $ref: "external/definitions.yml#/definitions/named" + + datedTag: + allOf: + - type: string + format: date + - $ref: "external/definitions.yml#/definitions/tag" + + records: + type: array + items: + - $ref: "external/definitions.yml#/definitions/record" + + datedRecords: + type: array + items: + - type: string + format: date-time + - $ref: "external/definitions.yml#/definitions/record" + + datedTaggedRecords: + type: array + items: + - type: string + format: date-time + - $ref: "external/definitions.yml#/definitions/record" + additionalItems: + $ref: "external/definitions.yml#/definitions/tag" + + otherRecords: + type: array + items: + $ref: "external/definitions.yml#/definitions/record" + + tags: + type: object + additionalProperties: + $ref: "external/definitions.yml#/definitions/tag" + + namedThing: + type: object + properties: + name: + $ref: "external/definitions.yml#/definitions/named" \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/fixtures/flatten.yml b/vendor/github.com/go-openapi/analysis/fixtures/flatten.yml new file mode 100644 index 0000000000..d3bd8d9a53 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/flatten.yml @@ -0,0 +1,85 @@ +--- +swagger: "2.0" +info: + version: "0.1.0" + title: reference analysis + +parameters: + someParam: + name: some + in: query + type: string +responses: + notFound: + description: "Not Found" + schema: + $ref: "external/errors.yml#/error" + +paths: + "/some/where/{id}": + parameters: + - $ref: "external/parameters.yml#/parameters/idParam" + + get: + parameters: + - $ref: "external/parameters.yml#/parameters/limitParam" + - $ref: "#/parameters/someParam" + - name: other + in: query + type: string + - $ref: "external/nestedParams.yml#/bodyParam" + + responses: + default: + $ref: "external/nestedResponses.yml#/genericResponse" + 404: + $ref: "#/responses/notFound" + 200: + description: "RecordHolder" + schema: + type: object + properties: + record: + $ref: "external/definitions.yml#/definitions/nestedThing" + "/other/place": + $ref: "external/pathItem.yml" + +definitions: + namedAgain: + $ref: "external/definitions.yml#/definitions/named" + + datedTag: + allOf: + - type: string + format: date + - $ref: "external/definitions.yml#/definitions/tag" + + records: + type: array + items: + - $ref: "external/definitions.yml#/definitions/record" + + datedRecords: + type: array + items: + - type: string + format: date-time + - $ref: "external/definitions.yml#/definitions/record" + + otherRecords: + type: array + items: + $ref: "external/definitions.yml#/definitions/record" + + tags: + type: object + additionalProperties: + $ref: "external/definitions.yml#/definitions/tag" + + namedThing: + type: object + properties: + name: + $ref: "external/definitions.yml#/definitions/named" + namedAgain: + $ref: "#/definitions/namedAgain" diff --git a/vendor/github.com/go-openapi/analysis/fixtures/foo-crud.yml b/vendor/github.com/go-openapi/analysis/fixtures/foo-crud.yml new file mode 100644 index 0000000000..2e3d1f60f2 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/foo-crud.yml @@ -0,0 +1,180 @@ +--- +swagger: '2.0' +info: + title: foo CRUD API + version: 4.2.0 +schemes: + - http +basePath: /api +consumes: + - application/json +produces: + - application/json +paths: + /common: + get: + operationId: commonGet + summary: here to test path collisons + responses: + '200': + description: OK + schema: + $ref: "#/definitions/foo" + /foos: + post: + operationId: create + summary: Create a new foo + parameters: + - name: info + in: body + schema: + $ref: "#/definitions/foo" + responses: + '201': + description: created + schema: + $ref: "#/definitions/fooId" + default: + description: error + schema: + $ref: "#/definitions/error" + /foos/{fooid}: + get: + operationId: get + summary: Get a foo by id + parameters: + - $ref: "#/parameters/fooid" + responses: + '200': + description: OK + schema: + $ref: "#/definitions/foo" + '401': + $ref: "#/responses/401" + '404': + $ref: "#/responses/404" + default: + description: error + schema: + $ref: "#/definitions/error" + delete: + operationId: delete + summary: delete a foo by id + parameters: + - name: fooid + in: path + required: true + type: string + responses: + '200': + description: OK + '401': + description: unauthorized + schema: + $ref: "#/definitions/error" + '404': + description: resource not found + schema: + $ref: "#/definitions/error" + default: + description: error + schema: + $ref: "#/definitions/error" + post: + operationId: update + summary: update a foo by id + parameters: + - name: fooid + in: path + required: true + type: string + - name: info + in: body + schema: + $ref: "#/definitions/foo" + responses: + '200': + description: OK + '401': + description: unauthorized + schema: + $ref: "#/definitions/error" + '404': + description: resource not found + schema: + $ref: "#/definitions/error" + default: + description: error + schema: + $ref: "#/definitions/error" + +definitions: + common: + type: object + required: + - id + properties: + id: + type: string + format: string + minLength: 1 + foo: + type: object + required: + - name + - description + properties: + id: + type: string + format: string + readOnly: true + name: + type: string + format: string + minLength: 1 + description: + type: string + format: string + minLength: 1 + fooId: + type: object + required: + - id + properties: + id: + type: string + format: string + minLength: 1 + error: + type: object + required: + - message + properties: + code: + type: string + format: string + message: + type: string + fields: + type: string + +parameters: + common: + name: common + in: query + type: string + fooid: + name: fooid + in: path + required: true + type: string + +responses: + 401: + description: foo unauthorized + schema: + $ref: "#/definitions/error" + 404: + description: foo resource not found + schema: + $ref: "#/definitions/error" diff --git a/vendor/github.com/go-openapi/analysis/fixtures/inline_schemas.yml b/vendor/github.com/go-openapi/analysis/fixtures/inline_schemas.yml new file mode 100644 index 0000000000..59699571e8 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/inline_schemas.yml @@ -0,0 +1,187 @@ +--- +swagger: "2.0" +info: + version: "0.1.0" + title: reference analysis + +parameters: + someParam: + name: someParam + in: body + schema: + type: object + properties: + createdAt: + type: string + format: date-time +responses: + someResponse: + schema: + type: object + properties: + createdAt: + type: string + format: date-time +paths: + "/some/where/{id}": + parameters: + - name: id + in: path + type: integer + format: int32 + + - name: bodyId + in: body + schema: + type: object + properties: + createdAt: + type: string + format: date-time + post: + responses: + default: + description: all good + get: + parameters: + - name: limit + in: query + type: integer + format: int32 + required: false + - name: other + in: query + type: array + items: + type: object + properties: + id: + type: integer + format: int64 + - name: body + in: body + schema: + type: object + properties: + createdAt: + type: string + format: date-time + responses: + default: + schema: + type: object + properties: + createdAt: + type: string + format: date-time + 404: + schema: + $ref: "errors.yml#/error" + 200: + schema: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + "/other/place": + $ref: "external/pathItem.yml" + +definitions: + namedAgain: + type: object + properties: + id: + type: integer + format: int64 + + datedTag: + allOf: + - type: string + format: date + - type: object + properties: + id: + type: integer + format: int64 + value: + type: string + + records: + type: array + items: + - type: object + properties: + createdAt: + type: string + format: date-time + + datedRecords: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + + datedTaggedRecords: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + additionalItems: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + + otherRecords: + type: array + items: + type: object + properties: + createdAt: + type: string + format: date-time + + tags: + type: object + additionalProperties: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + + namedThing: + type: object + properties: + name: + type: object + properties: + id: + type: integer + format: int64 + + # depth first should have this at the bottom, it's just a very long name + pneumonoultramicroscopicsilicovolcanoconiosisAntidisestablishmentarianism: + type: object + properties: + floccinaucinihilipilificationCreatedAt: + type: integer + format: int64 diff --git a/vendor/github.com/go-openapi/analysis/fixtures/nested_inline_schemas.yml b/vendor/github.com/go-openapi/analysis/fixtures/nested_inline_schemas.yml new file mode 100644 index 0000000000..6acf3b3400 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/nested_inline_schemas.yml @@ -0,0 +1,298 @@ +--- +swagger: "2.0" +info: + version: "0.1.0" + title: reference analysis + +parameters: + someParam: + name: someParam + in: body + schema: + type: object + properties: + createdAt: + type: string + format: date-time +responses: + someResponse: + schema: + type: object + properties: + createdAt: + type: string + format: date-time +paths: + "/some/where/{id}": + parameters: + - name: id + in: path + type: integer + format: int32 + + - name: bodyId + in: body + schema: + type: array + items: + type: object + properties: + createdAt: + type: string + format: date-time + post: + responses: + default: + description: all good + get: + parameters: + - name: limit + in: query + type: integer + format: int32 + required: false + - name: other + in: query + type: array + items: + type: object + properties: + id: + type: integer + format: int64 + - name: body + in: body + schema: + type: object + properties: + record: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + - allOf: + - type: string + format: date + - type: object + properties: + id: + type: integer + format: int64 + value: + type: string + name: + type: object + properties: + id: + type: integer + format: int64 + createdAt: + type: string + format: date-time + responses: + default: + schema: + type: object + properties: + record: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + - allOf: + - type: string + format: date + - type: object + properties: + id: + type: integer + format: int64 + value: + type: string + name: + type: object + properties: + id: + type: integer + format: int64 + createdAt: + type: string + format: date-time + 404: + schema: + $ref: "errors.yml#/error" + 200: + schema: + type: object + properties: + record: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + - allOf: + - type: string + format: date + - type: object + properties: + id: + type: integer + format: int64 + value: + type: string + name: + type: object + properties: + id: + type: integer + format: int64 + createdAt: + type: string + format: date-time + "/other/place": + $ref: "external/pathItem.yml" + +definitions: + namedAgain: + type: object + properties: + id: + type: integer + format: int64 + + datedTag: + allOf: + - type: string + format: date + - type: object + properties: + id: + type: integer + format: int64 + value: + type: string + + records: + type: array + items: + - type: object + properties: + createdAt: + type: string + format: date-time + + datedRecords: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + + datedTaggedRecords: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + additionalItems: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + + otherRecords: + type: array + items: + type: object + properties: + createdAt: + type: string + format: date-time + + tags: + type: object + additionalProperties: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + + namedThing: + type: object + properties: + name: + type: object + properties: + id: + type: integer + format: int64 + + nestedThing: + type: object + properties: + record: + type: array + items: + - type: string + format: date-time + - type: object + properties: + createdAt: + type: string + format: date-time + - allOf: + - type: string + format: date + - type: object + additionalProperties: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + properties: + id: + type: integer + format: int64 + value: + type: string + name: + type: object + properties: + id: + type: integer + format: int64 + createdAt: + type: string + format: date-time \ No newline at end of file diff --git a/vendor/github.com/go-openapi/analysis/fixtures/no-paths.yml b/vendor/github.com/go-openapi/analysis/fixtures/no-paths.yml new file mode 100644 index 0000000000..783f59c420 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/no-paths.yml @@ -0,0 +1,38 @@ +--- +swagger: '2.0' +info: + title: no paths API + version: 4.1.7 +schemes: + - http +basePath: /wooble +consumes: + - application/json +produces: + - application/json +paths: +definitions: + common: + type: object + required: + - id + properties: + id: + type: string + format: string + minLength: 1 +parameters: + common: + name: common + in: query + type: string + +responses: + 401: + description: bar unauthorized + schema: + $ref: "#/definitions/error" + 404: + description: bar resource not found + schema: + $ref: "#/definitions/error" diff --git a/vendor/github.com/go-openapi/analysis/fixtures/patterns.yml b/vendor/github.com/go-openapi/analysis/fixtures/patterns.yml new file mode 100644 index 0000000000..3fe1ab5162 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/patterns.yml @@ -0,0 +1,124 @@ +--- +swagger: "2.0" +info: + version: "0.1.0" + title: reference analysis + +parameters: + idParam: + name: id + in: path + type: string + pattern: 'a[A-Za-Z0-9]+' + +responses: + notFound: + headers: + ContentLength: + type: string + pattern: '[0-9]+' + schema: + $ref: "#/definitions/error" + +paths: + "/some/where/{id}": + parameters: + - $ref: "#/parameters/idParam" + - name: name + in: query + pattern: 'b[A-Za-z0-9]+' + - name: bodyId + in: body + schema: + type: object + get: + parameters: + - name: filter + in: query + type: string + pattern: "[abc][0-9]+" + - name: other + in: query + type: array + items: + type: string + pattern: 'c[A-Za-z0-9]+' + - name: body + in: body + schema: + type: object + + responses: + default: + schema: + type: object + 404: + $ref: "#/responses/notFound" + 200: + headers: + X-Request-Id: + type: string + pattern: 'd[A-Za-z0-9]+' + schema: + $ref: "#/definitions/tag" + "/other/place": + post: + parameters: + - name: body + in: body + schema: + type: object + properties: + value: + type: string + pattern: 'e[A-Za-z0-9]+' + responses: + default: + headers: + Via: + type: array + items: + type: string + pattern: '[A-Za-z]+' + 200: + schema: + type: object + properties: + data: + type: string + pattern: "[0-9]+[abd]" + +definitions: + named: + type: string + pattern: 'f[A-Za-z0-9]+' + tag: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + pattern: 'g[A-Za-z0-9]+' + audit: + $ref: "#/definitions/record" + record: + type: object + properties: + createdAt: + type: string + format: date-time + error: + type: object + required: + - id + - message + properties: + id: + type: integer + format: int64 + readOnly: true + message: + type: string + readOnly: true diff --git a/vendor/github.com/go-openapi/analysis/fixtures/references.yml b/vendor/github.com/go-openapi/analysis/fixtures/references.yml new file mode 100644 index 0000000000..b571766352 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/references.yml @@ -0,0 +1,89 @@ +--- +swagger: "2.0" +info: + version: "0.1.0" + title: reference analysis + +parameters: + idParam: + name: id + in: path + type: integer + format: int32 + limitParam: + name: limit + in: query + type: integer + format: int32 + required: false + +responses: + notFound: + schema: + $ref: "#/definitions/error" + +paths: + "/some/where/{id}": + parameters: + - $ref: "#/parameters/idParam" + + - name: bodyId + in: body + schema: + type: object + get: + parameters: + - $ref: "#/parameters/limitParam" + - name: other + in: query + type: array + items: + $ref: "#/definitions/named" + - name: body + in: body + schema: + type: object + responses: + default: + schema: + type: object + 404: + $ref: "#/responses/notFound" + 200: + schema: + $ref: "#/definitions/tag" + "/other/place": + $ref: "#/x-shared-path/getItems" + +definitions: + named: + type: string + tag: + type: object + properties: + id: + type: integer + format: int64 + value: + type: string + audit: + $ref: "#/definitions/record" + record: + type: object + properties: + createdAt: + type: string + format: date-time + error: + type: object + required: + - id + - message + properties: + id: + type: integer + format: int64 + readOnly: true + message: + type: string + readOnly: true diff --git a/vendor/github.com/go-openapi/analysis/fixtures/widget-crud.yml b/vendor/github.com/go-openapi/analysis/fixtures/widget-crud.yml new file mode 100644 index 0000000000..d1acb92775 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/fixtures/widget-crud.yml @@ -0,0 +1,181 @@ +--- +swagger: '2.0' +info: + title: widget CRUD API + version: 4.2.0 +schemes: + - http +basePath: /api +consumes: + - application/json +produces: + - application/json +paths: + /common: + get: + operationId: commonGet + summary: here to test path collisons + responses: + '200': + description: OK + schema: + $ref: "#/definitions/widget" + + /widgets: + post: + operationId: create + summary: Create a new widget + parameters: + - name: info + in: body + schema: + $ref: "#/definitions/widget" + responses: + '201': + description: created + schema: + $ref: "#/definitions/widgetId" + default: + description: error + schema: + $ref: "#/definitions/error" + /widgets/{widgetid}: + get: + operationId: get + summary: Get a widget by id + parameters: + - $ref: "#/parameters/widgetid" + responses: + '200': + description: OK + schema: + $ref: "#/definitions/widget" + '401': + $ref: "#/responses/401" + '404': + $ref: "#/responses/404" + default: + description: error + schema: + $ref: "#/definitions/error" + delete: + operationId: delete + summary: delete a widget by id + parameters: + - name: widgetid + in: path + required: true + type: string + responses: + '200': + description: OK + '401': + description: unauthorized + schema: + $ref: "#/definitions/error" + '404': + description: resource not found + schema: + $ref: "#/definitions/error" + default: + description: error + schema: + $ref: "#/definitions/error" + post: + operationId: update + summary: update a widget by id + parameters: + - name: widgetid + in: path + required: true + type: string + - name: info + in: body + schema: + $ref: "#/definitions/widget" + responses: + '200': + description: OK + '401': + description: unauthorized + schema: + $ref: "#/definitions/error" + '404': + description: resource not found + schema: + $ref: "#/definitions/error" + default: + description: error + schema: + $ref: "#/definitions/error" + +definitions: + common: + type: object + required: + - id + properties: + id: + type: string + format: string + minLength: 1 + widget: + type: object + required: + - name + - description + properties: + id: + type: string + format: string + readOnly: true + name: + type: string + format: string + minLength: 1 + description: + type: string + format: string + minLength: 1 + widgetId: + type: object + required: + - id + properties: + id: + type: string + format: string + minLength: 1 + error: + type: object + required: + - message + properties: + code: + type: string + format: string + message: + type: string + fields: + type: string + +parameters: + common: + name: common + in: query + type: string + widgetid: + name: widgetid + in: path + required: true + type: string + +responses: + 401: + description: widget unauthorized + schema: + $ref: "#/definitions/error" + 404: + description: widget resource not found + schema: + $ref: "#/definitions/error" diff --git a/vendor/github.com/go-openapi/analysis/flatten.go b/vendor/github.com/go-openapi/analysis/flatten.go new file mode 100644 index 0000000000..23d7242f45 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/flatten.go @@ -0,0 +1,756 @@ +package analysis + +import ( + "fmt" + "log" + "net/http" + "path" + "sort" + "strings" + + "strconv" + + "github.com/go-openapi/jsonpointer" + swspec "github.com/go-openapi/spec" + "github.com/go-openapi/swag" +) + +// FlattenOpts configuration for flattening a swagger specification. +type FlattenOpts struct { + Spec *Spec + BasePath string + + _ struct{} // require keys +} + +// ExpandOpts creates a spec.ExpandOptions to configure expanding a specification document. +func (f *FlattenOpts) ExpandOpts(skipSchemas bool) *swspec.ExpandOptions { + return &swspec.ExpandOptions{RelativeBase: f.BasePath, SkipSchemas: skipSchemas} +} + +// Swagger gets the swagger specification for this flatten operation +func (f *FlattenOpts) Swagger() *swspec.Swagger { + return f.Spec.spec +} + +// Flatten an analyzed spec. +// +// To flatten a spec means: +// +// Expand the parameters, responses, path items, parameter items and header items. +// Import external (http, file) references so they become internal to the document. +// Move every inline schema to be a definition with an auto-generated name in a depth-first fashion. +// Rewritten schemas get a vendor extension x-go-gen-location so we know in which package they need to be rendered. +func Flatten(opts FlattenOpts) error { + // recursively expand responses, parameters, path items and items + err := swspec.ExpandSpec(opts.Swagger(), opts.ExpandOpts(true)) + if err != nil { + return err + } + opts.Spec.reload() // re-analyze + + // at this point there are no other references left but schemas + if err := importExternalReferences(&opts); err != nil { + return err + } + opts.Spec.reload() // re-analyze + + // rewrite the inline schemas (schemas that aren't simple types or arrays of simple types) + if err := nameInlinedSchemas(&opts); err != nil { + return err + } + opts.Spec.reload() // re-analyze + + // TODO: simplifiy known schema patterns to flat objects with properties? + return nil +} + +func nameInlinedSchemas(opts *FlattenOpts) error { + namer := &inlineSchemaNamer{Spec: opts.Swagger(), Operations: opRefsByRef(gatherOperations(opts.Spec, nil))} + depthFirst := sortDepthFirst(opts.Spec.allSchemas) + + for _, key := range depthFirst { + sch := opts.Spec.allSchemas[key] + if sch.Schema != nil && sch.Schema.Ref.String() == "" && !sch.TopLevel { // inline schema + asch, err := Schema(SchemaOpts{Schema: sch.Schema, Root: opts.Swagger(), BasePath: opts.BasePath}) + if err != nil { + return fmt.Errorf("schema analysis [%s]: %v", sch.Ref.String(), err) + } + + if !asch.IsSimpleSchema { // complex schemas get moved + if err := namer.Name(key, sch.Schema, asch); err != nil { + return err + } + } + } + } + return nil +} + +var depthGroupOrder = []string{"sharedOpParam", "opParam", "codeResponse", "defaultResponse", "definition"} + +func sortDepthFirst(data map[string]SchemaRef) (sorted []string) { + // group by category (shared params, op param, statuscode response, default response, definitions) + // sort groups internally by number of parts in the key and lexical names + // flatten groups into a single list of keys + grouped := make(map[string]keys, len(data)) + for k := range data { + split := keyParts(k) + var pk string + if split.IsSharedOperationParam() { + pk = "sharedOpParam" + } + if split.IsOperationParam() { + pk = "opParam" + } + if split.IsStatusCodeResponse() { + pk = "codeResponse" + } + if split.IsDefaultResponse() { + pk = "defaultResponse" + } + if split.IsDefinition() { + pk = "definition" + } + grouped[pk] = append(grouped[pk], key{len(split), k}) + } + + for _, pk := range depthGroupOrder { + res := grouped[pk] + sort.Sort(res) + for _, v := range res { + sorted = append(sorted, v.Key) + } + } + + return +} + +type key struct { + Segments int + Key string +} +type keys []key + +func (k keys) Len() int { return len(k) } +func (k keys) Swap(i, j int) { k[i], k[j] = k[j], k[i] } +func (k keys) Less(i, j int) bool { + return k[i].Segments > k[j].Segments || (k[i].Segments == k[j].Segments && k[i].Key < k[j].Key) +} + +type inlineSchemaNamer struct { + Spec *swspec.Swagger + Operations map[string]opRef +} + +func opRefsByRef(oprefs map[string]opRef) map[string]opRef { + result := make(map[string]opRef, len(oprefs)) + for _, v := range oprefs { + result[v.Ref.String()] = v + } + return result +} + +func (isn *inlineSchemaNamer) Name(key string, schema *swspec.Schema, aschema *AnalyzedSchema) error { + if swspec.Debug { + log.Printf("naming inlined schema at %s", key) + } + + parts := keyParts(key) + for _, name := range namesFromKey(parts, aschema, isn.Operations) { + if name != "" { + // create unique name + newName := uniqifyName(isn.Spec.Definitions, swag.ToJSONName(name)) + + // clone schema + sch, err := cloneSchema(schema) + if err != nil { + return err + } + + // replace values on schema + if err := rewriteSchemaToRef(isn.Spec, key, swspec.MustCreateRef("#/definitions/"+newName)); err != nil { + return fmt.Errorf("name inlined schema: %v", err) + } + + sch.AddExtension("x-go-gen-location", genLocation(parts)) + // fmt.Printf("{\n %q,\n \"\",\n spec.MustCreateRef(%q),\n \"\",\n},\n", key, "#/definitions/"+newName) + // save cloned schema to definitions + saveSchema(isn.Spec, newName, sch) + } + } + return nil +} + +func genLocation(parts splitKey) string { + if parts.IsOperation() { + return "operations" + } + if parts.IsDefinition() { + return "models" + } + return "" +} + +func uniqifyName(definitions swspec.Definitions, name string) string { + if name == "" { + name = "oaiGen" + } + if len(definitions) == 0 { + return name + } + + if _, ok := definitions[name]; !ok { + return name + } + name += "OAIGen" + var idx int + unique := name + _, known := definitions[unique] + for known { + idx++ + unique = fmt.Sprintf("%s%d", name, idx) + _, known = definitions[unique] + } + return unique +} + +func namesFromKey(parts splitKey, aschema *AnalyzedSchema, operations map[string]opRef) []string { + var baseNames [][]string + var startIndex int + if parts.IsOperation() { + // params + if parts.IsOperationParam() || parts.IsSharedOperationParam() { + piref := parts.PathItemRef() + if piref.String() != "" && parts.IsOperationParam() { + if op, ok := operations[piref.String()]; ok { + startIndex = 5 + baseNames = append(baseNames, []string{op.ID, "params", "body"}) + } + } else if parts.IsSharedOperationParam() { + pref := parts.PathRef() + for k, v := range operations { + if strings.HasPrefix(k, pref.String()) { + startIndex = 4 + baseNames = append(baseNames, []string{v.ID, "params", "body"}) + } + } + } + } + // responses + if parts.IsOperationResponse() { + piref := parts.PathItemRef() + if piref.String() != "" { + if op, ok := operations[piref.String()]; ok { + startIndex = 6 + baseNames = append(baseNames, []string{op.ID, parts.ResponseName(), "body"}) + } + } + } + } + + // definitions + if parts.IsDefinition() { + nm := parts.DefinitionName() + if nm != "" { + startIndex = 2 + baseNames = append(baseNames, []string{parts.DefinitionName()}) + } + } + + var result []string + for _, segments := range baseNames { + nm := parts.BuildName(segments, startIndex, aschema) + if nm != "" { + result = append(result, nm) + } + } + sort.Strings(result) + return result +} + +const ( + pths = "paths" + responses = "responses" + parameters = "parameters" + definitions = "definitions" +) + +var ignoredKeys map[string]struct{} + +func init() { + ignoredKeys = map[string]struct{}{ + "schema": {}, + "properties": {}, + "not": {}, + "anyOf": {}, + "oneOf": {}, + } +} + +type splitKey []string + +func (s splitKey) IsDefinition() bool { + return len(s) > 1 && s[0] == definitions +} + +func (s splitKey) DefinitionName() string { + if !s.IsDefinition() { + return "" + } + return s[1] +} + +func (s splitKey) BuildName(segments []string, startIndex int, aschema *AnalyzedSchema) string { + for _, part := range s[startIndex:] { + if _, ignored := ignoredKeys[part]; !ignored { + if part == "items" || part == "additionalItems" { + if aschema.IsTuple || aschema.IsTupleWithExtra { + segments = append(segments, "tuple") + } else { + segments = append(segments, "items") + } + if part == "additionalItems" { + segments = append(segments, part) + } + continue + } + segments = append(segments, part) + } + } + return strings.Join(segments, " ") +} + +func (s splitKey) IsOperation() bool { + return len(s) > 1 && s[0] == pths +} + +func (s splitKey) IsSharedOperationParam() bool { + return len(s) > 2 && s[0] == pths && s[2] == parameters +} + +func (s splitKey) IsOperationParam() bool { + return len(s) > 3 && s[0] == pths && s[3] == parameters +} + +func (s splitKey) IsOperationResponse() bool { + return len(s) > 3 && s[0] == pths && s[3] == responses +} + +func (s splitKey) IsDefaultResponse() bool { + return len(s) > 4 && s[0] == pths && s[3] == responses && s[4] == "default" +} + +func (s splitKey) IsStatusCodeResponse() bool { + isInt := func() bool { + _, err := strconv.Atoi(s[4]) + return err == nil + } + return len(s) > 4 && s[0] == pths && s[3] == responses && isInt() +} + +func (s splitKey) ResponseName() string { + if s.IsStatusCodeResponse() { + code, _ := strconv.Atoi(s[4]) + return http.StatusText(code) + } + if s.IsDefaultResponse() { + return "Default" + } + return "" +} + +var validMethods map[string]struct{} + +func init() { + validMethods = map[string]struct{}{ + "GET": {}, + "HEAD": {}, + "OPTIONS": {}, + "PATCH": {}, + "POST": {}, + "PUT": {}, + "DELETE": {}, + } +} + +func (s splitKey) PathItemRef() swspec.Ref { + if len(s) < 3 { + return swspec.Ref{} + } + pth, method := s[1], s[2] + if _, validMethod := validMethods[strings.ToUpper(method)]; !validMethod && !strings.HasPrefix(method, "x-") { + return swspec.Ref{} + } + return swspec.MustCreateRef("#" + path.Join("/", pths, jsonpointer.Escape(pth), strings.ToUpper(method))) +} + +func (s splitKey) PathRef() swspec.Ref { + if !s.IsOperation() { + return swspec.Ref{} + } + return swspec.MustCreateRef("#" + path.Join("/", pths, jsonpointer.Escape(s[1]))) +} + +func keyParts(key string) splitKey { + var res []string + for _, part := range strings.Split(key[1:], "/") { + if part != "" { + res = append(res, jsonpointer.Unescape(part)) + } + } + return res +} + +func rewriteSchemaToRef(spec *swspec.Swagger, key string, ref swspec.Ref) error { + if swspec.Debug { + log.Printf("rewriting schema to ref for %s with %s", key, ref.String()) + } + pth := key[1:] + ptr, err := jsonpointer.New(pth) + if err != nil { + return err + } + + value, _, err := ptr.Get(spec) + if err != nil { + return err + } + + switch refable := value.(type) { + case *swspec.Schema: + return rewriteParentRef(spec, key, ref) + case *swspec.SchemaOrBool: + if refable.Schema != nil { + refable.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + } + case *swspec.SchemaOrArray: + if refable.Schema != nil { + refable.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + } + case swspec.Schema: + return rewriteParentRef(spec, key, ref) + default: + return fmt.Errorf("no schema with ref found at %s for %T", key, value) + } + + return nil +} + +func rewriteParentRef(spec *swspec.Swagger, key string, ref swspec.Ref) error { + pth := key[1:] + parent, entry := path.Dir(pth), path.Base(pth) + if swspec.Debug { + log.Println("getting schema holder at:", parent) + } + + pptr, err := jsonpointer.New(parent) + if err != nil { + return err + } + pvalue, _, err := pptr.Get(spec) + if err != nil { + return fmt.Errorf("can't get parent for %s: %v", parent, err) + } + if swspec.Debug { + log.Printf("rewriting holder for %T", pvalue) + } + + switch container := pvalue.(type) { + case swspec.Response: + if err := rewriteParentRef(spec, "#"+parent, ref); err != nil { + return err + } + + case *swspec.Response: + container.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + + case *swspec.Responses: + statusCode, err := strconv.Atoi(entry) + if err != nil { + return fmt.Errorf("%s not a number: %v", pth, err) + } + resp := container.StatusCodeResponses[statusCode] + resp.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + container.StatusCodeResponses[statusCode] = resp + + case map[string]swspec.Response: + resp := container[entry] + resp.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + container[entry] = resp + + case swspec.Parameter: + if err := rewriteParentRef(spec, "#"+parent, ref); err != nil { + return err + } + + case map[string]swspec.Parameter: + param := container[entry] + param.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + container[entry] = param + + case []swspec.Parameter: + idx, err := strconv.Atoi(entry) + if err != nil { + return fmt.Errorf("%s not a number: %v", pth, err) + } + param := container[idx] + param.Schema = &swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + container[idx] = param + + case swspec.Definitions: + container[entry] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + + case map[string]swspec.Schema: + container[entry] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + + case []swspec.Schema: + idx, err := strconv.Atoi(entry) + if err != nil { + return fmt.Errorf("%s not a number: %v", pth, err) + } + container[idx] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + + case *swspec.SchemaOrArray: + idx, err := strconv.Atoi(entry) + if err != nil { + return fmt.Errorf("%s not a number: %v", pth, err) + } + container.Schemas[idx] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + default: + return fmt.Errorf("unhandled parent schema rewrite %s (%T)", key, pvalue) + } + return nil +} + +func cloneSchema(schema *swspec.Schema) (*swspec.Schema, error) { + var sch swspec.Schema + if err := swag.FromDynamicJSON(schema, &sch); err != nil { + return nil, fmt.Errorf("name inlined schema: %v", err) + } + return &sch, nil +} + +func importExternalReferences(opts *FlattenOpts) error { + groupedRefs := reverseIndexForSchemaRefs(opts) + + for refStr, entry := range groupedRefs { + if !entry.Ref.HasFragmentOnly { + if swspec.Debug { + log.Printf("importing external schema for [%s] from %s", strings.Join(entry.Keys, ", "), refStr) + } + // resolve to actual schema + sch, err := swspec.ResolveRefWithBase(opts.Swagger(), &entry.Ref, opts.ExpandOpts(false)) + if err != nil { + return err + } + if sch == nil { + return fmt.Errorf("no schema found at %s for [%s]", refStr, strings.Join(entry.Keys, ", ")) + } + if swspec.Debug { + log.Printf("importing external schema for [%s] from %s", strings.Join(entry.Keys, ", "), refStr) + } + + // generate a unique name + newName := uniqifyName(opts.Swagger().Definitions, nameFromRef(entry.Ref)) + if swspec.Debug { + log.Printf("new name for [%s]: %s", strings.Join(entry.Keys, ", "), newName) + } + + // rewrite the external refs to local ones + for _, key := range entry.Keys { + if err := updateRef(opts.Swagger(), key, swspec.MustCreateRef("#"+path.Join("/definitions", newName))); err != nil { + return err + } + } + + // add the resolved schema to the definitions + saveSchema(opts.Swagger(), newName, sch) + } + } + return nil +} + +type refRevIdx struct { + Ref swspec.Ref + Keys []string +} + +func reverseIndexForSchemaRefs(opts *FlattenOpts) map[string]refRevIdx { + collected := make(map[string]refRevIdx) + for key, schRef := range opts.Spec.references.schemas { + if entry, ok := collected[schRef.String()]; ok { + entry.Keys = append(entry.Keys, key) + collected[schRef.String()] = entry + } else { + collected[schRef.String()] = refRevIdx{ + Ref: schRef, + Keys: []string{key}, + } + } + } + return collected +} + +func nameFromRef(ref swspec.Ref) string { + u := ref.GetURL() + if u.Fragment != "" { + return swag.ToJSONName(path.Base(u.Fragment)) + } + if u.Path != "" { + bn := path.Base(u.Path) + if bn != "" && bn != "/" { + ext := path.Ext(bn) + if ext != "" { + return swag.ToJSONName(bn[:len(bn)-len(ext)]) + } + return swag.ToJSONName(bn) + } + } + return swag.ToJSONName(strings.Replace(u.Host, ".", " ", -1)) +} + +func saveSchema(spec *swspec.Swagger, name string, schema *swspec.Schema) { + if schema == nil { + return + } + if spec.Definitions == nil { + spec.Definitions = make(map[string]swspec.Schema, 150) + } + spec.Definitions[name] = *schema +} + +func updateRef(spec *swspec.Swagger, key string, ref swspec.Ref) error { + if swspec.Debug { + log.Printf("updating ref for %s with %s", key, ref.String()) + } + pth := key[1:] + ptr, err := jsonpointer.New(pth) + if err != nil { + return err + } + + value, _, err := ptr.Get(spec) + if err != nil { + return err + } + + switch refable := value.(type) { + case *swspec.Schema: + refable.Ref = ref + case *swspec.SchemaOrBool: + if refable.Schema != nil { + refable.Schema.Ref = ref + } + case *swspec.SchemaOrArray: + if refable.Schema != nil { + refable.Schema.Ref = ref + } + case swspec.Schema: + parent, entry := path.Dir(pth), path.Base(pth) + if swspec.Debug { + log.Println("getting schema holder at:", parent) + } + + pptr, err := jsonpointer.New(parent) + if err != nil { + return err + } + pvalue, _, err := pptr.Get(spec) + if err != nil { + return fmt.Errorf("can't get parent for %s: %v", parent, err) + } + + switch container := pvalue.(type) { + case swspec.Definitions: + container[entry] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + + case map[string]swspec.Schema: + container[entry] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + + case []swspec.Schema: + idx, err := strconv.Atoi(entry) + if err != nil { + return fmt.Errorf("%s not a number: %v", pth, err) + } + container[idx] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + + case *swspec.SchemaOrArray: + idx, err := strconv.Atoi(entry) + if err != nil { + return fmt.Errorf("%s not a number: %v", pth, err) + } + container.Schemas[idx] = swspec.Schema{SchemaProps: swspec.SchemaProps{Ref: ref}} + + } + + default: + return fmt.Errorf("no schema with ref found at %s for %T", key, value) + } + + return nil +} + +func containsString(names []string, name string) bool { + for _, nm := range names { + if nm == name { + return true + } + } + return false +} + +type opRef struct { + Method string + Path string + Key string + ID string + Op *swspec.Operation + Ref swspec.Ref +} + +type opRefs []opRef + +func (o opRefs) Len() int { return len(o) } +func (o opRefs) Swap(i, j int) { o[i], o[j] = o[j], o[i] } +func (o opRefs) Less(i, j int) bool { return o[i].Key < o[j].Key } + +func gatherOperations(specDoc *Spec, operationIDs []string) map[string]opRef { + var oprefs opRefs + + for method, pathItem := range specDoc.Operations() { + for pth, operation := range pathItem { + vv := *operation + oprefs = append(oprefs, opRef{ + Key: swag.ToGoName(strings.ToLower(method) + " " + pth), + Method: method, + Path: pth, + ID: vv.ID, + Op: &vv, + Ref: swspec.MustCreateRef("#" + path.Join("/paths", jsonpointer.Escape(pth), method)), + }) + } + } + + sort.Sort(oprefs) + + operations := make(map[string]opRef) + for _, opr := range oprefs { + nm := opr.ID + if nm == "" { + nm = opr.Key + } + + oo, found := operations[nm] + if found && oo.Method != opr.Method && oo.Path != opr.Path { + nm = opr.Key + } + if len(operationIDs) == 0 || containsString(operationIDs, opr.ID) || containsString(operationIDs, nm) { + opr.ID = nm + opr.Op.ID = nm + operations[nm] = opr + } + } + + return operations +} diff --git a/vendor/github.com/go-openapi/analysis/flatten_test.go b/vendor/github.com/go-openapi/analysis/flatten_test.go new file mode 100644 index 0000000000..6ccdf77513 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/flatten_test.go @@ -0,0 +1,805 @@ +package analysis + +import ( + "path/filepath" + "strings" + "testing" + + "github.com/go-openapi/jsonpointer" + "github.com/go-openapi/spec" + "github.com/stretchr/testify/assert" +) + +func TestSaveDefinition(t *testing.T) { + sp := &spec.Swagger{} + saveSchema(sp, "theName", spec.StringProperty()) + assert.Contains(t, sp.Definitions, "theName") +} + +func TestNameFromRef(t *testing.T) { + values := []struct{ Source, Expected string }{ + {"#/definitions/errorModel", "errorModel"}, + {"http://somewhere.com/definitions/errorModel", "errorModel"}, + {"http://somewhere.com/definitions/errorModel.json", "errorModel"}, + {"/definitions/errorModel", "errorModel"}, + {"/definitions/errorModel.json", "errorModel"}, + {"http://somewhere.com", "somewhereCom"}, + {"#", ""}, + } + + for _, v := range values { + assert.Equal(t, v.Expected, nameFromRef(spec.MustCreateRef(v.Source))) + } +} + +func TestDefinitionName(t *testing.T) { + values := []struct { + Source, Expected string + Definitions spec.Definitions + }{ + {"#/definitions/errorModel", "errorModel", map[string]spec.Schema(nil)}, + {"http://somewhere.com/definitions/errorModel", "errorModel", map[string]spec.Schema(nil)}, + {"#/definitions/errorModel", "errorModel", map[string]spec.Schema{"apples": *spec.StringProperty()}}, + {"#/definitions/errorModel", "errorModelOAIGen", map[string]spec.Schema{"errorModel": *spec.StringProperty()}}, + {"#/definitions/errorModel", "errorModelOAIGen1", map[string]spec.Schema{"errorModel": *spec.StringProperty(), "errorModelOAIGen": *spec.StringProperty()}}, + {"#", "oaiGen", nil}, + } + + for _, v := range values { + assert.Equal(t, v.Expected, uniqifyName(v.Definitions, nameFromRef(spec.MustCreateRef(v.Source)))) + } +} + +func TestUpdateRef(t *testing.T) { + bp := filepath.Join("fixtures", "external_definitions.yml") + sp, err := loadSpec(bp) + if assert.NoError(t, err) { + + values := []struct { + Key string + Ref spec.Ref + }{ + {"#/parameters/someParam/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/parameters/1/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/responses/someResponse/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/get/responses/default/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/get/responses/200/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/namedAgain", spec.MustCreateRef("#/definitions/named")}, + {"#/definitions/datedTag/allOf/1", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/datedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/datedTaggedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/datedTaggedRecords/additionalItems", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/otherRecords/items", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/tags/additionalProperties", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/namedThing/properties/name", spec.MustCreateRef("#/definitions/named")}, + } + + for _, v := range values { + err := updateRef(sp, v.Key, v.Ref) + if assert.NoError(t, err) { + ptr, err := jsonpointer.New(v.Key[1:]) + if assert.NoError(t, err) { + vv, _, err := ptr.Get(sp) + + if assert.NoError(t, err) { + switch tv := vv.(type) { + case *spec.Schema: + assert.Equal(t, v.Ref.String(), tv.Ref.String()) + case spec.Schema: + assert.Equal(t, v.Ref.String(), tv.Ref.String()) + case *spec.SchemaOrBool: + assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String()) + case *spec.SchemaOrArray: + assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String()) + default: + assert.Fail(t, "unknown type", "got %T", vv) + } + } + } + } + } + } +} + +func TestImportExternalReferences(t *testing.T) { + bp := filepath.Join(".", "fixtures", "external_definitions.yml") + sp, err := loadSpec(bp) + if assert.NoError(t, err) { + + values := []struct { + Key string + Ref spec.Ref + }{ + {"#/parameters/someParam/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/parameters/1/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/responses/someResponse/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/get/responses/default/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/get/responses/200/schema", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/namedAgain", spec.MustCreateRef("#/definitions/named")}, + {"#/definitions/datedTag/allOf/1", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/datedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/datedTaggedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/datedTaggedRecords/additionalItems", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/otherRecords/items", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/tags/additionalProperties", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/namedThing/properties/name", spec.MustCreateRef("#/definitions/named")}, + } + for _, v := range values { + // technically not necessary to run for each value, but if things go right + // this is idempotent, so having it repeat shouldn't matter + // this validates that behavior + err := importExternalReferences(&FlattenOpts{ + Spec: New(sp), + BasePath: bp, + }) + + if assert.NoError(t, err) { + + ptr, err := jsonpointer.New(v.Key[1:]) + if assert.NoError(t, err) { + vv, _, err := ptr.Get(sp) + + if assert.NoError(t, err) { + switch tv := vv.(type) { + case *spec.Schema: + assert.Equal(t, v.Ref.String(), tv.Ref.String(), "for %s", v.Key) + case spec.Schema: + assert.Equal(t, v.Ref.String(), tv.Ref.String(), "for %s", v.Key) + case *spec.SchemaOrBool: + assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String(), "for %s", v.Key) + case *spec.SchemaOrArray: + assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String(), "for %s", v.Key) + default: + assert.Fail(t, "unknown type", "got %T", vv) + } + } + } + } + } + assert.Len(t, sp.Definitions, 11) + assert.Contains(t, sp.Definitions, "tag") + assert.Contains(t, sp.Definitions, "named") + assert.Contains(t, sp.Definitions, "record") + } +} + +func TestRewriteSchemaRef(t *testing.T) { + bp := filepath.Join("fixtures", "inline_schemas.yml") + sp, err := loadSpec(bp) + if assert.NoError(t, err) { + + values := []struct { + Key string + Ref spec.Ref + }{ + {"#/parameters/someParam/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/parameters/1/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/responses/someResponse/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/get/responses/default/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/paths/~1some~1where~1{id}/get/responses/200/schema", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/namedAgain", spec.MustCreateRef("#/definitions/named")}, + {"#/definitions/datedTag/allOf/1", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/datedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/datedTaggedRecords/items/1", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/datedTaggedRecords/additionalItems", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/otherRecords/items", spec.MustCreateRef("#/definitions/record")}, + {"#/definitions/tags/additionalProperties", spec.MustCreateRef("#/definitions/tag")}, + {"#/definitions/namedThing/properties/name", spec.MustCreateRef("#/definitions/named")}, + } + + for i, v := range values { + err := rewriteSchemaToRef(sp, v.Key, v.Ref) + if assert.NoError(t, err) { + ptr, err := jsonpointer.New(v.Key[1:]) + if assert.NoError(t, err) { + vv, _, err := ptr.Get(sp) + + if assert.NoError(t, err) { + switch tv := vv.(type) { + case *spec.Schema: + assert.Equal(t, v.Ref.String(), tv.Ref.String(), "at %d for %s", i, v.Key) + case spec.Schema: + assert.Equal(t, v.Ref.String(), tv.Ref.String(), "at %d for %s", i, v.Key) + case *spec.SchemaOrBool: + assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String(), "at %d for %s", i, v.Key) + case *spec.SchemaOrArray: + assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String(), "at %d for %s", i, v.Key) + default: + assert.Fail(t, "unknown type", "got %T", vv) + } + } + } + } + } + } +} + +func TestSplitKey(t *testing.T) { + + type KeyFlag uint64 + + const ( + isOperation KeyFlag = 1 << iota + isDefinition + isSharedOperationParam + isOperationParam + isOperationResponse + isDefaultResponse + isStatusCodeResponse + ) + + values := []struct { + Key string + Flags KeyFlag + PathItemRef spec.Ref + PathRef spec.Ref + Name string + }{ + { + "#/paths/~1some~1where~1{id}/parameters/1/schema", + isOperation | isSharedOperationParam, + spec.Ref{}, + spec.MustCreateRef("#/paths/~1some~1where~1{id}"), + "", + }, + { + "#/paths/~1some~1where~1{id}/get/parameters/2/schema", + isOperation | isOperationParam, + spec.MustCreateRef("#/paths/~1some~1where~1{id}/GET"), + spec.MustCreateRef("#/paths/~1some~1where~1{id}"), + "", + }, + { + "#/paths/~1some~1where~1{id}/get/responses/default/schema", + isOperation | isOperationResponse | isDefaultResponse, + spec.MustCreateRef("#/paths/~1some~1where~1{id}/GET"), + spec.MustCreateRef("#/paths/~1some~1where~1{id}"), + "Default", + }, + { + "#/paths/~1some~1where~1{id}/get/responses/200/schema", + isOperation | isOperationResponse | isStatusCodeResponse, + spec.MustCreateRef("#/paths/~1some~1where~1{id}/GET"), + spec.MustCreateRef("#/paths/~1some~1where~1{id}"), + "OK", + }, + { + "#/definitions/namedAgain", + isDefinition, + spec.Ref{}, + spec.Ref{}, + "namedAgain", + }, + { + "#/definitions/datedRecords/items/1", + isDefinition, + spec.Ref{}, + spec.Ref{}, + "datedRecords", + }, + { + "#/definitions/datedRecords/items/1", + isDefinition, + spec.Ref{}, + spec.Ref{}, + "datedRecords", + }, + { + "#/definitions/datedTaggedRecords/items/1", + isDefinition, + spec.Ref{}, + spec.Ref{}, + "datedTaggedRecords", + }, + { + "#/definitions/datedTaggedRecords/additionalItems", + isDefinition, + spec.Ref{}, + spec.Ref{}, + "datedTaggedRecords", + }, + { + "#/definitions/otherRecords/items", + isDefinition, + spec.Ref{}, + spec.Ref{}, + "otherRecords", + }, + { + "#/definitions/tags/additionalProperties", + isDefinition, + spec.Ref{}, + spec.Ref{}, + "tags", + }, + { + "#/definitions/namedThing/properties/name", + isDefinition, + spec.Ref{}, + spec.Ref{}, + "namedThing", + }, + } + + for i, v := range values { + parts := keyParts(v.Key) + pref := parts.PathRef() + piref := parts.PathItemRef() + assert.Equal(t, v.PathRef.String(), pref.String(), "pathRef: %s at %d", v.Key, i) + assert.Equal(t, v.PathItemRef.String(), piref.String(), "pathItemRef: %s at %d", v.Key, i) + + if v.Flags&isOperation != 0 { + assert.True(t, parts.IsOperation(), "isOperation: %s at %d", v.Key, i) + } else { + assert.False(t, parts.IsOperation(), "isOperation: %s at %d", v.Key, i) + } + if v.Flags&isDefinition != 0 { + assert.True(t, parts.IsDefinition(), "isDefinition: %s at %d", v.Key, i) + assert.Equal(t, v.Name, parts.DefinitionName(), "definition name: %s at %d", v.Key, i) + } else { + assert.False(t, parts.IsDefinition(), "isDefinition: %s at %d", v.Key, i) + if v.Name != "" { + assert.Equal(t, v.Name, parts.ResponseName(), "response name: %s at %d", v.Key, i) + } + } + if v.Flags&isOperationParam != 0 { + assert.True(t, parts.IsOperationParam(), "isOperationParam: %s at %d", v.Key, i) + } else { + assert.False(t, parts.IsOperationParam(), "isOperationParam: %s at %d", v.Key, i) + } + if v.Flags&isSharedOperationParam != 0 { + assert.True(t, parts.IsSharedOperationParam(), "isSharedOperationParam: %s at %d", v.Key, i) + } else { + assert.False(t, parts.IsSharedOperationParam(), "isSharedOperationParam: %s at %d", v.Key, i) + } + if v.Flags&isOperationResponse != 0 { + assert.True(t, parts.IsOperationResponse(), "isOperationResponse: %s at %d", v.Key, i) + } else { + assert.False(t, parts.IsOperationResponse(), "isOperationResponse: %s at %d", v.Key, i) + } + if v.Flags&isDefaultResponse != 0 { + assert.True(t, parts.IsDefaultResponse(), "isDefaultResponse: %s at %d", v.Key, i) + } else { + assert.False(t, parts.IsDefaultResponse(), "isDefaultResponse: %s at %d", v.Key, i) + } + if v.Flags&isStatusCodeResponse != 0 { + assert.True(t, parts.IsStatusCodeResponse(), "isStatusCodeResponse: %s at %d", v.Key, i) + } else { + assert.False(t, parts.IsStatusCodeResponse(), "isStatusCodeResponse: %s at %d", v.Key, i) + } + } +} + +func definitionPtr(key string) string { + if !strings.HasPrefix(key, "#/definitions") { + return key + } + return strings.Join(strings.Split(key, "/")[:3], "/") +} + +func TestNamesFromKey(t *testing.T) { + bp := filepath.Join("fixtures", "inline_schemas.yml") + sp, err := loadSpec(bp) + if assert.NoError(t, err) { + + values := []struct { + Key string + Names []string + }{ + {"#/paths/~1some~1where~1{id}/parameters/1/schema", []string{"GetSomeWhereID params body", "PostSomeWhereID params body"}}, + {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", []string{"GetSomeWhereID params body"}}, + {"#/paths/~1some~1where~1{id}/get/responses/default/schema", []string{"GetSomeWhereID Default body"}}, + {"#/paths/~1some~1where~1{id}/get/responses/200/schema", []string{"GetSomeWhereID OK body"}}, + {"#/definitions/namedAgain", []string{"namedAgain"}}, + {"#/definitions/datedTag/allOf/1", []string{"datedTag allOf 1"}}, + {"#/definitions/datedRecords/items/1", []string{"datedRecords tuple 1"}}, + {"#/definitions/datedTaggedRecords/items/1", []string{"datedTaggedRecords tuple 1"}}, + {"#/definitions/datedTaggedRecords/additionalItems", []string{"datedTaggedRecords tuple additionalItems"}}, + {"#/definitions/otherRecords/items", []string{"otherRecords items"}}, + {"#/definitions/tags/additionalProperties", []string{"tags additionalProperties"}}, + {"#/definitions/namedThing/properties/name", []string{"namedThing name"}}, + } + + for i, v := range values { + ptr, err := jsonpointer.New(definitionPtr(v.Key)[1:]) + if assert.NoError(t, err) { + vv, _, err := ptr.Get(sp) + if assert.NoError(t, err) { + switch tv := vv.(type) { + case *spec.Schema: + aschema, err := Schema(SchemaOpts{Schema: tv, Root: sp, BasePath: bp}) + if assert.NoError(t, err) { + names := namesFromKey(keyParts(v.Key), aschema, opRefsByRef(gatherOperations(New(sp), nil))) + assert.Equal(t, v.Names, names, "for %s at %d", v.Key, i) + } + case spec.Schema: + aschema, err := Schema(SchemaOpts{Schema: &tv, Root: sp, BasePath: bp}) + if assert.NoError(t, err) { + names := namesFromKey(keyParts(v.Key), aschema, opRefsByRef(gatherOperations(New(sp), nil))) + assert.Equal(t, v.Names, names, "for %s at %d", v.Key, i) + } + default: + assert.Fail(t, "unknown type", "got %T", vv) + } + } + } + } + } +} + +func TestDepthFirstSort(t *testing.T) { + bp := filepath.Join("fixtures", "inline_schemas.yml") + sp, err := loadSpec(bp) + values := []string{ + "#/paths/~1some~1where~1{id}/parameters/1/schema/properties/createdAt", + "#/paths/~1some~1where~1{id}/parameters/1/schema", + "#/paths/~1some~1where~1{id}/get/parameters/2/schema/properties/createdAt", + "#/paths/~1some~1where~1{id}/get/parameters/2/schema", + "#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/id", + "#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/value", + "#/paths/~1some~1where~1{id}/get/responses/200/schema", + "#/paths/~1some~1where~1{id}/get/responses/404/schema", + "#/paths/~1some~1where~1{id}/get/responses/default/schema/properties/createdAt", + "#/paths/~1some~1where~1{id}/get/responses/default/schema", + "#/definitions/datedRecords/items/1/properties/createdAt", + "#/definitions/datedTaggedRecords/items/1/properties/createdAt", + "#/definitions/namedThing/properties/name/properties/id", + "#/definitions/records/items/0/properties/createdAt", + "#/definitions/datedTaggedRecords/additionalItems/properties/id", + "#/definitions/datedTaggedRecords/additionalItems/properties/value", + "#/definitions/otherRecords/items/properties/createdAt", + "#/definitions/tags/additionalProperties/properties/id", + "#/definitions/tags/additionalProperties/properties/value", + "#/definitions/datedRecords/items/0", + "#/definitions/datedRecords/items/1", + "#/definitions/datedTag/allOf/0", + "#/definitions/datedTag/allOf/1", + "#/definitions/datedTag/properties/id", + "#/definitions/datedTag/properties/value", + "#/definitions/datedTaggedRecords/items/0", + "#/definitions/datedTaggedRecords/items/1", + "#/definitions/namedAgain/properties/id", + "#/definitions/namedThing/properties/name", + "#/definitions/pneumonoultramicroscopicsilicovolcanoconiosisAntidisestablishmentarianism/properties/floccinaucinihilipilificationCreatedAt", + "#/definitions/records/items/0", + "#/definitions/datedTaggedRecords/additionalItems", + "#/definitions/otherRecords/items", + "#/definitions/tags/additionalProperties", + "#/definitions/datedRecords", + "#/definitions/datedTag", + "#/definitions/datedTaggedRecords", + "#/definitions/namedAgain", + "#/definitions/namedThing", + "#/definitions/otherRecords", + "#/definitions/pneumonoultramicroscopicsilicovolcanoconiosisAntidisestablishmentarianism", + "#/definitions/records", + "#/definitions/tags", + } + if assert.NoError(t, err) { + a := New(sp) + result := sortDepthFirst(a.allSchemas) + assert.Equal(t, values, result) + } +} + +func TestNameInlinedSchemas(t *testing.T) { + bp := filepath.Join(".", "fixtures", "nested_inline_schemas.yml") + sp, err := loadSpec(bp) + values := []struct { + Key string + Location string + Ref spec.Ref + }{ + {"#/paths/~1some~1where~1{id}/parameters/1/schema/items", "#/definitions/postSomeWhereIdParamsBody/items", spec.MustCreateRef("#/definitions/postSomeWhereIdParamsBodyItems")}, + {"#/paths/~1some~1where~1{id}/parameters/1/schema", "#/paths/~1some~1where~1{id}/parameters/1/schema", spec.MustCreateRef("#/definitions/postSomeWhereIdParamsBody")}, + {"#/paths/~1some~1where~1{id}/get/parameters/2/schema/properties/record/items/2/properties/name", "#/definitions/getSomeWhereIdParamsBodyRecordItems2/properties/name", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems2Name")}, + {"#/paths/~1some~1where~1{id}/get/parameters/2/schema/properties/record/items/1", "#/definitions/getSomeWhereIdParamsBodyRecord/items/1", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems1")}, + {"#/paths/~1some~1where~1{id}/get/parameters/2/schema/properties/record/items/2", "#/definitions/getSomeWhereIdParamsBodyRecord/items/2", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems2")}, + {"#/paths/~1some~1where~1{id}/get/parameters/2/schema/properties/record", "#/definitions/getSomeWhereIdParamsBodyOAIGen/properties/record", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecord")}, + {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", "#/paths/~1some~1where~1{id}/get/parameters/2/schema", spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyOAIGen")}, + {"#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/record/items/2/properties/name", "#/definitions/getSomeWhereIdOKBodyRecordItems2/properties/name", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBodyRecordItems2Name")}, + {"#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/record/items/1", "#/definitions/getSomeWhereIdOKBodyRecord/items/1", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBodyRecordItems1")}, + {"#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/record/items/2", "#/definitions/getSomeWhereIdOKBodyRecord/items/2", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBodyRecordItems2")}, + {"#/paths/~1some~1where~1{id}/get/responses/200/schema/properties/record", "#/definitions/getSomeWhereIdOKBody/properties/record", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBodyRecord")}, + {"#/paths/~1some~1where~1{id}/get/responses/200/schema", "#/paths/~1some~1where~1{id}/get/responses/200/schema", spec.MustCreateRef("#/definitions/getSomeWhereIdOKBody")}, + {"#/paths/~1some~1where~1{id}/get/responses/default/schema/properties/record/items/2/properties/name", "#/definitions/getSomeWhereIdDefaultBodyRecordItems2/properties/name", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBodyRecordItems2Name")}, + {"#/paths/~1some~1where~1{id}/get/responses/default/schema/properties/record/items/1", "#/definitions/getSomeWhereIdDefaultBodyRecord/items/1", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBodyRecordItems1")}, + {"#/paths/~1some~1where~1{id}/get/responses/default/schema/properties/record/items/2", "#/definitions/getSomeWhereIdDefaultBodyRecord/items/2", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBodyRecordItems2")}, + {"#/paths/~1some~1where~1{id}/get/responses/default/schema/properties/record", "#/definitions/getSomeWhereIdDefaultBody/properties/record", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBodyRecord")}, + {"#/paths/~1some~1where~1{id}/get/responses/default/schema", "#/paths/~1some~1where~1{id}/get/responses/default/schema", spec.MustCreateRef("#/definitions/getSomeWhereIdDefaultBody")}, + {"#/definitions/nestedThing/properties/record/items/2/allOf/1/additionalProperties", "#/definitions/nestedThingRecordItems2AllOf1/additionalProperties", spec.MustCreateRef("#/definitions/nestedThingRecordItems2AllOf1AdditionalProperties")}, + {"#/definitions/nestedThing/properties/record/items/2/allOf/1", "#/definitions/nestedThingRecordItems2/allOf/1", spec.MustCreateRef("#/definitions/nestedThingRecordItems2AllOf1")}, + {"#/definitions/nestedThing/properties/record/items/2/properties/name", "#/definitions/nestedThingRecordItems2/properties/name", spec.MustCreateRef("#/definitions/nestedThingRecordItems2Name")}, + {"#/definitions/nestedThing/properties/record/items/1", "#/definitions/nestedThingRecord/items/1", spec.MustCreateRef("#/definitions/nestedThingRecordItems1")}, + {"#/definitions/nestedThing/properties/record/items/2", "#/definitions/nestedThingRecord/items/2", spec.MustCreateRef("#/definitions/nestedThingRecordItems2")}, + {"#/definitions/datedRecords/items/1", "#/definitions/datedRecords/items/1", spec.MustCreateRef("#/definitions/datedRecordsItems1")}, + {"#/definitions/datedTaggedRecords/items/1", "#/definitions/datedTaggedRecords/items/1", spec.MustCreateRef("#/definitions/datedTaggedRecordsItems1")}, + {"#/definitions/namedThing/properties/name", "#/definitions/namedThing/properties/name", spec.MustCreateRef("#/definitions/namedThingName")}, + {"#/definitions/nestedThing/properties/record", "#/definitions/nestedThing/properties/record", spec.MustCreateRef("#/definitions/nestedThingRecord")}, + {"#/definitions/records/items/0", "#/definitions/records/items/0", spec.MustCreateRef("#/definitions/recordsItems0")}, + {"#/definitions/datedTaggedRecords/additionalItems", "#/definitions/datedTaggedRecords/additionalItems", spec.MustCreateRef("#/definitions/datedTaggedRecordsItemsAdditionalItems")}, + {"#/definitions/otherRecords/items", "#/definitions/otherRecords/items", spec.MustCreateRef("#/definitions/otherRecordsItems")}, + {"#/definitions/tags/additionalProperties", "#/definitions/tags/additionalProperties", spec.MustCreateRef("#/definitions/tagsAdditionalProperties")}, + } + if assert.NoError(t, err) { + err := nameInlinedSchemas(&FlattenOpts{ + Spec: New(sp), + BasePath: bp, + }) + + if assert.NoError(t, err) { + for i, v := range values { + ptr, err := jsonpointer.New(v.Location[1:]) + if assert.NoError(t, err, "at %d for %s", i, v.Key) { + vv, _, err := ptr.Get(sp) + + if assert.NoError(t, err, "at %d for %s", i, v.Key) { + switch tv := vv.(type) { + case *spec.Schema: + assert.Equal(t, v.Ref.String(), tv.Ref.String(), "at %d for %s", i, v.Key) + case spec.Schema: + assert.Equal(t, v.Ref.String(), tv.Ref.String(), "at %d for %s", i, v.Key) + case *spec.SchemaOrBool: + var sRef spec.Ref + if tv != nil && tv.Schema != nil { + sRef = tv.Schema.Ref + } + assert.Equal(t, v.Ref.String(), sRef.String(), "at %d for %s", i, v.Key) + case *spec.SchemaOrArray: + var sRef spec.Ref + if tv != nil && tv.Schema != nil { + sRef = tv.Schema.Ref + } + assert.Equal(t, v.Ref.String(), sRef.String(), "at %d for %s", i, v.Key) + default: + assert.Fail(t, "unknown type", "got %T", vv) + } + } + } + } + } + + for k, rr := range New(sp).allSchemas { + if !strings.HasPrefix(k, "#/responses") && !strings.HasPrefix(k, "#/parameters") { + if rr.Schema != nil && rr.Schema.Ref.String() == "" && !rr.TopLevel { + asch, err := Schema(SchemaOpts{Schema: rr.Schema, Root: sp, BasePath: bp}) + if assert.NoError(t, err, "for key: %s", k) { + if !asch.IsSimpleSchema { + assert.Fail(t, "not a top level schema", "for key: %s", k) + } + } + } + } + } + } +} + +func TestFlatten(t *testing.T) { + bp := filepath.Join(".", "fixtures", "flatten.yml") + sp, err := loadSpec(bp) + values := []struct { + Key string + Location string + Ref spec.Ref + Expected interface{} + }{ + { + "#/responses/notFound/schema", + "#/responses/notFound/schema", + spec.MustCreateRef("#/definitions/error"), + nil, + }, + { + "#/paths/~1some~1where~1{id}/parameters/0", + "#/paths/~1some~1where~1{id}/parameters/0/name", + spec.Ref{}, + "id", + }, + { + "#/paths/~1other~1place", + "#/paths/~1other~1place/get/operationId", + spec.Ref{}, + "modelOp", + }, + { + "#/paths/~1some~1where~1{id}/get/parameters/0", + "#/paths/~1some~1where~1{id}/get/parameters/0/name", + spec.Ref{}, + "limit", + }, + { + "#/paths/~1some~1where~1{id}/get/parameters/1", + "#/paths/~1some~1where~1{id}/get/parameters/1/name", + spec.Ref{}, + "some", + }, + { + "#/paths/~1some~1where~1{id}/get/parameters/2", + "#/paths/~1some~1where~1{id}/get/parameters/2/name", + spec.Ref{}, + "other", + }, + { + "#/paths/~1some~1where~1{id}/get/parameters/3", + "#/paths/~1some~1where~1{id}/get/parameters/3/schema", + spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBody"), + "", + }, + { + "#/paths/~1some~1where~1{id}/get/responses/200", + "#/paths/~1some~1where~1{id}/get/responses/200/schema", + spec.MustCreateRef("#/definitions/getSomeWhereIdOKBody"), + "", + }, + { + "#/definitions/namedAgain", + "", + spec.MustCreateRef("#/definitions/named"), + "", + }, + { + "#/definitions/namedThing/properties/name", + "", + spec.MustCreateRef("#/definitions/named"), + "", + }, + { + "#/definitions/namedThing/properties/namedAgain", + "", + spec.MustCreateRef("#/definitions/namedAgain"), + "", + }, + { + "#/definitions/datedRecords/items/1", + "", + spec.MustCreateRef("#/definitions/record"), + "", + }, + { + "#/definitions/otherRecords/items", + "", + spec.MustCreateRef("#/definitions/record"), + "", + }, + { + "#/definitions/tags/additionalProperties", + "", + spec.MustCreateRef("#/definitions/tag"), + "", + }, + { + "#/definitions/datedTag/allOf/1", + "", + spec.MustCreateRef("#/definitions/tag"), + "", + }, + { + "#/definitions/nestedThingRecordItems2/allOf/1", + "", + spec.MustCreateRef("#/definitions/nestedThingRecordItems2AllOf1"), + "", + }, + { + "#/definitions/nestedThingRecord/items/1", + "", + spec.MustCreateRef("#/definitions/nestedThingRecordItems1"), + "", + }, + { + "#/definitions/nestedThingRecord/items/2", + "", + spec.MustCreateRef("#/definitions/nestedThingRecordItems2"), + "", + }, + { + "#/definitions/nestedThing/properties/record", + "", + spec.MustCreateRef("#/definitions/nestedThingRecord"), + "", + }, + { + "#/definitions/named", + "#/definitions/named/type", + spec.Ref{}, + spec.StringOrArray{"string"}, + }, + { + "#/definitions/error", + "#/definitions/error/properties/id/type", + spec.Ref{}, + spec.StringOrArray{"integer"}, + }, + { + "#/definitions/record", + "#/definitions/record/properties/createdAt/format", + spec.Ref{}, + "date-time", + }, + { + "#/definitions/getSomeWhereIdOKBody", + "#/definitions/getSomeWhereIdOKBody/properties/record", + spec.MustCreateRef("#/definitions/nestedThing"), + nil, + }, + { + "#/definitions/getSomeWhereIdParamsBody", + "#/definitions/getSomeWhereIdParamsBody/properties/record", + spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecord"), + nil, + }, + { + "#/definitions/getSomeWhereIdParamsBodyRecord", + "#/definitions/getSomeWhereIdParamsBodyRecord/items/1", + spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems1"), + nil, + }, + { + "#/definitions/getSomeWhereIdParamsBodyRecord", + "#/definitions/getSomeWhereIdParamsBodyRecord/items/2", + spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems2"), + nil, + }, + { + "#/definitions/getSomeWhereIdParamsBodyRecordItems2", + "#/definitions/getSomeWhereIdParamsBodyRecordItems2/allOf/0/format", + spec.Ref{}, + "date", + }, + { + "#/definitions/getSomeWhereIdParamsBodyRecordItems2Name", + "#/definitions/getSomeWhereIdParamsBodyRecordItems2Name/properties/createdAt/format", + spec.Ref{}, + "date-time", + }, + { + "#/definitions/getSomeWhereIdParamsBodyRecordItems2", + "#/definitions/getSomeWhereIdParamsBodyRecordItems2/properties/name", + spec.MustCreateRef("#/definitions/getSomeWhereIdParamsBodyRecordItems2Name"), + "date", + }, + } + if assert.NoError(t, err) { + err := Flatten(FlattenOpts{Spec: New(sp), BasePath: bp}) + if assert.NoError(t, err) { + for i, v := range values { + pk := v.Key[1:] + if v.Location != "" { + pk = v.Location[1:] + } + ptr, err := jsonpointer.New(pk) + if assert.NoError(t, err, "at %d for %s", i, v.Key) { + d, _, err := ptr.Get(sp) + if assert.NoError(t, err) { + if v.Ref.String() != "" { + switch s := d.(type) { + case *spec.Schema: + assert.Equal(t, v.Ref.String(), s.Ref.String(), "at %d for %s", i, v.Key) + case spec.Schema: + assert.Equal(t, v.Ref.String(), s.Ref.String(), "at %d for %s", i, v.Key) + case *spec.SchemaOrArray: + var sRef spec.Ref + if s != nil && s.Schema != nil { + sRef = s.Schema.Ref + } + assert.Equal(t, v.Ref.String(), sRef.String(), "at %d for %s", i, v.Key) + case *spec.SchemaOrBool: + var sRef spec.Ref + if s != nil && s.Schema != nil { + sRef = s.Schema.Ref + } + assert.Equal(t, v.Ref.String(), sRef.String(), "at %d for %s", i, v.Key) + default: + assert.Fail(t, "unknown type", "got %T at %d for %s", d, i, v.Key) + } + } else { + assert.Equal(t, v.Expected, d) + } + } + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/analysis/mixin.go b/vendor/github.com/go-openapi/analysis/mixin.go new file mode 100644 index 0000000000..a547433ba8 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/mixin.go @@ -0,0 +1,199 @@ +package analysis + +import ( + "fmt" + + "github.com/go-openapi/spec" +) + +// Mixin modifies the primary swagger spec by adding the paths and +// definitions from the mixin specs. Top level parameters and +// responses from the mixins are also carried over. Operation id +// collisions are avoided by appending "Mixin" but only if +// needed. No other parts of primary are modified. Consider calling +// FixEmptyResponseDescriptions() on the modified primary if you read +// them from storage and they are valid to start with. +// +// Entries in "paths", "definitions", "parameters" and "responses" are +// added to the primary in the order of the given mixins. If the entry +// already exists in primary it is skipped with a warning message. +// +// The count of skipped entries (from collisions) is returned so any +// deviation from the number expected can flag warning in your build +// scripts. Carefully review the collisions before accepting them; +// consider renaming things if possible. +// +// No normalization of any keys takes place (paths, type defs, +// etc). Ensure they are canonical if your downstream tools do +// key normalization of any form. +func Mixin(primary *spec.Swagger, mixins ...*spec.Swagger) []string { + var skipped []string + opIds := getOpIds(primary) + if primary.Paths == nil { + primary.Paths = &spec.Paths{Paths: make(map[string]spec.PathItem)} + } + if primary.Paths.Paths == nil { + primary.Paths.Paths = make(map[string]spec.PathItem) + } + if primary.Definitions == nil { + primary.Definitions = make(spec.Definitions) + } + if primary.Parameters == nil { + primary.Parameters = make(map[string]spec.Parameter) + } + if primary.Responses == nil { + primary.Responses = make(map[string]spec.Response) + } + + for i, m := range mixins { + for k, v := range m.Definitions { + // assume name collisions represent IDENTICAL type. careful. + if _, exists := primary.Definitions[k]; exists { + warn := fmt.Sprintf("definitions entry '%v' already exists in primary or higher priority mixin, skipping\n", k) + skipped = append(skipped, warn) + continue + } + primary.Definitions[k] = v + } + if m.Paths != nil { + for k, v := range m.Paths.Paths { + if _, exists := primary.Paths.Paths[k]; exists { + warn := fmt.Sprintf("paths entry '%v' already exists in primary or higher priority mixin, skipping\n", k) + skipped = append(skipped, warn) + continue + } + + // Swagger requires that operationIds be + // unique within a spec. If we find a + // collision we append "Mixin0" to the + // operatoinId we are adding, where 0 is mixin + // index. We assume that operationIds with + // all the proivded specs are already unique. + piops := pathItemOps(v) + for _, piop := range piops { + if opIds[piop.ID] { + piop.ID = fmt.Sprintf("%v%v%v", piop.ID, "Mixin", i) + } + opIds[piop.ID] = true + } + primary.Paths.Paths[k] = v + } + } + for k, v := range m.Parameters { + // could try to rename on conflict but would + // have to fix $refs in the mixin. Complain + // for now + if _, exists := primary.Parameters[k]; exists { + warn := fmt.Sprintf("top level parameters entry '%v' already exists in primary or higher priority mixin, skipping\n", k) + skipped = append(skipped, warn) + continue + } + primary.Parameters[k] = v + } + for k, v := range m.Responses { + // could try to rename on conflict but would + // have to fix $refs in the mixin. Complain + // for now + if _, exists := primary.Responses[k]; exists { + warn := fmt.Sprintf("top level responses entry '%v' already exists in primary or higher priority mixin, skipping\n", k) + skipped = append(skipped, warn) + continue + } + primary.Responses[k] = v + } + } + return skipped +} + +// FixEmptyResponseDescriptions replaces empty ("") response +// descriptions in the input with "(empty)" to ensure that the +// resulting Swagger is stays valid. The problem appears to arise +// from reading in valid specs that have a explicit response +// description of "" (valid, response.description is required), but +// due to zero values being omitted upon re-serializing (omitempty) we +// lose them unless we stick some chars in there. +func FixEmptyResponseDescriptions(s *spec.Swagger) { + if s.Paths != nil { + for _, v := range s.Paths.Paths { + if v.Get != nil { + FixEmptyDescs(v.Get.Responses) + } + if v.Put != nil { + FixEmptyDescs(v.Put.Responses) + } + if v.Post != nil { + FixEmptyDescs(v.Post.Responses) + } + if v.Delete != nil { + FixEmptyDescs(v.Delete.Responses) + } + if v.Options != nil { + FixEmptyDescs(v.Options.Responses) + } + if v.Head != nil { + FixEmptyDescs(v.Head.Responses) + } + if v.Patch != nil { + FixEmptyDescs(v.Patch.Responses) + } + } + } + for k, v := range s.Responses { + FixEmptyDesc(&v) + s.Responses[k] = v + } +} + +// FixEmptyDescs adds "(empty)" as the description for any Response in +// the given Responses object that doesn't already have one. +func FixEmptyDescs(rs *spec.Responses) { + FixEmptyDesc(rs.Default) + for k, v := range rs.StatusCodeResponses { + FixEmptyDesc(&v) + rs.StatusCodeResponses[k] = v + } +} + +// FixEmptyDesc adds "(empty)" as the description to the given +// Response object if it doesn't already have one and isn't a +// ref. No-op on nil input. +func FixEmptyDesc(rs *spec.Response) { + if rs == nil || rs.Description != "" || rs.Ref.Ref.GetURL() != nil { + return + } + rs.Description = "(empty)" +} + +// getOpIds extracts all the paths..operationIds from the given +// spec and returns them as the keys in a map with 'true' values. +func getOpIds(s *spec.Swagger) map[string]bool { + rv := make(map[string]bool) + if s.Paths == nil { + return rv + } + for _, v := range s.Paths.Paths { + piops := pathItemOps(v) + for _, op := range piops { + rv[op.ID] = true + } + } + return rv +} + +func pathItemOps(p spec.PathItem) []*spec.Operation { + var rv []*spec.Operation + rv = appendOp(rv, p.Get) + rv = appendOp(rv, p.Put) + rv = appendOp(rv, p.Post) + rv = appendOp(rv, p.Delete) + rv = appendOp(rv, p.Head) + rv = appendOp(rv, p.Patch) + return rv +} + +func appendOp(ops []*spec.Operation, op *spec.Operation) []*spec.Operation { + if op == nil { + return ops + } + return append(ops, op) +} diff --git a/vendor/github.com/go-openapi/analysis/mixin_test.go b/vendor/github.com/go-openapi/analysis/mixin_test.go new file mode 100644 index 0000000000..1d8028217f --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/mixin_test.go @@ -0,0 +1,64 @@ +package analysis + +import "testing" + +const ( + widgetFile = "fixtures/widget-crud.yml" + fooFile = "fixtures/foo-crud.yml" + barFile = "fixtures/bar-crud.yml" + noPathsFile = "fixtures/no-paths.yml" + emptyPathsFile = "fixtures/empty-paths.json" +) + +func TestMixin(t *testing.T) { + + primary, err := loadSpec(widgetFile) + if err != nil { + t.Fatalf("Could not load '%v': %v\n", widgetFile, err) + } + mixin1, err := loadSpec(fooFile) + if err != nil { + t.Fatalf("Could not load '%v': %v\n", fooFile, err) + } + mixin2, err := loadSpec(barFile) + if err != nil { + t.Fatalf("Could not load '%v': %v\n", barFile, err) + } + mixin3, err := loadSpec(noPathsFile) + if err != nil { + t.Fatalf("Could not load '%v': %v\n", noPathsFile, err) + } + + collisions := Mixin(primary, mixin1, mixin2, mixin3) + if len(collisions) != 16 { + t.Errorf("TestMixin: Expected 16 collisions, got %v\n%v", len(collisions), collisions) + } + + if len(primary.Paths.Paths) != 7 { + t.Errorf("TestMixin: Expected 7 paths in merged, got %v\n", len(primary.Paths.Paths)) + } + + if len(primary.Definitions) != 8 { + t.Errorf("TestMixin: Expected 8 definitions in merged, got %v\n", len(primary.Definitions)) + } + + if len(primary.Parameters) != 4 { + t.Errorf("TestMixin: Expected 4 top level parameters in merged, got %v\n", len(primary.Parameters)) + } + + if len(primary.Responses) != 2 { + t.Errorf("TestMixin: Expected 2 top level responses in merged, got %v\n", len(primary.Responses)) + } + + // test that adding paths to a primary with no paths works (was NPE) + emptyPaths, err := loadSpec(emptyPathsFile) + if err != nil { + t.Fatalf("Could not load '%v': %v\n", emptyPathsFile, err) + } + + collisions = Mixin(emptyPaths, primary) + if len(collisions) != 0 { + t.Errorf("TestMixin: Expected 0 collisions, got %v\n%v", len(collisions), collisions) + } + +} diff --git a/vendor/github.com/go-openapi/analysis/schema.go b/vendor/github.com/go-openapi/analysis/schema.go new file mode 100644 index 0000000000..b616288bb6 --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/schema.go @@ -0,0 +1,233 @@ +package analysis + +import ( + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" +) + +// SchemaOpts configures the schema analyzer +type SchemaOpts struct { + Schema *spec.Schema + Root interface{} + BasePath string + _ struct{} +} + +// Schema analysis, will classify the schema according to known +// patterns. +func Schema(opts SchemaOpts) (*AnalyzedSchema, error) { + a := &AnalyzedSchema{ + schema: opts.Schema, + root: opts.Root, + basePath: opts.BasePath, + } + + a.initializeFlags() + a.inferKnownType() + a.inferEnum() + a.inferBaseType() + + if err := a.inferMap(); err != nil { + return nil, err + } + if err := a.inferArray(); err != nil { + return nil, err + } + + if err := a.inferTuple(); err != nil { + return nil, err + } + + if err := a.inferFromRef(); err != nil { + return nil, err + } + + a.inferSimpleSchema() + return a, nil +} + +// AnalyzedSchema indicates what the schema represents +type AnalyzedSchema struct { + schema *spec.Schema + root interface{} + basePath string + + hasProps bool + hasAllOf bool + hasItems bool + hasAdditionalProps bool + hasAdditionalItems bool + hasRef bool + + IsKnownType bool + IsSimpleSchema bool + IsArray bool + IsSimpleArray bool + IsMap bool + IsSimpleMap bool + IsExtendedObject bool + IsTuple bool + IsTupleWithExtra bool + IsBaseType bool + IsEnum bool +} + +// Inherits copies value fields from other onto this schema +func (a *AnalyzedSchema) inherits(other *AnalyzedSchema) { + if other == nil { + return + } + a.hasProps = other.hasProps + a.hasAllOf = other.hasAllOf + a.hasItems = other.hasItems + a.hasAdditionalItems = other.hasAdditionalItems + a.hasAdditionalProps = other.hasAdditionalProps + a.hasRef = other.hasRef + + a.IsKnownType = other.IsKnownType + a.IsSimpleSchema = other.IsSimpleSchema + a.IsArray = other.IsArray + a.IsSimpleArray = other.IsSimpleArray + a.IsMap = other.IsMap + a.IsSimpleMap = other.IsSimpleMap + a.IsExtendedObject = other.IsExtendedObject + a.IsTuple = other.IsTuple + a.IsTupleWithExtra = other.IsTupleWithExtra + a.IsBaseType = other.IsBaseType + a.IsEnum = other.IsEnum +} + +func (a *AnalyzedSchema) inferFromRef() error { + if a.hasRef { + opts := &spec.ExpandOptions{RelativeBase: a.basePath} + sch, err := spec.ResolveRefWithBase(a.root, &a.schema.Ref, opts) + if err != nil { + return err + } + if sch != nil { + rsch, err := Schema(SchemaOpts{ + Schema: sch, + Root: a.root, + BasePath: a.basePath, + }) + if err != nil { + return err + } + a.inherits(rsch) + } + } + return nil +} + +func (a *AnalyzedSchema) inferSimpleSchema() { + a.IsSimpleSchema = a.IsKnownType || a.IsSimpleArray || a.IsSimpleMap +} + +func (a *AnalyzedSchema) inferKnownType() { + tpe := a.schema.Type + format := a.schema.Format + a.IsKnownType = tpe.Contains("boolean") || + tpe.Contains("integer") || + tpe.Contains("number") || + tpe.Contains("string") || + (format != "" && strfmt.Default.ContainsName(format)) || + (a.isObjectType() && !a.hasProps && !a.hasAllOf && !a.hasAdditionalProps && !a.hasAdditionalItems) +} + +func (a *AnalyzedSchema) inferMap() error { + if a.isObjectType() { + hasExtra := a.hasProps || a.hasAllOf + a.IsMap = a.hasAdditionalProps && !hasExtra + a.IsExtendedObject = a.hasAdditionalProps && hasExtra + if a.IsMap { + if a.schema.AdditionalProperties.Schema != nil { + msch, err := Schema(SchemaOpts{ + Schema: a.schema.AdditionalProperties.Schema, + Root: a.root, + BasePath: a.basePath, + }) + if err != nil { + return err + } + a.IsSimpleMap = msch.IsSimpleSchema + } else if a.schema.AdditionalProperties.Allows { + a.IsSimpleMap = true + } + } + } + return nil +} + +func (a *AnalyzedSchema) inferArray() error { + fromValid := a.isArrayType() && (a.schema.Items == nil || a.schema.Items.Len() < 2) + a.IsArray = fromValid || (a.hasItems && a.schema.Items.Len() < 2) + if a.IsArray && a.hasItems { + if a.schema.Items.Schema != nil { + itsch, err := Schema(SchemaOpts{ + Schema: a.schema.Items.Schema, + Root: a.root, + BasePath: a.basePath, + }) + if err != nil { + return err + } + a.IsSimpleArray = itsch.IsSimpleSchema + } + if len(a.schema.Items.Schemas) > 0 { + itsch, err := Schema(SchemaOpts{ + Schema: &a.schema.Items.Schemas[0], + Root: a.root, + BasePath: a.basePath, + }) + if err != nil { + return err + } + a.IsSimpleArray = itsch.IsSimpleSchema + } + } + if a.IsArray && !a.hasItems { + a.IsSimpleArray = true + } + return nil +} + +func (a *AnalyzedSchema) inferTuple() error { + tuple := a.hasItems && a.schema.Items.Len() > 1 + a.IsTuple = tuple && !a.hasAdditionalItems + a.IsTupleWithExtra = tuple && a.hasAdditionalItems + return nil +} + +func (a *AnalyzedSchema) inferBaseType() { + if a.isObjectType() { + a.IsBaseType = a.schema.Discriminator != "" + } +} + +func (a *AnalyzedSchema) inferEnum() { + a.IsEnum = len(a.schema.Enum) > 0 +} + +func (a *AnalyzedSchema) initializeFlags() { + a.hasProps = len(a.schema.Properties) > 0 + a.hasAllOf = len(a.schema.AllOf) > 0 + a.hasRef = a.schema.Ref.String() != "" + + a.hasItems = a.schema.Items != nil && + (a.schema.Items.Schema != nil || len(a.schema.Items.Schemas) > 0) + + a.hasAdditionalProps = a.schema.AdditionalProperties != nil && + (a.schema.AdditionalProperties != nil || a.schema.AdditionalProperties.Allows) + + a.hasAdditionalItems = a.schema.AdditionalItems != nil && + (a.schema.AdditionalItems.Schema != nil || a.schema.AdditionalItems.Allows) + +} + +func (a *AnalyzedSchema) isObjectType() bool { + return !a.hasRef && (a.schema.Type == nil || a.schema.Type.Contains("") || a.schema.Type.Contains("object")) +} + +func (a *AnalyzedSchema) isArrayType() bool { + return !a.hasRef && (a.schema.Type != nil && a.schema.Type.Contains("array")) +} diff --git a/vendor/github.com/go-openapi/analysis/schema_test.go b/vendor/github.com/go-openapi/analysis/schema_test.go new file mode 100644 index 0000000000..0c386b2a4a --- /dev/null +++ b/vendor/github.com/go-openapi/analysis/schema_test.go @@ -0,0 +1,266 @@ +package analysis + +import ( + "encoding/json" + "fmt" + "path" + "testing" + + "net/http" + "net/http/httptest" + + "github.com/go-openapi/spec" + "github.com/stretchr/testify/assert" +) + +var knownSchemas = []*spec.Schema{ + spec.BoolProperty(), // 0 + spec.StringProperty(), // 1 + spec.Int8Property(), // 2 + spec.Int16Property(), // 3 + spec.Int32Property(), // 4 + spec.Int64Property(), // 5 + spec.Float32Property(), // 6 + spec.Float64Property(), // 7 + spec.DateProperty(), // 8 + spec.DateTimeProperty(), // 9 + (&spec.Schema{}), // 10 + (&spec.Schema{}).Typed("object", ""), // 11 + (&spec.Schema{}).Typed("", ""), // 12 + (&spec.Schema{}).Typed("", "uuid"), // 13 +} + +func newCObj() *spec.Schema { + return (&spec.Schema{}).Typed("object", "").SetProperty("id", *spec.Int64Property()) +} + +var complexObject = newCObj() + +var complexSchemas = []*spec.Schema{ + complexObject, + spec.ArrayProperty(complexObject), + spec.MapProperty(complexObject), +} + +func knownRefs(base string) []spec.Ref { + urls := []string{"bool", "string", "integer", "float", "date", "object", "format"} + + var result []spec.Ref + for _, u := range urls { + result = append(result, spec.MustCreateRef(fmt.Sprintf("%s/%s", base, path.Join("known", u)))) + } + return result +} + +func complexRefs(base string) []spec.Ref { + urls := []string{"object", "array", "map"} + + var result []spec.Ref + for _, u := range urls { + result = append(result, spec.MustCreateRef(fmt.Sprintf("%s/%s", base, path.Join("complex", u)))) + } + return result +} + +func refServer() *httptest.Server { + mux := http.NewServeMux() + mux.Handle("/known/bool", schemaHandler(knownSchemas[0])) + mux.Handle("/known/string", schemaHandler(knownSchemas[1])) + mux.Handle("/known/integer", schemaHandler(knownSchemas[5])) + mux.Handle("/known/float", schemaHandler(knownSchemas[6])) + mux.Handle("/known/date", schemaHandler(knownSchemas[8])) + mux.Handle("/known/object", schemaHandler(knownSchemas[11])) + mux.Handle("/known/format", schemaHandler(knownSchemas[13])) + + mux.Handle("/complex/object", schemaHandler(complexSchemas[0])) + mux.Handle("/complex/array", schemaHandler(complexSchemas[1])) + mux.Handle("/complex/map", schemaHandler(complexSchemas[2])) + + return httptest.NewServer(mux) +} + +func refSchema(ref spec.Ref) *spec.Schema { + return &spec.Schema{SchemaProps: spec.SchemaProps{Ref: ref}} +} + +func schemaHandler(schema *spec.Schema) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + writeJSON(w, schema) + }) +} + +func writeJSON(w http.ResponseWriter, data interface{}) { + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + enc := json.NewEncoder(w) + if err := enc.Encode(data); err != nil { + panic(err) + } +} + +func TestSchemaAnalysis_KnownTypes(t *testing.T) { + for i, v := range knownSchemas { + sch, err := Schema(SchemaOpts{Schema: v}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.True(t, sch.IsKnownType, "item at %d should be a known type", i) + } + } + for i, v := range complexSchemas { + sch, err := Schema(SchemaOpts{Schema: v}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.False(t, sch.IsKnownType, "item at %d should not be a known type", i) + } + } + + serv := refServer() + defer serv.Close() + + for i, ref := range knownRefs(serv.URL) { + sch, err := Schema(SchemaOpts{Schema: refSchema(ref)}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.True(t, sch.IsKnownType, "item at %d should be a known type", i) + } + } + for i, ref := range complexRefs(serv.URL) { + sch, err := Schema(SchemaOpts{Schema: refSchema(ref)}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.False(t, sch.IsKnownType, "item at %d should not be a known type", i) + } + } +} + +func TestSchemaAnalysis_Array(t *testing.T) { + for i, v := range append(knownSchemas, (&spec.Schema{}).Typed("array", "")) { + sch, err := Schema(SchemaOpts{Schema: spec.ArrayProperty(v)}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.True(t, sch.IsArray, "item at %d should be an array type", i) + assert.True(t, sch.IsSimpleArray, "item at %d should be a simple array type", i) + } + } + + for i, v := range complexSchemas { + sch, err := Schema(SchemaOpts{Schema: spec.ArrayProperty(v)}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.True(t, sch.IsArray, "item at %d should be an array type", i) + assert.False(t, sch.IsSimpleArray, "item at %d should not be a simple array type", i) + } + } + + serv := refServer() + defer serv.Close() + + for i, ref := range knownRefs(serv.URL) { + sch, err := Schema(SchemaOpts{Schema: spec.ArrayProperty(refSchema(ref))}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.True(t, sch.IsArray, "item at %d should be an array type", i) + assert.True(t, sch.IsSimpleArray, "item at %d should be a simple array type", i) + } + } + for i, ref := range complexRefs(serv.URL) { + sch, err := Schema(SchemaOpts{Schema: spec.ArrayProperty(refSchema(ref))}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.False(t, sch.IsKnownType, "item at %d should not be a known type", i) + assert.True(t, sch.IsArray, "item at %d should be an array type", i) + assert.False(t, sch.IsSimpleArray, "item at %d should not be a simple array type", i) + } + } + +} + +func TestSchemaAnalysis_Map(t *testing.T) { + for i, v := range append(knownSchemas, spec.MapProperty(nil)) { + sch, err := Schema(SchemaOpts{Schema: spec.MapProperty(v)}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.True(t, sch.IsMap, "item at %d should be a map type", i) + assert.True(t, sch.IsSimpleMap, "item at %d should be a simple map type", i) + } + } + + for i, v := range complexSchemas { + sch, err := Schema(SchemaOpts{Schema: spec.MapProperty(v)}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.True(t, sch.IsMap, "item at %d should be a map type", i) + assert.False(t, sch.IsSimpleMap, "item at %d should not be a simple map type", i) + } + } +} + +func TestSchemaAnalysis_ExtendedObject(t *testing.T) { + for i, v := range knownSchemas { + wex := spec.MapProperty(v).SetProperty("name", *spec.StringProperty()) + sch, err := Schema(SchemaOpts{Schema: wex}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.True(t, sch.IsExtendedObject, "item at %d should be an extended map object type", i) + assert.False(t, sch.IsMap, "item at %d should not be a map type", i) + assert.False(t, sch.IsSimpleMap, "item at %d should not be a simple map type", i) + } + } +} + +func TestSchemaAnalysis_Tuple(t *testing.T) { + at := spec.ArrayProperty(nil) + at.Items = &spec.SchemaOrArray{} + at.Items.Schemas = append(at.Items.Schemas, *spec.StringProperty(), *spec.Int64Property()) + + sch, err := Schema(SchemaOpts{Schema: at}) + if assert.NoError(t, err) { + assert.True(t, sch.IsTuple) + assert.False(t, sch.IsTupleWithExtra) + assert.False(t, sch.IsKnownType) + assert.False(t, sch.IsSimpleSchema) + } +} + +func TestSchemaAnalysis_TupleWithExtra(t *testing.T) { + at := spec.ArrayProperty(nil) + at.Items = &spec.SchemaOrArray{} + at.Items.Schemas = append(at.Items.Schemas, *spec.StringProperty(), *spec.Int64Property()) + at.AdditionalItems = &spec.SchemaOrBool{Allows: true} + at.AdditionalItems.Schema = spec.Int32Property() + + sch, err := Schema(SchemaOpts{Schema: at}) + if assert.NoError(t, err) { + assert.False(t, sch.IsTuple) + assert.True(t, sch.IsTupleWithExtra) + assert.False(t, sch.IsKnownType) + assert.False(t, sch.IsSimpleSchema) + } +} + +func TestSchemaAnalysis_BaseType(t *testing.T) { + cl := (&spec.Schema{}).Typed("object", "").SetProperty("type", *spec.StringProperty()).WithDiscriminator("type") + + sch, err := Schema(SchemaOpts{Schema: cl}) + if assert.NoError(t, err) { + assert.True(t, sch.IsBaseType) + assert.False(t, sch.IsKnownType) + assert.False(t, sch.IsSimpleSchema) + } +} + +func TestSchemaAnalysis_SimpleSchema(t *testing.T) { + for i, v := range append(knownSchemas, spec.ArrayProperty(nil), spec.MapProperty(nil)) { + sch, err := Schema(SchemaOpts{Schema: v}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.True(t, sch.IsSimpleSchema, "item at %d should be a simple schema", i) + } + + asch, err := Schema(SchemaOpts{Schema: spec.ArrayProperty(v)}) + if assert.NoError(t, err, "failed to analyze array schema at %d: %v", i, err) { + assert.True(t, asch.IsSimpleSchema, "array item at %d should be a simple schema", i) + } + + msch, err := Schema(SchemaOpts{Schema: spec.MapProperty(v)}) + if assert.NoError(t, err, "failed to analyze map schema at %d: %v", i, err) { + assert.True(t, msch.IsSimpleSchema, "map item at %d should be a simple schema", i) + } + } + + for i, v := range complexSchemas { + sch, err := Schema(SchemaOpts{Schema: v}) + if assert.NoError(t, err, "failed to analyze schema at %d: %v", i, err) { + assert.False(t, sch.IsSimpleSchema, "item at %d should not be a simple schema", i) + } + } + +} diff --git a/vendor/github.com/go-openapi/errors/.github/CONTRIBUTING.md b/vendor/github.com/go-openapi/errors/.github/CONTRIBUTING.md new file mode 100644 index 0000000000..7dea4240d7 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/.github/CONTRIBUTING.md @@ -0,0 +1,117 @@ +## Contribution Guidelines + +### Pull requests are always welcome + +We are always thrilled to receive pull requests, and do our best to +process them as fast as possible. Not sure if that typo is worth a pull +request? Do it! We will appreciate it. + +If your pull request is not accepted on the first try, don't be +discouraged! If there's a problem with the implementation, hopefully you +received feedback on what to improve. + +We're trying very hard to keep go-swagger lean and focused. We don't want it +to do everything for everybody. This means that we might decide against +incorporating a new feature. However, there might be a way to implement +that feature *on top of* go-swagger. + + +### Conventions + +Fork the repo and make changes on your fork in a feature branch: + +- If it's a bugfix branch, name it XXX-something where XXX is the number of the + issue +- If it's a feature branch, create an enhancement issue to announce your + intentions, and name it XXX-something where XXX is the number of the issue. + +Submit unit tests for your changes. Go has a great test framework built in; use +it! Take a look at existing tests for inspiration. Run the full test suite on +your branch before submitting a pull request. + +Update the documentation when creating or modifying features. Test +your documentation changes for clarity, concision, and correctness, as +well as a clean documentation build. See ``docs/README.md`` for more +information on building the docs and how docs get released. + +Write clean code. Universally formatted code promotes ease of writing, reading, +and maintenance. Always run `gofmt -s -w file.go` on each changed file before +committing your changes. Most editors have plugins that do this automatically. + +Pull requests descriptions should be as clear as possible and include a +reference to all the issues that they address. + +Pull requests must not contain commits from other users or branches. + +Commit messages must start with a capitalized and short summary (max. 50 +chars) written in the imperative, followed by an optional, more detailed +explanatory text which is separated from the summary by an empty line. + +Code review comments may be added to your pull request. Discuss, then make the +suggested modifications and push additional commits to your feature branch. Be +sure to post a comment after pushing. The new commits will show up in the pull +request automatically, but the reviewers will not be notified unless you +comment. + +Before the pull request is merged, make sure that you squash your commits into +logical units of work using `git rebase -i` and `git push -f`. After every +commit the test suite should be passing. Include documentation changes in the +same commit so that a revert would remove all traces of the feature or fix. + +Commits that fix or close an issue should include a reference like `Closes #XXX` +or `Fixes #XXX`, which will automatically close the issue when merged. + +### Sign your work + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right to +pass it on as an open-source patch. The rules are pretty simple: if you +can certify the below (from +[developercertificate.org](http://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +You can add the sign off when creating the git commit via `git commit -s`. diff --git a/vendor/github.com/go-openapi/errors/.gitignore b/vendor/github.com/go-openapi/errors/.gitignore new file mode 100644 index 0000000000..dd91ed6a04 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/.gitignore @@ -0,0 +1,2 @@ +secrets.yml +coverage.out diff --git a/vendor/github.com/go-openapi/errors/.travis.yml b/vendor/github.com/go-openapi/errors/.travis.yml new file mode 100644 index 0000000000..8d22a34a9f --- /dev/null +++ b/vendor/github.com/go-openapi/errors/.travis.yml @@ -0,0 +1,12 @@ +language: go +go: +- 1.7 +install: +- go get -u github.com/stretchr/testify/assert +script: +- go test -v -race -cover -coverprofile=coverage.txt -covermode=atomic ./... +after_success: +- bash <(curl -s https://codecov.io/bash) +notifications: + slack: + secure: gZGp9NaHxi7zawlXJXKY92BGeDR1x0tbIcTyU5nMKLq0fhIaiEBJEeALwZ4VgqsSv3DytSSF5mLH8fevAM3ixE6hxjKQ+lQuf7V/w3btCN1CSWgoua5LOh1kTnqZQtJuRvO4pzoJcT3bJWBsVZ07VGNVzzJEy/zAKCHFqBUCXShw7QemlLBcYWFNqveTlvDIfCzvouoLnPoXwxEpkjxe9uz/ZKZgAnup/fXjC8RFctmgCnkCyvJTk0Y/fZCsufixJrJhshBWTnlrFCzRmgNkz2d+i1Ls3+MJ5EJJ2Tx/A5S63dL49J1f9Kr0AKHADmulSy8JNzIckKwbyFMYUecrsW+Lsu9DhnVMy1jj5pKsJDLRi2iIU3fXTMWbcyQbXjbbnBO2mPdP3Tzme75y4D9fc8hUPeyqVv2BU26NEbQ7EF2pKJ93OXvci7HlwRBgdJa8j6mP2LEDClcPQW00g7N/OZe0cTOMa8L5AwiBlbArwqt9wv6YLJoTG0wpDhzWsFvbCg5bJxe28Yn3fIDD0Lk1I7iSnBbp/5gzF19jmxqvcT8tHRkDL4xfjbENFTZjA5uB4Z4pj4WSyWQILLV/Jwhe3fi9uQwdviFHfj5pnVrmNUiGSOQL672K5wl2c3E9mGwejvsu2dfEz28n7Y/FUnOpY3/cBS0n27JJaerS0zMKNLE= diff --git a/vendor/github.com/go-openapi/errors/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/errors/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..9322b065e3 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at ivan+abuse@flanders.co.nz. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/errors/LICENSE b/vendor/github.com/go-openapi/errors/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/go-openapi/errors/README.md b/vendor/github.com/go-openapi/errors/README.md new file mode 100644 index 0000000000..48c49fb2dd --- /dev/null +++ b/vendor/github.com/go-openapi/errors/README.md @@ -0,0 +1,5 @@ +# OpenAPI errors [![Build Status](https://travis-ci.org/go-openapi/errors.svg?branch=master)](https://travis-ci.org/go-openapi/errors) [![codecov](https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/errors) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) + +[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/errors/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/errors?status.svg)](http://godoc.org/github.com/go-openapi/errors) + +Shared errors used throughout the various libraries for the go-openapi toolkit \ No newline at end of file diff --git a/vendor/github.com/go-openapi/errors/api.go b/vendor/github.com/go-openapi/errors/api.go new file mode 100644 index 0000000000..64e0e73003 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/api.go @@ -0,0 +1,150 @@ +// 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 errors + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" +) + +// Error represents a error interface all swagger framework errors implement +type Error interface { + error + Code() int32 +} + +type apiError struct { + code int32 + message string +} + +func (a *apiError) Error() string { + return a.message +} + +func (a *apiError) Code() int32 { + return a.code +} + +// New creates a new API error with a code and a message +func New(code int32, message string, args ...interface{}) Error { + if len(args) > 0 { + return &apiError{code, fmt.Sprintf(message, args...)} + } + return &apiError{code, message} +} + +// NotFound creates a new not found error +func NotFound(message string, args ...interface{}) Error { + if message == "" { + message = "Not found" + } + return New(http.StatusNotFound, fmt.Sprintf(message, args...)) +} + +// NotImplemented creates a new not implemented error +func NotImplemented(message string) Error { + return New(http.StatusNotImplemented, message) +} + +// MethodNotAllowedError represents an error for when the path matches but the method doesn't +type MethodNotAllowedError struct { + code int32 + Allowed []string + message string +} + +func (m *MethodNotAllowedError) Error() string { + return m.message +} + +// Code the error code +func (m *MethodNotAllowedError) Code() int32 { + return m.code +} + +func errorAsJSON(err Error) []byte { + b, _ := json.Marshal(struct { + Code int32 `json:"code"` + Message string `json:"message"` + }{err.Code(), err.Error()}) + return b +} + +func flattenComposite(errs *CompositeError) *CompositeError { + var res []error + for _, er := range errs.Errors { + switch e := er.(type) { + case *CompositeError: + if len(e.Errors) > 0 { + flat := flattenComposite(e) + if len(flat.Errors) > 0 { + res = append(res, flat.Errors...) + } + } + default: + if e != nil { + res = append(res, e) + } + } + } + return CompositeValidationError(res...) +} + +// MethodNotAllowed creates a new method not allowed error +func MethodNotAllowed(requested string, allow []string) Error { + msg := fmt.Sprintf("method %s is not allowed, but [%s] are", requested, strings.Join(allow, ",")) + return &MethodNotAllowedError{code: http.StatusMethodNotAllowed, Allowed: allow, message: msg} +} + +// ServeError the error handler interface implemenation +func ServeError(rw http.ResponseWriter, r *http.Request, err error) { + rw.Header().Set("Content-Type", "application/json") + switch e := err.(type) { + case *CompositeError: + er := flattenComposite(e) + ServeError(rw, r, er.Errors[0]) + case *MethodNotAllowedError: + rw.Header().Add("Allow", strings.Join(err.(*MethodNotAllowedError).Allowed, ",")) + rw.WriteHeader(asHTTPCode(int(e.Code()))) + if r == nil || r.Method != "HEAD" { + rw.Write(errorAsJSON(e)) + } + case Error: + if e == nil { + rw.WriteHeader(http.StatusInternalServerError) + rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error"))) + return + } + rw.WriteHeader(asHTTPCode(int(e.Code()))) + if r == nil || r.Method != "HEAD" { + rw.Write(errorAsJSON(e)) + } + default: + rw.WriteHeader(http.StatusInternalServerError) + if r == nil || r.Method != "HEAD" { + rw.Write(errorAsJSON(New(http.StatusInternalServerError, err.Error()))) + } + } +} + +func asHTTPCode(input int) int { + if input >= 600 { + return 422 + } + return input +} diff --git a/vendor/github.com/go-openapi/errors/api_test.go b/vendor/github.com/go-openapi/errors/api_test.go new file mode 100644 index 0000000000..4c928172dd --- /dev/null +++ b/vendor/github.com/go-openapi/errors/api_test.go @@ -0,0 +1,97 @@ +// 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 errors + +import ( + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestServeError(t *testing.T) { + // method not allowed wins + var err error + err = MethodNotAllowed("GET", []string{"POST", "PUT"}) + recorder := httptest.NewRecorder() + ServeError(recorder, nil, err) + assert.Equal(t, http.StatusMethodNotAllowed, recorder.Code) + assert.Equal(t, "POST,PUT", recorder.Header().Get("Allow")) + // assert.Equal(t, "application/json", recorder.Header().Get("content-type")) + assert.Equal(t, `{"code":405,"message":"method GET is not allowed, but [POST,PUT] are"}`, recorder.Body.String()) + + // renders status code from error when present + err = NotFound("") + recorder = httptest.NewRecorder() + ServeError(recorder, nil, err) + assert.Equal(t, http.StatusNotFound, recorder.Code) + // assert.Equal(t, "application/json", recorder.Header().Get("content-type")) + assert.Equal(t, `{"code":404,"message":"Not found"}`, recorder.Body.String()) + + // renders mapped status code from error when present + err = InvalidTypeName("someType") + recorder = httptest.NewRecorder() + ServeError(recorder, nil, err) + assert.Equal(t, http.StatusUnprocessableEntity, recorder.Code) + // assert.Equal(t, "application/json", recorder.Header().Get("content-type")) + assert.Equal(t, `{"code":601,"message":"someType is an invalid type name"}`, recorder.Body.String()) + + // defaults to internal server error + err = fmt.Errorf("some error") + recorder = httptest.NewRecorder() + ServeError(recorder, nil, err) + assert.Equal(t, http.StatusInternalServerError, recorder.Code) + // assert.Equal(t, "application/json", recorder.Header().Get("content-type")) + assert.Equal(t, `{"code":500,"message":"some error"}`, recorder.Body.String()) +} + +func TestAPIErrors(t *testing.T) { + err := New(402, "this failed %s", "yada") + assert.Error(t, err) + assert.EqualValues(t, 402, err.Code()) + assert.EqualValues(t, "this failed yada", err.Error()) + + err = NotFound("this failed %d", 1) + assert.Error(t, err) + assert.EqualValues(t, http.StatusNotFound, err.Code()) + assert.EqualValues(t, "this failed 1", err.Error()) + + err = NotFound("") + assert.Error(t, err) + assert.EqualValues(t, http.StatusNotFound, err.Code()) + assert.EqualValues(t, "Not found", err.Error()) + + err = NotImplemented("not implemented") + assert.Error(t, err) + assert.EqualValues(t, http.StatusNotImplemented, err.Code()) + assert.EqualValues(t, "not implemented", err.Error()) + + err = MethodNotAllowed("GET", []string{"POST", "PUT"}) + assert.Error(t, err) + assert.EqualValues(t, http.StatusMethodNotAllowed, err.Code()) + assert.EqualValues(t, "method GET is not allowed, but [POST,PUT] are", err.Error()) + + err = InvalidContentType("application/saml", []string{"application/json", "application/x-yaml"}) + assert.Error(t, err) + assert.EqualValues(t, http.StatusUnsupportedMediaType, err.Code()) + assert.EqualValues(t, "unsupported media type \"application/saml\", only [application/json application/x-yaml] are allowed", err.Error()) + + err = InvalidResponseFormat("application/saml", []string{"application/json", "application/x-yaml"}) + assert.Error(t, err) + assert.EqualValues(t, http.StatusNotAcceptable, err.Code()) + assert.EqualValues(t, "unsupported media type requested, only [application/json application/x-yaml] are available", err.Error()) +} diff --git a/vendor/github.com/go-openapi/errors/auth.go b/vendor/github.com/go-openapi/errors/auth.go new file mode 100644 index 0000000000..70eb960b1a --- /dev/null +++ b/vendor/github.com/go-openapi/errors/auth.go @@ -0,0 +1,20 @@ +// 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 errors + +// Unauthenticated returns an unauthenticated error +func Unauthenticated(scheme string) Error { + return New(401, "unauthenticated for %s", scheme) +} diff --git a/vendor/github.com/go-openapi/errors/auth_test.go b/vendor/github.com/go-openapi/errors/auth_test.go new file mode 100644 index 0000000000..eee7a5c7e2 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/auth_test.go @@ -0,0 +1,27 @@ +// 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 errors + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUnauthenticated(t *testing.T) { + err := Unauthenticated("basic") + assert.EqualValues(t, 401, err.Code()) + assert.Equal(t, "unauthenticated for basic", err.Error()) +} diff --git a/vendor/github.com/go-openapi/errors/headers.go b/vendor/github.com/go-openapi/errors/headers.go new file mode 100644 index 0000000000..66a1f4bc8f --- /dev/null +++ b/vendor/github.com/go-openapi/errors/headers.go @@ -0,0 +1,85 @@ +// 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 errors + +import ( + "fmt" + "net/http" +) + +// Validation represents a failure of a precondition +type Validation struct { + code int32 + Name string + In string + Value interface{} + message string + Values []interface{} +} + +func (e *Validation) Error() string { + return e.message +} + +// Code the error code +func (e *Validation) Code() int32 { + return e.code +} + +const ( + contentTypeFail = `unsupported media type %q, only %v are allowed` + responseFormatFail = `unsupported media type requested, only %v are available` +) + +// InvalidContentType error for an invalid content type +func InvalidContentType(value string, allowed []string) *Validation { + var values []interface{} + for _, v := range allowed { + values = append(values, v) + } + return &Validation{ + code: http.StatusUnsupportedMediaType, + Name: "Content-Type", + In: "header", + Value: value, + Values: values, + message: fmt.Sprintf(contentTypeFail, value, allowed), + } +} + +// InvalidResponseFormat error for an unacceptable response format request +func InvalidResponseFormat(value string, allowed []string) *Validation { + var values []interface{} + for _, v := range allowed { + values = append(values, v) + } + return &Validation{ + code: http.StatusNotAcceptable, + Name: "Accept", + In: "header", + Value: value, + Values: values, + message: fmt.Sprintf(responseFormatFail, allowed), + } +} + +// Validate error message name for aliased property +func (e *Validation) ValidateName(name string) *Validation { + if e.Name == "" && name != "" { + e.Name = name + e.message = name+e.message + } + return e +} diff --git a/vendor/github.com/go-openapi/errors/middleware.go b/vendor/github.com/go-openapi/errors/middleware.go new file mode 100644 index 0000000000..6390d4636a --- /dev/null +++ b/vendor/github.com/go-openapi/errors/middleware.go @@ -0,0 +1,51 @@ +// 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 errors + +import ( + "bytes" + "fmt" + "strings" +) + +// APIVerificationFailed is an error that contains all the missing info for a mismatched section +// between the api registrations and the api spec +type APIVerificationFailed struct { + Section string + MissingSpecification []string + MissingRegistration []string +} + +// +func (v *APIVerificationFailed) Error() string { + buf := bytes.NewBuffer(nil) + + hasRegMissing := len(v.MissingRegistration) > 0 + hasSpecMissing := len(v.MissingSpecification) > 0 + + if hasRegMissing { + buf.WriteString(fmt.Sprintf("missing [%s] %s registrations", strings.Join(v.MissingRegistration, ", "), v.Section)) + } + + if hasRegMissing && hasSpecMissing { + buf.WriteString("\n") + } + + if hasSpecMissing { + buf.WriteString(fmt.Sprintf("missing from spec file [%s] %s", strings.Join(v.MissingSpecification, ", "), v.Section)) + } + + return buf.String() +} diff --git a/vendor/github.com/go-openapi/errors/middleware_test.go b/vendor/github.com/go-openapi/errors/middleware_test.go new file mode 100644 index 0000000000..feff2074d6 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/middleware_test.go @@ -0,0 +1,33 @@ +// 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 errors + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAPIVerificationFailed(t *testing.T) { + err := &APIVerificationFailed{ + Section: "consumer", + MissingSpecification: []string{"application/json", "application/x-yaml"}, + MissingRegistration: []string{"text/html", "application/xml"}, + } + + expected := `missing [text/html, application/xml] consumer registrations +missing from spec file [application/json, application/x-yaml] consumer` + assert.Equal(t, expected, err.Error()) +} diff --git a/vendor/github.com/go-openapi/errors/parsing.go b/vendor/github.com/go-openapi/errors/parsing.go new file mode 100644 index 0000000000..1bae87302a --- /dev/null +++ b/vendor/github.com/go-openapi/errors/parsing.go @@ -0,0 +1,59 @@ +// 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 errors + +import "fmt" + +// ParseError respresents a parsing error +type ParseError struct { + code int32 + Name string + In string + Value string + Reason error + message string +} + +func (e *ParseError) Error() string { + return e.message +} + +// Code returns the http status code for this error +func (e *ParseError) Code() int32 { + return e.code +} + +const ( + parseErrorTemplContent = `parsing %s %s from %q failed, because %s` + parseErrorTemplContentNoIn = `parsing %s from %q failed, because %s` +) + +// NewParseError creates a new parse error +func NewParseError(name, in, value string, reason error) *ParseError { + var msg string + if in == "" { + msg = fmt.Sprintf(parseErrorTemplContentNoIn, name, value, reason) + } else { + msg = fmt.Sprintf(parseErrorTemplContent, name, in, value, reason) + } + return &ParseError{ + code: 400, + Name: name, + In: in, + Value: value, + Reason: reason, + message: msg, + } +} diff --git a/vendor/github.com/go-openapi/errors/parsing_test.go b/vendor/github.com/go-openapi/errors/parsing_test.go new file mode 100644 index 0000000000..a51f773c97 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/parsing_test.go @@ -0,0 +1,32 @@ +// 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 errors + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParseError(t *testing.T) { + err := NewParseError("Content-Type", "header", "application(", errors.New("unable to parse")) + assert.EqualValues(t, 400, err.Code()) + assert.Equal(t, "parsing Content-Type header from \"application(\" failed, because unable to parse", err.Error()) + + err = NewParseError("Content-Type", "", "application(", errors.New("unable to parse")) + assert.EqualValues(t, 400, err.Code()) + assert.Equal(t, "parsing Content-Type from \"application(\" failed, because unable to parse", err.Error()) +} diff --git a/vendor/github.com/go-openapi/errors/schema.go b/vendor/github.com/go-openapi/errors/schema.go new file mode 100644 index 0000000000..c52f5c3143 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/schema.go @@ -0,0 +1,548 @@ +// 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 errors + +import ( + "fmt" + "strings" +) + +const ( + invalidType = "%s is an invalid type name" + typeFail = "%s in %s must be of type %s" + typeFailWithData = "%s in %s must be of type %s: %q" + typeFailWithError = "%s in %s must be of type %s, because: %s" + requiredFail = "%s in %s is required" + tooLongMessage = "%s in %s should be at most %d chars long" + tooShortMessage = "%s in %s should be at least %d chars long" + patternFail = "%s in %s should match '%s'" + enumFail = "%s in %s should be one of %v" + multipleOfFail = "%s in %s should be a multiple of %v" + maxIncFail = "%s in %s should be less than or equal to %v" + maxExcFail = "%s in %s should be less than %v" + minIncFail = "%s in %s should be greater than or equal to %v" + minExcFail = "%s in %s should be greater than %v" + uniqueFail = "%s in %s shouldn't contain duplicates" + maxItemsFail = "%s in %s should have at most %d items" + minItemsFail = "%s in %s should have at least %d items" + typeFailNoIn = "%s must be of type %s" + typeFailWithDataNoIn = "%s must be of type %s: %q" + typeFailWithErrorNoIn = "%s must be of type %s, because: %s" + requiredFailNoIn = "%s is required" + tooLongMessageNoIn = "%s should be at most %d chars long" + tooShortMessageNoIn = "%s should be at least %d chars long" + patternFailNoIn = "%s should match '%s'" + enumFailNoIn = "%s should be one of %v" + multipleOfFailNoIn = "%s should be a multiple of %v" + maxIncFailNoIn = "%s should be less than or equal to %v" + maxExcFailNoIn = "%s should be less than %v" + minIncFailNoIn = "%s should be greater than or equal to %v" + minExcFailNoIn = "%s should be greater than %v" + uniqueFailNoIn = "%s shouldn't contain duplicates" + maxItemsFailNoIn = "%s should have at most %d items" + minItemsFailNoIn = "%s should have at least %d items" + noAdditionalItems = "%s in %s can't have additional items" + noAdditionalItemsNoIn = "%s can't have additional items" + tooFewProperties = "%s in %s should have at least %d properties" + tooFewPropertiesNoIn = "%s should have at least %d properties" + tooManyProperties = "%s in %s should have at most %d properties" + tooManyPropertiesNoIn = "%s should have at most %d properties" + unallowedProperty = "%s.%s in %s is a forbidden property" + unallowedPropertyNoIn = "%s.%s is a forbidden property" + failedAllPatternProps = "%s.%s in %s failed all pattern properties" + failedAllPatternPropsNoIn = "%s.%s failed all pattern properties" +) + +// All code responses can be used to differentiate errors for different handling +// by the consuming program +const ( + // CompositeErrorCode remains 422 for backwards-compatibility + // and to separate it from validation errors with cause + CompositeErrorCode = 422 + // InvalidTypeCode is used for any subclass of invalid types + InvalidTypeCode = 600 + iota + RequiredFailCode + TooLongFailCode + TooShortFailCode + PatternFailCode + EnumFailCode + MultipleOfFailCode + MaxFailCode + MinFailCode + UniqueFailCode + MaxItemsFailCode + MinItemsFailCode + NoAdditionalItemsCode + TooFewPropertiesCode + TooManyPropertiesCode + UnallowedPropertyCode + FailedAllPatternPropsCode +) + +// CompositeError is an error that groups several errors together +type CompositeError struct { + Errors []error + code int32 + message string +} + +// Code for this error +func (c *CompositeError) Code() int32 { + return c.code +} + +func (c *CompositeError) Error() string { + if len(c.Errors) > 0 { + msgs := []string{c.message + ":"} + for _, e := range c.Errors { + msgs = append(msgs, e.Error()) + } + return strings.Join(msgs, "\n") + } + return c.message +} + +// CompositeValidationError an error to wrap a bunch of other errors +func CompositeValidationError(errors ...error) *CompositeError { + return &CompositeError{ + code: CompositeErrorCode, + Errors: append([]error{}, errors...), + message: "validation failure list", + } +} + +// FailedAllPatternProperties an error for when the property doesn't match a pattern +func FailedAllPatternProperties(name, in, key string) *Validation { + msg := fmt.Sprintf(failedAllPatternProps, name, key, in) + if in == "" { + msg = fmt.Sprintf(failedAllPatternPropsNoIn, name, key) + } + return &Validation{ + code: FailedAllPatternPropsCode, + Name: name, + In: in, + Value: key, + message: msg, + } +} + +// PropertyNotAllowed an error for when the property doesn't match a pattern +func PropertyNotAllowed(name, in, key string) *Validation { + msg := fmt.Sprintf(unallowedProperty, name, key, in) + if in == "" { + msg = fmt.Sprintf(unallowedPropertyNoIn, name, key) + } + return &Validation{ + code: UnallowedPropertyCode, + Name: name, + In: in, + Value: key, + message: msg, + } +} + +// TooFewProperties an error for an object with too few properties +func TooFewProperties(name, in string, n int64) *Validation { + msg := fmt.Sprintf(tooFewProperties, name, in, n) + if in == "" { + msg = fmt.Sprintf(tooFewPropertiesNoIn, name, n) + } + return &Validation{ + code: TooFewPropertiesCode, + Name: name, + In: in, + Value: n, + message: msg, + } +} + +// TooManyProperties an error for an object with too many properties +func TooManyProperties(name, in string, n int64) *Validation { + msg := fmt.Sprintf(tooManyProperties, name, in, n) + if in == "" { + msg = fmt.Sprintf(tooManyPropertiesNoIn, name, n) + } + return &Validation{ + code: TooManyPropertiesCode, + Name: name, + In: in, + Value: n, + message: msg, + } +} + +// AdditionalItemsNotAllowed an error for invalid additional items +func AdditionalItemsNotAllowed(name, in string) *Validation { + msg := fmt.Sprintf(noAdditionalItems, name, in) + if in == "" { + msg = fmt.Sprintf(noAdditionalItemsNoIn, name) + } + return &Validation{ + code: NoAdditionalItemsCode, + Name: name, + In: in, + message: msg, + } +} + +// InvalidCollectionFormat another flavor of invalid type error +func InvalidCollectionFormat(name, in, format string) *Validation { + return &Validation{ + code: InvalidTypeCode, + Name: name, + In: in, + Value: format, + message: fmt.Sprintf("the collection format %q is not supported for the %s param %q", format, in, name), + } +} + +// InvalidTypeName an error for when the type is invalid +func InvalidTypeName(typeName string) *Validation { + return &Validation{ + code: InvalidTypeCode, + Value: typeName, + message: fmt.Sprintf(invalidType, typeName), + } +} + +// InvalidType creates an error for when the type is invalid +func InvalidType(name, in, typeName string, value interface{}) *Validation { + var message string + + if in != "" { + switch value.(type) { + case string: + message = fmt.Sprintf(typeFailWithData, name, in, typeName, value) + case error: + message = fmt.Sprintf(typeFailWithError, name, in, typeName, value) + default: + message = fmt.Sprintf(typeFail, name, in, typeName) + } + } else { + switch value.(type) { + case string: + message = fmt.Sprintf(typeFailWithDataNoIn, name, typeName, value) + case error: + message = fmt.Sprintf(typeFailWithErrorNoIn, name, typeName, value) + default: + message = fmt.Sprintf(typeFailNoIn, name, typeName) + } + } + + return &Validation{ + code: InvalidTypeCode, + Name: name, + In: in, + Value: value, + message: message, + } + +} + +// DuplicateItems error for when an array contains duplicates +func DuplicateItems(name, in string) *Validation { + msg := fmt.Sprintf(uniqueFail, name, in) + if in == "" { + msg = fmt.Sprintf(uniqueFailNoIn, name) + } + return &Validation{ + code: UniqueFailCode, + Name: name, + In: in, + message: msg, + } +} + +// TooManyItems error for when an array contains too many items +func TooManyItems(name, in string, max int64) *Validation { + msg := fmt.Sprintf(maxItemsFail, name, in, max) + if in == "" { + msg = fmt.Sprintf(maxItemsFailNoIn, name, max) + } + + return &Validation{ + code: MaxItemsFailCode, + Name: name, + In: in, + message: msg, + } +} + +// TooFewItems error for when an array contains too few items +func TooFewItems(name, in string, min int64) *Validation { + msg := fmt.Sprintf(minItemsFail, name, in, min) + if in == "" { + msg = fmt.Sprintf(minItemsFailNoIn, name, min) + } + return &Validation{ + code: MinItemsFailCode, + Name: name, + In: in, + message: msg, + } +} + +// ExceedsMaximumInt error for when maxinum validation fails +func ExceedsMaximumInt(name, in string, max int64, exclusive bool) *Validation { + var message string + if in == "" { + m := maxIncFailNoIn + if exclusive { + m = maxExcFailNoIn + } + message = fmt.Sprintf(m, name, max) + } else { + m := maxIncFail + if exclusive { + m = maxExcFail + } + message = fmt.Sprintf(m, name, in, max) + } + return &Validation{ + code: MaxFailCode, + Name: name, + In: in, + Value: max, + message: message, + } +} + +// ExceedsMaximumUint error for when maxinum validation fails +func ExceedsMaximumUint(name, in string, max uint64, exclusive bool) *Validation { + var message string + if in == "" { + m := maxIncFailNoIn + if exclusive { + m = maxExcFailNoIn + } + message = fmt.Sprintf(m, name, max) + } else { + m := maxIncFail + if exclusive { + m = maxExcFail + } + message = fmt.Sprintf(m, name, in, max) + } + return &Validation{ + code: MaxFailCode, + Name: name, + In: in, + Value: max, + message: message, + } +} + +// ExceedsMaximum error for when maxinum validation fails +func ExceedsMaximum(name, in string, max float64, exclusive bool) *Validation { + var message string + if in == "" { + m := maxIncFailNoIn + if exclusive { + m = maxExcFailNoIn + } + message = fmt.Sprintf(m, name, max) + } else { + m := maxIncFail + if exclusive { + m = maxExcFail + } + message = fmt.Sprintf(m, name, in, max) + } + return &Validation{ + code: MaxFailCode, + Name: name, + In: in, + Value: max, + message: message, + } +} + +// ExceedsMinimumInt error for when maxinum validation fails +func ExceedsMinimumInt(name, in string, min int64, exclusive bool) *Validation { + var message string + if in == "" { + m := minIncFailNoIn + if exclusive { + m = minExcFailNoIn + } + message = fmt.Sprintf(m, name, min) + } else { + m := minIncFail + if exclusive { + m = minExcFail + } + message = fmt.Sprintf(m, name, in, min) + } + return &Validation{ + code: MinFailCode, + Name: name, + In: in, + Value: min, + message: message, + } +} + +// ExceedsMinimumUint error for when maxinum validation fails +func ExceedsMinimumUint(name, in string, min uint64, exclusive bool) *Validation { + var message string + if in == "" { + m := minIncFailNoIn + if exclusive { + m = minExcFailNoIn + } + message = fmt.Sprintf(m, name, min) + } else { + m := minIncFail + if exclusive { + m = minExcFail + } + message = fmt.Sprintf(m, name, in, min) + } + return &Validation{ + code: MinFailCode, + Name: name, + In: in, + Value: min, + message: message, + } +} + +// ExceedsMinimum error for when maxinum validation fails +func ExceedsMinimum(name, in string, min float64, exclusive bool) *Validation { + var message string + if in == "" { + m := minIncFailNoIn + if exclusive { + m = minExcFailNoIn + } + message = fmt.Sprintf(m, name, min) + } else { + m := minIncFail + if exclusive { + m = minExcFail + } + message = fmt.Sprintf(m, name, in, min) + } + return &Validation{ + code: MinFailCode, + Name: name, + In: in, + Value: min, + message: message, + } +} + +// NotMultipleOf error for when multiple of validation fails +func NotMultipleOf(name, in string, multiple float64) *Validation { + var msg string + if in == "" { + msg = fmt.Sprintf(multipleOfFailNoIn, name, multiple) + } else { + msg = fmt.Sprintf(multipleOfFail, name, in, multiple) + } + return &Validation{ + code: MultipleOfFailCode, + Name: name, + In: in, + Value: multiple, + message: msg, + } +} + +// EnumFail error for when an enum validation fails +func EnumFail(name, in string, value interface{}, values []interface{}) *Validation { + var msg string + if in == "" { + msg = fmt.Sprintf(enumFailNoIn, name, values) + } else { + msg = fmt.Sprintf(enumFail, name, in, values) + } + + return &Validation{ + code: EnumFailCode, + Name: name, + In: in, + Value: value, + Values: values, + message: msg, + } +} + +// Required error for when a value is missing +func Required(name, in string) *Validation { + var msg string + if in == "" { + msg = fmt.Sprintf(requiredFailNoIn, name) + } else { + msg = fmt.Sprintf(requiredFail, name, in) + } + return &Validation{ + code: RequiredFailCode, + Name: name, + In: in, + message: msg, + } +} + +// TooLong error for when a string is too long +func TooLong(name, in string, max int64) *Validation { + var msg string + if in == "" { + msg = fmt.Sprintf(tooLongMessageNoIn, name, max) + } else { + msg = fmt.Sprintf(tooLongMessage, name, in, max) + } + return &Validation{ + code: TooLongFailCode, + Name: name, + In: in, + message: msg, + } +} + +// TooShort error for when a string is too short +func TooShort(name, in string, min int64) *Validation { + var msg string + if in == "" { + msg = fmt.Sprintf(tooShortMessageNoIn, name, min) + } else { + msg = fmt.Sprintf(tooShortMessage, name, in, min) + } + + return &Validation{ + code: TooShortFailCode, + Name: name, + In: in, + message: msg, + } +} + +// FailedPattern error for when a string fails a regex pattern match +// the pattern that is returned is the ECMA syntax version of the pattern not the golang version. +func FailedPattern(name, in, pattern string) *Validation { + var msg string + if in == "" { + msg = fmt.Sprintf(patternFailNoIn, name, pattern) + } else { + msg = fmt.Sprintf(patternFail, name, in, pattern) + } + + return &Validation{ + code: PatternFailCode, + Name: name, + In: in, + message: msg, + } +} diff --git a/vendor/github.com/go-openapi/errors/schema_test.go b/vendor/github.com/go-openapi/errors/schema_test.go new file mode 100644 index 0000000000..3a64872370 --- /dev/null +++ b/vendor/github.com/go-openapi/errors/schema_test.go @@ -0,0 +1,284 @@ +// 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 errors + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSchemaErrors(t *testing.T) { + err := InvalidType("confirmed", "query", "boolean", nil) + assert.Error(t, err) + assert.EqualValues(t, InvalidTypeCode, err.Code()) + assert.Equal(t, "confirmed in query must be of type boolean", err.Error()) + + err = InvalidType("confirmed", "", "boolean", nil) + assert.Error(t, err) + assert.EqualValues(t, InvalidTypeCode, err.Code()) + assert.Equal(t, "confirmed must be of type boolean", err.Error()) + + err = InvalidType("confirmed", "query", "boolean", "hello") + assert.Error(t, err) + assert.EqualValues(t, InvalidTypeCode, err.Code()) + assert.Equal(t, "confirmed in query must be of type boolean: \"hello\"", err.Error()) + + err = InvalidType("confirmed", "query", "boolean", errors.New("hello")) + assert.Error(t, err) + assert.EqualValues(t, InvalidTypeCode, err.Code()) + assert.Equal(t, "confirmed in query must be of type boolean, because: hello", err.Error()) + + err = InvalidType("confirmed", "", "boolean", "hello") + assert.Error(t, err) + assert.EqualValues(t, InvalidTypeCode, err.Code()) + assert.Equal(t, "confirmed must be of type boolean: \"hello\"", err.Error()) + + err = InvalidType("confirmed", "", "boolean", errors.New("hello")) + assert.Error(t, err) + assert.EqualValues(t, InvalidTypeCode, err.Code()) + assert.Equal(t, "confirmed must be of type boolean, because: hello", err.Error()) + + err = DuplicateItems("uniques", "query") + assert.Error(t, err) + assert.EqualValues(t, UniqueFailCode, err.Code()) + assert.Equal(t, "uniques in query shouldn't contain duplicates", err.Error()) + + err = DuplicateItems("uniques", "") + assert.Error(t, err) + assert.EqualValues(t, UniqueFailCode, err.Code()) + assert.Equal(t, "uniques shouldn't contain duplicates", err.Error()) + + err = TooManyItems("something", "query", 5) + assert.Error(t, err) + assert.EqualValues(t, MaxItemsFailCode, err.Code()) + assert.Equal(t, "something in query should have at most 5 items", err.Error()) + + err = TooManyItems("something", "", 5) + assert.Error(t, err) + assert.EqualValues(t, MaxItemsFailCode, err.Code()) + assert.Equal(t, "something should have at most 5 items", err.Error()) + + err = TooFewItems("something", "", 5) + assert.Error(t, err) + assert.EqualValues(t, MinItemsFailCode, err.Code()) + assert.Equal(t, "something should have at least 5 items", err.Error()) + + err = ExceedsMaximumInt("something", "query", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something in query should be less than or equal to 5", err.Error()) + + err = ExceedsMaximumInt("something", "", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something should be less than or equal to 5", err.Error()) + + err = ExceedsMaximumInt("something", "query", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something in query should be less than 5", err.Error()) + + err = ExceedsMaximumInt("something", "", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something should be less than 5", err.Error()) + + err = ExceedsMaximumUint("something", "query", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something in query should be less than or equal to 5", err.Error()) + + err = ExceedsMaximumUint("something", "", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something should be less than or equal to 5", err.Error()) + + err = ExceedsMaximumUint("something", "query", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something in query should be less than 5", err.Error()) + + err = ExceedsMaximumUint("something", "", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something should be less than 5", err.Error()) + + err = ExceedsMaximum("something", "query", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something in query should be less than or equal to 5", err.Error()) + + err = ExceedsMaximum("something", "", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something should be less than or equal to 5", err.Error()) + + err = ExceedsMaximum("something", "query", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something in query should be less than 5", err.Error()) + + err = ExceedsMaximum("something", "", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MaxFailCode, err.Code()) + assert.Equal(t, "something should be less than 5", err.Error()) + + err = ExceedsMinimumInt("something", "query", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something in query should be greater than or equal to 5", err.Error()) + + err = ExceedsMinimumInt("something", "", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something should be greater than or equal to 5", err.Error()) + + err = ExceedsMinimumInt("something", "query", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something in query should be greater than 5", err.Error()) + + err = ExceedsMinimumInt("something", "", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something should be greater than 5", err.Error()) + + err = ExceedsMinimumUint("something", "query", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something in query should be greater than or equal to 5", err.Error()) + + err = ExceedsMinimumUint("something", "", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something should be greater than or equal to 5", err.Error()) + + err = ExceedsMinimumUint("something", "query", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something in query should be greater than 5", err.Error()) + + err = ExceedsMinimumUint("something", "", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something should be greater than 5", err.Error()) + + err = ExceedsMinimum("something", "query", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something in query should be greater than or equal to 5", err.Error()) + + err = ExceedsMinimum("something", "", 5, false) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something should be greater than or equal to 5", err.Error()) + + err = ExceedsMinimum("something", "query", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something in query should be greater than 5", err.Error()) + + err = ExceedsMinimum("something", "", 5, true) + assert.Error(t, err) + assert.EqualValues(t, MinFailCode, err.Code()) + assert.Equal(t, "something should be greater than 5", err.Error()) + + err = NotMultipleOf("something", "query", 5) + assert.Error(t, err) + assert.EqualValues(t, MultipleOfFailCode, err.Code()) + assert.Equal(t, "something in query should be a multiple of 5", err.Error()) + + err = NotMultipleOf("something", "", 5) + assert.Error(t, err) + assert.EqualValues(t, MultipleOfFailCode, err.Code()) + assert.Equal(t, "something should be a multiple of 5", err.Error()) + + err = EnumFail("something", "query", "yada", []interface{}{"hello", "world"}) + assert.Error(t, err) + assert.EqualValues(t, EnumFailCode, err.Code()) + assert.Equal(t, "something in query should be one of [hello world]", err.Error()) + + err = EnumFail("something", "", "yada", []interface{}{"hello", "world"}) + assert.Error(t, err) + assert.EqualValues(t, EnumFailCode, err.Code()) + assert.Equal(t, "something should be one of [hello world]", err.Error()) + + err = Required("something", "query") + assert.Error(t, err) + assert.EqualValues(t, RequiredFailCode, err.Code()) + assert.Equal(t, "something in query is required", err.Error()) + + err = Required("something", "") + assert.Error(t, err) + assert.EqualValues(t, RequiredFailCode, err.Code()) + assert.Equal(t, "something is required", err.Error()) + + err = TooLong("something", "query", 5) + assert.Error(t, err) + assert.EqualValues(t, TooLongFailCode, err.Code()) + assert.Equal(t, "something in query should be at most 5 chars long", err.Error()) + + err = TooLong("something", "", 5) + assert.Error(t, err) + assert.EqualValues(t, TooLongFailCode, err.Code()) + assert.Equal(t, "something should be at most 5 chars long", err.Error()) + + err = TooShort("something", "query", 5) + assert.Error(t, err) + assert.EqualValues(t, TooShortFailCode, err.Code()) + assert.Equal(t, "something in query should be at least 5 chars long", err.Error()) + + err = TooShort("something", "", 5) + assert.Error(t, err) + assert.EqualValues(t, TooShortFailCode, err.Code()) + assert.Equal(t, "something should be at least 5 chars long", err.Error()) + + err = FailedPattern("something", "query", "\\d+") + assert.Error(t, err) + assert.EqualValues(t, PatternFailCode, err.Code()) + assert.Equal(t, "something in query should match '\\d+'", err.Error()) + + err = FailedPattern("something", "", "\\d+") + assert.Error(t, err) + assert.EqualValues(t, PatternFailCode, err.Code()) + assert.Equal(t, "something should match '\\d+'", err.Error()) + + err = InvalidTypeName("something") + assert.Error(t, err) + assert.EqualValues(t, InvalidTypeCode, err.Code()) + assert.Equal(t, "something is an invalid type name", err.Error()) + + err = AdditionalItemsNotAllowed("something", "query") + assert.Error(t, err) + assert.EqualValues(t, NoAdditionalItemsCode, err.Code()) + assert.Equal(t, "something in query can't have additional items", err.Error()) + + err = AdditionalItemsNotAllowed("something", "") + assert.Error(t, err) + assert.EqualValues(t, NoAdditionalItemsCode, err.Code()) + assert.Equal(t, "something can't have additional items", err.Error()) + + err = InvalidCollectionFormat("something", "query", "yada") + assert.Error(t, err) + assert.EqualValues(t, InvalidTypeCode, err.Code()) + assert.Equal(t, "the collection format \"yada\" is not supported for the query param \"something\"", err.Error()) + + err2 := CompositeValidationError() + assert.Error(t, err2) + assert.EqualValues(t, CompositeErrorCode, err2.Code()) + assert.Equal(t, "validation failure list", err2.Error()) +} diff --git a/vendor/github.com/go-openapi/loads/.drone.yml b/vendor/github.com/go-openapi/loads/.drone.yml new file mode 100644 index 0000000000..9822910353 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/.drone.yml @@ -0,0 +1,39 @@ +clone: + path: github.com/go-openapi/loads + +matrix: + GO_VERSION: + - "1.6" + +build: + integration: + image: golang:$$GO_VERSION + pull: true + environment: + GOCOVMODE: "count" + commands: + - go get -u github.com/axw/gocov/gocov + - go get -u gopkg.in/matm/v1/gocov-html + - go get -u github.com/cee-dub/go-junit-report + - go get -u github.com/stretchr/testify/assert + - go get -u gopkg.in/yaml.v2 + - go get -u github.com/go-openapi/swag + - go get -u github.com/go-openapi/analysis + - go get -u github.com/go-openapi/spec + - ./hack/build-drone.sh + +notify: + slack: + channel: bots + webhook_url: $$SLACK_URL + username: drone + +publish: + coverage: + server: https://coverage.vmware.run + token: $$GITHUB_TOKEN + # threshold: 70 + # must_increase: true + when: + matrix: + GO_VERSION: "1.6" diff --git a/vendor/github.com/go-openapi/loads/.editorconfig b/vendor/github.com/go-openapi/loads/.editorconfig new file mode 100644 index 0000000000..3152da69a5 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/.editorconfig @@ -0,0 +1,26 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +# Set default charset +[*.{js,py,go,scala,rb,java,html,css,less,sass,md}] +charset = utf-8 + +# Tab indentation (no size specified) +[*.go] +indent_style = tab + +[*.md] +trim_trailing_whitespace = false + +# Matches the exact files either package.json or .travis.yml +[{package.json,.travis.yml}] +indent_style = space +indent_size = 2 diff --git a/vendor/github.com/go-openapi/loads/.github/CONTRIBUTING.md b/vendor/github.com/go-openapi/loads/.github/CONTRIBUTING.md new file mode 100644 index 0000000000..7dea4240d7 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/.github/CONTRIBUTING.md @@ -0,0 +1,117 @@ +## Contribution Guidelines + +### Pull requests are always welcome + +We are always thrilled to receive pull requests, and do our best to +process them as fast as possible. Not sure if that typo is worth a pull +request? Do it! We will appreciate it. + +If your pull request is not accepted on the first try, don't be +discouraged! If there's a problem with the implementation, hopefully you +received feedback on what to improve. + +We're trying very hard to keep go-swagger lean and focused. We don't want it +to do everything for everybody. This means that we might decide against +incorporating a new feature. However, there might be a way to implement +that feature *on top of* go-swagger. + + +### Conventions + +Fork the repo and make changes on your fork in a feature branch: + +- If it's a bugfix branch, name it XXX-something where XXX is the number of the + issue +- If it's a feature branch, create an enhancement issue to announce your + intentions, and name it XXX-something where XXX is the number of the issue. + +Submit unit tests for your changes. Go has a great test framework built in; use +it! Take a look at existing tests for inspiration. Run the full test suite on +your branch before submitting a pull request. + +Update the documentation when creating or modifying features. Test +your documentation changes for clarity, concision, and correctness, as +well as a clean documentation build. See ``docs/README.md`` for more +information on building the docs and how docs get released. + +Write clean code. Universally formatted code promotes ease of writing, reading, +and maintenance. Always run `gofmt -s -w file.go` on each changed file before +committing your changes. Most editors have plugins that do this automatically. + +Pull requests descriptions should be as clear as possible and include a +reference to all the issues that they address. + +Pull requests must not contain commits from other users or branches. + +Commit messages must start with a capitalized and short summary (max. 50 +chars) written in the imperative, followed by an optional, more detailed +explanatory text which is separated from the summary by an empty line. + +Code review comments may be added to your pull request. Discuss, then make the +suggested modifications and push additional commits to your feature branch. Be +sure to post a comment after pushing. The new commits will show up in the pull +request automatically, but the reviewers will not be notified unless you +comment. + +Before the pull request is merged, make sure that you squash your commits into +logical units of work using `git rebase -i` and `git push -f`. After every +commit the test suite should be passing. Include documentation changes in the +same commit so that a revert would remove all traces of the feature or fix. + +Commits that fix or close an issue should include a reference like `Closes #XXX` +or `Fixes #XXX`, which will automatically close the issue when merged. + +### Sign your work + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right to +pass it on as an open-source patch. The rules are pretty simple: if you +can certify the below (from +[developercertificate.org](http://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +You can add the sign off when creating the git commit via `git commit -s`. diff --git a/vendor/github.com/go-openapi/loads/.gitignore b/vendor/github.com/go-openapi/loads/.gitignore new file mode 100644 index 0000000000..e4f15f17bf --- /dev/null +++ b/vendor/github.com/go-openapi/loads/.gitignore @@ -0,0 +1,4 @@ +secrets.yml +coverage.out +profile.cov +profile.out diff --git a/vendor/github.com/go-openapi/loads/.travis.yml b/vendor/github.com/go-openapi/loads/.travis.yml new file mode 100644 index 0000000000..b0d357e659 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/.travis.yml @@ -0,0 +1,16 @@ +language: go +go: +- 1.8 +install: +- go get -u github.com/stretchr/testify +- go get -u github.com/go-openapi/analysis +- go get -u github.com/go-openapi/spec +- go get -u github.com/go-openapi/swag +- go get -u gopkg.in/yaml.v2 +script: +- ./hack/coverage +after_success: +- bash <(curl -s https://codecov.io/bash) +notifications: + slack: + secure: OxkPwVp35qBTUilgWC8xykSj+sGMcj0h8IIOKD+Rflx2schZVlFfdYdyVBM+s9OqeOfvtuvnR9v1Ye2rPKAvcjWdC4LpRGUsgmItZaI6Um8Aj6+K9udCw5qrtZVfOVmRu8LieH//XznWWKdOultUuniW0MLqw5+II87Gd00RWbCGi0hk0PykHe7uK+PDA2BEbqyZ2WKKYCvfB3j+0nrFOHScXqnh0V05l2E83J4+Sgy1fsPy+1WdX58ZlNBG333ibaC1FS79XvKSmTgKRkx3+YBo97u6ZtUmJa5WZjf2OdLG3KIckGWAv6R5xgxeU31N0Ng8L332w/Edpp2O/M2bZwdnKJ8hJQikXIAQbICbr+lTDzsoNzMdEIYcHpJ5hjPbiUl3Bmd+Jnsjf5McgAZDiWIfpCKZ29tPCEkVwRsOCqkyPRMNMzHHmoja495P5jR+ODS7+J8RFg5xgcnOgpP9D4Wlhztlf5WyZMpkLxTUD+bZq2SRf50HfHFXTkfq22zPl3d1eq0yrLwh/Z/fWKkfb6SyysROL8y6s8u3dpFX1YHSg0BR6i913h4aoZw9B2BG27cafLLTwKYsp2dFo1PWl4O6u9giFJIeqwloZHLKKrwh0cBFhB7RH0I58asxkZpCH6uWjJierahmHe7iS+E6i+9oCHkOZ59hmCYNimIs3hM= diff --git a/vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..9322b065e3 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at ivan+abuse@flanders.co.nz. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/loads/LICENSE b/vendor/github.com/go-openapi/loads/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/go-openapi/loads/README.md b/vendor/github.com/go-openapi/loads/README.md new file mode 100644 index 0000000000..6dbb8342e1 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/README.md @@ -0,0 +1,5 @@ +# Loads OAI specs [![Build Status](https://travis-ci.org/go-openapi/loads.svg?branch=master)](https://travis-ci.org/go-openapi/loads) [![codecov](https://codecov.io/gh/go-openapi/loads/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/loads) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) + +[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/loads/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/loads?status.svg)](http://godoc.org/github.com/go-openapi/loads) + +Loading of OAI specification documents from local or remote locations. diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithArrayRef.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithArrayRef.json new file mode 100644 index 0000000000..25e8903a71 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithArrayRef.json @@ -0,0 +1,17 @@ +{ + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "children": { + "type": "array", + "items": { + "$ref": "Person" + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithComposition.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithComposition.json new file mode 100644 index 0000000000..21e01dc2af --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithComposition.json @@ -0,0 +1,68 @@ +{ + "definitions": { + "Cat": { + "description": "A representation of a cat", + "allOf": [ + { "$ref": "#/models/Pet" }, + { + "properties": { + "huntingSkill": { + "type": "string", + "description": "The measured skill for hunting", + "default": "lazy", + "enum": ["clueless", "lazy", "adventerous", "aggressive"] + } + }, + "required": [ "huntingSkill" ] + } + ] + }, + "Dog": { + "description": "A representation of a dog", + "allOf": [ + { "$ref": "#/models/Pet" }, + { + "properties": { + "packSize": { + "type": "integer", + "format": "int32", + "description": "the size of the pack the dog is from", + "default": 0, + "minimum": 0 + } + }, + "required": [ "name", "packSize" ] + } + ] + }, + "Fish": { + "description": "A representation of a fish", + "allOf": [ + { "$ref": "#/models/Pet" }, + { + "properties": { + "fins": { + "type": "integer", + "format": "int32", + "description": "count of fins", + "minimum": 0 + } + }, + "required": [ "fins" ] + } + ] + }, + "Pet": { + "discriminator": "petType", + "properties": { + "name": { + "type": "string" + }, + "petType": { + "type": "string" + } + }, + "required": [ "name", "petType" ] + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithDateTimeMap.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithDateTimeMap.json new file mode 100644 index 0000000000..a5ebdf9b29 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithDateTimeMap.json @@ -0,0 +1,7 @@ +{ + "description": "true", + "additionalProperties": { + "type": "string", + "format": "date-time" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithExamples.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithExamples.json new file mode 100644 index 0000000000..f62be6624d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithExamples.json @@ -0,0 +1,28 @@ +{ + "definitions": { + "Pet": { + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "Dog": { + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithInt32Map.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithInt32Map.json new file mode 100644 index 0000000000..b4597e846d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithInt32Map.json @@ -0,0 +1,7 @@ +{ + "description": "This is a Map[String, Integer]", + "additionalProperties": { + "type": "integer", + "format": "int32" + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithInt64Map.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithInt64Map.json new file mode 100644 index 0000000000..5160f21c4e --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithInt64Map.json @@ -0,0 +1,7 @@ +{ + "description": "true", + "additionalProperties": { + "type": "integer", + "format": "int64" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithMultipleProperties.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithMultipleProperties.json new file mode 100644 index 0000000000..dba5e64abd --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithMultipleProperties.json @@ -0,0 +1,67 @@ +{ + "description": "true", + "properties": { + "booleanValue": { + "type": "boolean" + }, + "byteValue": { + "type": "string", + "format": "byte" + }, + "dateTimeValue": { + "type": "string", + "format": "date-time" + }, + "int32Value": { + "type": "integer", + "format": "int32" + }, + "int64Value": { + "type": "integer", + "format": "int64" + }, + "stringValue": { + "type": "string" + }, + "booleanArrayValue": { + "type": "array", + "items": { + "type": "boolean" + } + }, + "byteArrayValue": { + "type": "array", + "items": { + "type": "string", + "format": "byte" + } + }, + "dateTimeArrayValue": { + "type": "array", + "items": { + "type": "string", + "format": "date-time" + } + }, + "int32ArrayValue": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + "int64ArrayValue": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + "stringArrayValue": { + "type": "array", + "items": { + "type": "string" + } + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithObjectMap.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithObjectMap.json new file mode 100644 index 0000000000..3e9fb7700c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithObjectMap.json @@ -0,0 +1,15 @@ +{ + "description": "This is a Map[String, { id: Long, name: String}]", + "additionalProperties": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithPrimitiveArray.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithPrimitiveArray.json new file mode 100644 index 0000000000..bc1a8e1740 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithPrimitiveArray.json @@ -0,0 +1,18 @@ +{ + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "childrensAges": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithStringProperty.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithStringProperty.json new file mode 100644 index 0000000000..53b4fe1d7c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithStringProperty.json @@ -0,0 +1,8 @@ +{ + "description": "true", + "properties": { + "name": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithXmlAttributes.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithXmlAttributes.json new file mode 100644 index 0000000000..1aed1a9f73 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/modelWithXmlAttributes.json @@ -0,0 +1,26 @@ +{ + "description": "this model serves xml and json structures", + "xml": { + "name": "XMLModel" + }, + "properties": { + "id": { + "type": "integer", + "format": "int64", + "xml": { + "attribute": true, + "namespace": "ns1", + "prefix": "urn1" + } + }, + "items": { + "type": "array", + "items": { + "type": "string" + }, + "xml": { + "wrapped": true + } + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/models.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/models.json new file mode 100644 index 0000000000..7eff6dbe04 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/models.json @@ -0,0 +1,14 @@ +{ + "definitions": { + "Pet": { + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/multipleModels.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/multipleModels.json new file mode 100644 index 0000000000..f62be6624d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/multipleModels.json @@ -0,0 +1,28 @@ +{ + "definitions": { + "Pet": { + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "Dog": { + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithBooleanArray.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithBooleanArray.json new file mode 100644 index 0000000000..e7ae99b077 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithBooleanArray.json @@ -0,0 +1,6 @@ +{ + "type": "array", + "items": { + "type": "boolean" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithByteArray.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithByteArray.json new file mode 100644 index 0000000000..a6cb13c18b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithByteArray.json @@ -0,0 +1,7 @@ +{ + "type": "array", + "items": { + "type": "string", + "format": "byte" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithComplexArray.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithComplexArray.json new file mode 100644 index 0000000000..c2402e0c6c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithComplexArray.json @@ -0,0 +1,6 @@ +{ + "type": "array", + "items": { + "$ref": "ComplexType" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithDateTimeArray.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithDateTimeArray.json new file mode 100644 index 0000000000..8b1077316d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithDateTimeArray.json @@ -0,0 +1,7 @@ +{ + "type": "array", + "items": { + "type": "string", + "format": "date-time" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithInt32Array.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithInt32Array.json new file mode 100644 index 0000000000..5aae819cae --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithInt32Array.json @@ -0,0 +1,7 @@ +{ + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithInt64Array.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithInt64Array.json new file mode 100644 index 0000000000..5b1f551595 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithInt64Array.json @@ -0,0 +1,7 @@ +{ + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithRef.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithRef.json new file mode 100644 index 0000000000..d8ffdd589b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithRef.json @@ -0,0 +1,5 @@ +{ + "$ref": "Foo", + "description": "a boolean", + "readOnly": true +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithStringArray.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithStringArray.json new file mode 100644 index 0000000000..7936520d79 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/propertyWithStringArray.json @@ -0,0 +1,6 @@ +{ + "type": "array", + "items": { + "type": "string" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleBooleanProperty.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleBooleanProperty.json new file mode 100644 index 0000000000..04153ed864 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleBooleanProperty.json @@ -0,0 +1,5 @@ +{ + "type": "boolean", + "description": "a boolean", + "readOnly": true +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleByteProperty.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleByteProperty.json new file mode 100644 index 0000000000..74fc007f75 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleByteProperty.json @@ -0,0 +1,4 @@ +{ + "type": "string", + "format": "byte" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleDateTimeProperty.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleDateTimeProperty.json new file mode 100644 index 0000000000..a154c6b388 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleDateTimeProperty.json @@ -0,0 +1,4 @@ +{ + "type": "string", + "format": "date-time" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleInt32Property.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleInt32Property.json new file mode 100644 index 0000000000..b436c52c79 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleInt32Property.json @@ -0,0 +1,4 @@ +{ + "type": "integer", + "format": "int32" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleInt64Property.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleInt64Property.json new file mode 100644 index 0000000000..1f3419620e --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleInt64Property.json @@ -0,0 +1,4 @@ +{ + "type": "integer", + "format": "int64" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleStringProperty.json b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleStringProperty.json new file mode 100644 index 0000000000..28ac6e8648 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/models/properties/simpleStringProperty.json @@ -0,0 +1,3 @@ +{ + "type": "string" +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/cascadingSchemes.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/cascadingSchemes.json new file mode 100644 index 0000000000..68c9702925 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/cascadingSchemes.json @@ -0,0 +1,98 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "my.api.com", + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "paths": { + "/pets/{petId}": { + "get": { + "description": "Returns a pet based on ID", + "summary": "Find pet by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "$ref": "Pet" + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + }, + "schemes": [ "https" ] + } + } + }, + "definitions": { + "Pet": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/commonParameters.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/commonParameters.json new file mode 100644 index 0000000000..5a9a128415 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/commonParameters.json @@ -0,0 +1,100 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "my.api.com", + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "paths": { + "/pets/{id}": { + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to use", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "get": { + "description": "Returns pets based on ID", + "summary": "Find pets by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "type": "array", + "items": { + "$ref": "Pet" + } + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } + } + }, + "definitions": { + "Pet": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/multipleMimeTypes.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/multipleMimeTypes.json new file mode 100644 index 0000000000..fa014914df --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/multipleMimeTypes.json @@ -0,0 +1,109 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "my.api.com", + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "text/plain; charset=utf-8", + "application/json", + "application/vnd.github+json", + "application/vnd.github.v3+json", + "application/vnd.github.v3.raw+json", + "application/vnd.github.v3.text+json", + "application/vnd.github.v3.html+json", + "application/vnd.github.v3.full+json", + "application/vnd.github.v3.diff", + "application/vnd.github.v3.patch" + ], + "produces": [ + "application/json", + "application/xml" + ], + "paths": { + "/pets/{id}": { + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to use", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "get": { + "description": "Returns pets based on ID", + "summary": "Find pets by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "type": "array", + "items": { + "$ref": "Pet" + } + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } + } + }, + "definitions": { + "Pet": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/operationWithTags.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/operationWithTags.json new file mode 100644 index 0000000000..8325605665 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/operationWithTags.json @@ -0,0 +1,30 @@ +{ + "description": "Returns a pet based on ID", + "summary": "Find pet by ID", + "operationId": "getPetsById", + "tags": [ "foo", "bar"], + "produces": [ + "application/json", + "text/html" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "200": { + "description": "a pet to be returned", + "schema": {"$ref": "Pet"} + }, + "default": { + "description": "Unexpected error", + "schema": {"$ref": "ErrorModel"} + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/stringPathAndBoolQueryParamResource.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/stringPathAndBoolQueryParamResource.json new file mode 100644 index 0000000000..75f0efa281 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/stringPathAndBoolQueryParamResource.json @@ -0,0 +1,36 @@ +{ + "description": "Returns a pet based on ID", + "summary": "Find pet by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "integer", + "format": "int64" + }, + { + "name": "includeDetails", + "in": "query", + "description": "include details in response", + "required": true, + "type": "boolean" + } + ], + "responses": { + "200": { + "description": "a pet to be returned", + "schema": {"$ref": "Pet"} + }, + "default": { + "description": "Unexpected error", + "schema": {"$ref": "ErrorModel"} + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/stringPathParamResource.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/stringPathParamResource.json new file mode 100644 index 0000000000..14eba194a9 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/operations/stringPathParamResource.json @@ -0,0 +1,33 @@ +{ + "description": "Returns a pet based on ID", + "summary": "Find pet by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "200": { + "description": "fun", + "schema": {"$ref": "Pet"} + }, + "400": { + "description": "Invalid ID supplied <= this is purely for documentation", + "schema": {"$ref": "ErrorModel"} + }, + "default": { + "description": "Unexpected error", + "schema": {"$ref": "ErrorModel"} + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyComplexArrayParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyComplexArrayParameter.json new file mode 100644 index 0000000000..5a4ef2582b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyComplexArrayParameter.json @@ -0,0 +1,13 @@ +{ + "name": "user", + "in": "body", + "description": "user to add to the system", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "format": "csv" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyComplexParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyComplexParameter.json new file mode 100644 index 0000000000..4a5327a811 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyComplexParameter.json @@ -0,0 +1,9 @@ +{ + "name": "user", + "in": "body", + "description": "user to add to the system", + "required": true, + "schema": { + "$ref": "User" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyInt64Parameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyInt64Parameter.json new file mode 100644 index 0000000000..5bd668b811 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyInt64Parameter.json @@ -0,0 +1,10 @@ +{ + "name": "id", + "in": "body", + "description": "id to add", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyStringArrayParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyStringArrayParameter.json new file mode 100644 index 0000000000..535a3056dc --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyStringArrayParameter.json @@ -0,0 +1,12 @@ +{ + "name": "user", + "in": "body", + "description": "user to add to the system", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyStringParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyStringParameter.json new file mode 100644 index 0000000000..499435a5b6 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/bodyStringParameter.json @@ -0,0 +1,9 @@ +{ + "name": "user", + "in": "body", + "description": "user to add to the system", + "required": true, + "schema": { + "type": "string" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataComplexParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataComplexParameter.json new file mode 100644 index 0000000000..aa09e71603 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataComplexParameter.json @@ -0,0 +1,7 @@ +{ + "name": "firstName", + "in": "formData", + "description": "users first name", + "required": true, + "$ref": "Nothing" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataInt64Parameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataInt64Parameter.json new file mode 100644 index 0000000000..c00176cb42 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataInt64Parameter.json @@ -0,0 +1,8 @@ +{ + "name": "id", + "in": "formData", + "description": "username to fetch", + "required": true, + "type": "integer", + "format": "int64" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataStringArrayParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataStringArrayParameter.json new file mode 100644 index 0000000000..9d06ef4652 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataStringArrayParameter.json @@ -0,0 +1,10 @@ +{ + "name": "user", + "in": "formData", + "description": "user to add to the system", + "required": true, + "type": "array", + "items": { + "type": "string" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataStringParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataStringParameter.json new file mode 100644 index 0000000000..98d66e63d8 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/formDataStringParameter.json @@ -0,0 +1,7 @@ +{ + "name": "firstName", + "in": "formData", + "description": "users first name", + "required": true, + "type": "string" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerInt64ArrayParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerInt64ArrayParameter.json new file mode 100644 index 0000000000..81c8f2f131 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerInt64ArrayParameter.json @@ -0,0 +1,12 @@ +{ + "name": "token", + "in": "header", + "description": "token to be passed as a header", + "required": true, + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "collectionFormat": "csv" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerStringArrayParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerStringArrayParameter.json new file mode 100644 index 0000000000..d6b134f936 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerStringArrayParameter.json @@ -0,0 +1,11 @@ +{ + "name": "token", + "in": "header", + "description": "token to be passed as a header", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerStringParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerStringParameter.json new file mode 100644 index 0000000000..d10051ed23 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/headerStringParameter.json @@ -0,0 +1,7 @@ +{ + "name": "token", + "in": "header", + "description": "token to be passed as a header", + "required": true, + "type": "string" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathInt64Parameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathInt64Parameter.json new file mode 100644 index 0000000000..47bf2e0b92 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathInt64Parameter.json @@ -0,0 +1,8 @@ +{ + "name": "id", + "in": "path", + "description": "username to fetch", + "required": true, + "type": "integer", + "format": "int64" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathStringArrayParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathStringArrayParameter.json new file mode 100644 index 0000000000..6da46aa5d7 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathStringArrayParameter.json @@ -0,0 +1,11 @@ +{ + "name": "usernames", + "in": "path", + "description": "usernames to pass", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathStringParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathStringParameter.json new file mode 100644 index 0000000000..0ac9c6f076 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/pathStringParameter.json @@ -0,0 +1,7 @@ +{ + "name": "username", + "in": "path", + "description": "username to fetch", + "required": true, + "type": "string" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryInt64ArrayParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryInt64ArrayParameter.json new file mode 100644 index 0000000000..59b557a6f6 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryInt64ArrayParameter.json @@ -0,0 +1,12 @@ +{ + "name": "id", + "in": "query", + "description": "ID of the object to fetch", + "required": true, + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "collectionFormat": "csv" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryStringParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryStringParameter.json new file mode 100644 index 0000000000..fde2d3badb --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryStringParameter.json @@ -0,0 +1,8 @@ +{ + "name": "id", + "in": "query", + "description": "ID of the object to fetch", + "required": true, + "type": "integer", + "format": "int64" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryWithComplexParameter.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryWithComplexParameter.json new file mode 100644 index 0000000000..61f9e93234 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/parameters/queryWithComplexParameter.json @@ -0,0 +1,9 @@ +{ + "name": "id", + "in": "query", + "description": "a complex object which should not validate", + "required": true, + "schema": { + "$ref": "Pet" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithExamplePayload.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithExamplePayload.json new file mode 100644 index 0000000000..90767b6a5d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithExamplePayload.json @@ -0,0 +1,114 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "my.api.com", + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "paths": { + "/pets/{petId}": { + "get": { + "description": "Returns a pet based on ID", + "summary": "Find pet by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "$ref": "Pet" + }, + "examples": { + "application/json": { + "id": 9, + "category": { + "name": "domestic" + }, + "name": "monster", + "tags": [ + { + "name": "for sale" + } + ], + "status": "alive" + } + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } + } + }, + "definitions": { + "Pet": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "example": "cat" + }, + "tag": { + "type": "string", + "example": "for sale" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithLinkedDefinitions.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithLinkedDefinitions.json new file mode 100644 index 0000000000..52f9ebd9cc --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithLinkedDefinitions.json @@ -0,0 +1,62 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "my.api.com", + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "paths": { + "/pets/{petId}": { + "$ref": "https://raw.githubusercontent.com/reverb/swagger-spec/master/fixtures/v2.0/json/resources/resourceWithLinkedDefinitions_part1.json" + } + }, + "definitions": { + "Pet": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithLinkedDefinitions_part1.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithLinkedDefinitions_part1.json new file mode 100644 index 0000000000..5b7f5b9ad3 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithLinkedDefinitions_part1.json @@ -0,0 +1,38 @@ +{ + "get": { + "description": "Returns a pet based on ID", + "summary": "Find pet by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "$ref": "Pet" + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithRelativeHost.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithRelativeHost.json new file mode 100644 index 0000000000..2e16c3a395 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/resourceWithRelativeHost.json @@ -0,0 +1,99 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "paths": { + "/pets/{id}": { + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to use", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "get": { + "description": "Returns pets based on ID", + "summary": "Find pets by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "type": "array", + "items": { + "$ref": "Pet" + } + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } + } + }, + "definitions": { + "Pet": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/reusableParameters.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/reusableParameters.json new file mode 100644 index 0000000000..3547c419f7 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/reusableParameters.json @@ -0,0 +1,105 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "my.api.com", + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "paths": { + "/pets/{id}": { + "get": { + "description": "Returns pets based on ID", + "summary": "Find pets by ID", + "operationId": "getPetsById", + "parameters": [ + { "$ref": "#/parameters/skipParam" }, + { "$ref": "#/parameters/limitParam" } + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "type": "array", + "items": { + "$ref": "Pet" + } + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } + } + }, + "parameters": { + "skipParam": { + "name": "skip", + "in": "query", + "description": "number of items to skip", + "required": true, + "type": "integer", + "format": "int32" + }, + "limitParam": { + "name": "limit", + "in": "query", + "description": "max records to return", + "required": true, + "type": "integer", + "format": "int32" + } + }, + "definitions": { + "Pet": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/securityExample.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/securityExample.json new file mode 100644 index 0000000000..e4c482c4db --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/securityExample.json @@ -0,0 +1,181 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "security": [ + { + "githubAccessCode": [ "user", "gist" ] + }, + { + "internalApiKey": [] + } + ], + "paths": { + "/pets/{id}": { + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to use", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "get": { + "description": "Returns pets based on ID", + "summary": "Find pets by ID", + "operationId": "getPetsById", + "security": [ + { + "githubAuth":[ + "user:read", + "user:write" + ] + }, + { + "internalApiKey": [] + } + ], + "produces": [ + "application/json", + "text/html" + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "type": "array", + "items": { + "$ref": "Pet" + } + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } + } + }, + "securityDefinitions": { + "githubAccessCode": { + "type": "oauth2", + "scopes": { + "user": "Grants read/write access to profile info only. Note that this scope includes user:email and user:follow.", + "user:email": "Grants read access to a user’s email addresses.", + "user:follow": "Grants access to follow or unfollow other users.", + "public_repo": "Grants read/write access to code, commit statuses, and deployment statuses for public repositories and organizations.", + "repo": "Grants read/write access to code, commit statuses, and deployment statuses for public and private repositories and organizations.", + "repo_deployment": "Grants access to deployment statuses for public and private repositories. This scope is only necessary to grant other users or services access to deployment statuses, without granting access to the code.", + "repo:status": "Grants read/write access to public and private repository commit statuses. This scope is only necessary to grant other users or services access to private repository commit statuses without granting access to the code.", + "delete_repo": "Grants access to delete adminable repositories.", + "notifications": "Grants read access to a user’s notifications. repo also provides this access.", + "gist": "Grants write access to gists.", + "read:repo_hook": "Grants read and ping access to hooks in public or private repositories.", + "write:repo_hook": "Grants read, write, and ping access to hooks in public or private repositories.", + "admin:repo_hook": "Grants read, write, ping, and delete access to hooks in public or private repositories.", + "read:org": "Read-only access to organization, teams, and membership.", + "write:org": "Publicize and unpublicize organization membership.", + "admin:org": "Fully manage organization, teams, and memberships.", + "read:public_key": "List and view details for public keys.", + "write:public_key": "Create, list, and view details for public keys.", + "admin:public_key": "Fully manage public keys." + }, + "flow": "accessCode", + "authorizationUrl": "https://github.com/login/oauth/authorize", + "tokenUrl": "https://github.com/login/oauth/access_token" + }, + "petstoreImplicit": { + "type": "oauth2", + "scopes": { + "user": "Grants read/write access to profile info only. Note that this scope includes user:email and user:follow.", + "user:email": "Grants read access to a user’s email addresses.", + "user:follow": "Grants access to follow or unfollow other users.", + "public_repo": "Grants read/write access to code, commit statuses, and deployment statuses for public repositories and organizations.", + "repo": "Grants read/write access to code, commit statuses, and deployment statuses for public and private repositories and organizations.", + "repo_deployment": "Grants access to deployment statuses for public and private repositories. This scope is only necessary to grant other users or services access to deployment statuses, without granting access to the code.", + "repo:status": "Grants read/write access to public and private repository commit statuses. This scope is only necessary to grant other users or services access to private repository commit statuses without granting access to the code.", + "delete_repo": "Grants access to delete adminable repositories.", + "notifications": "Grants read access to a user’s notifications. repo also provides this access.", + "gist": "Grants write access to gists.", + "read:repo_hook": "Grants read and ping access to hooks in public or private repositories.", + "write:repo_hook": "Grants read, write, and ping access to hooks in public or private repositories.", + "admin:repo_hook": "Grants read, write, ping, and delete access to hooks in public or private repositories.", + "read:org": "Read-only access to organization, teams, and membership.", + "write:org": "Publicize and unpublicize organization membership.", + "admin:org": "Fully manage organization, teams, and memberships.", + "read:public_key": "List and view details for public keys.", + "write:public_key": "Create, list, and view details for public keys.", + "admin:public_key": "Fully manage public keys." + }, + "flow": "implicit", + "authorizationUrl": "http://petstore.swagger.wordnik.com/oauth/dialog" + }, + "internalApiKey": { + "type": "apiKey", + "in": "header", + "name": "api_key" + } + }, + "definitions": { + "Pet": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/stringPathParamResource.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/stringPathParamResource.json new file mode 100644 index 0000000000..a438a08ea2 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/stringPathParamResource.json @@ -0,0 +1,97 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "my.api.com", + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "paths": { + "/pets/{petId}": { + "get": { + "description": "Returns a pet based on ID", + "summary": "Find pet by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "$ref": "Pet" + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } + } + }, + "definitions": { + "Pet": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/taggedResource.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/taggedResource.json new file mode 100644 index 0000000000..19394c70d1 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/taggedResource.json @@ -0,0 +1,112 @@ +{ + "swagger": "2.0", + "x-reverb": { + "addAnythingYouWant": true + }, + "info": { + "x-reverb-info": "this is an example", + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "my.api.com", + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "tags": [ + { + "name": "pets" + } + ], + "paths": { + "x-reverb-path-info": "vendor info", + "/pets": { + "x-vendor-method": {}, + "get": { + "x-vendor-operation-property": {}, + "description": "Returns a pet based on ID", + "summary": "Find pet by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "parameters": [ + { + "x-vendor-parameter-property": {}, + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "responses": { + "x-vendor-operation-response-property": {}, + "200": { + "description": "pet response", + "schema": { + "$ref": "Pet" + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } + } + }, + "definitions": { + "Pet": { + "x-vendor-model-property": {}, + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/resources/vendorExtensionExamples.json b/vendor/github.com/go-openapi/loads/fixtures/json/resources/vendorExtensionExamples.json new file mode 100644 index 0000000000..267ce5399c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/resources/vendorExtensionExamples.json @@ -0,0 +1,107 @@ +{ + "swagger": "2.0", + "x-reverb": { + "addAnythingYouWant": true + }, + "info": { + "x-reverb-info": "this is an example", + "version": "1.0.9-abcd", + "title": "Swagger Sample API", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "wordnik api team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "my.api.com", + "basePath": "/v1", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "paths": { + "x-reverb-path-info": "vendor info", + "/pets": { + "x-vendor-method": {}, + "get": { + "x-vendor-operation-property": {}, + "description": "Returns a pet based on ID", + "summary": "Find pet by ID", + "operationId": "getPetsById", + "produces": [ + "application/json", + "text/html" + ], + "parameters": [ + { + "x-vendor-parameter-property": {}, + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + } + ], + "responses": { + "x-vendor-operation-response-property": {}, + "200": { + "description": "pet response", + "schema": { + "$ref": "Pet" + } + }, + "default": { + "description": "error payload", + "schema": { + "$ref": "ErrorModel" + } + } + } + } + } + }, + "definitions": { + "Pet": { + "x-vendor-model-property": {}, + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ErrorModel": { + "required": [ "code", "message" ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/responses/complexArrayResponse.json b/vendor/github.com/go-openapi/loads/fixtures/json/responses/complexArrayResponse.json new file mode 100644 index 0000000000..5d2ce79ee2 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/responses/complexArrayResponse.json @@ -0,0 +1,9 @@ +{ + "description": "A complex object array response", + "schema": { + "type": "array", + "items": { + "$ref": "VeryComplexType" + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/responses/dateTimeResponse.json b/vendor/github.com/go-openapi/loads/fixtures/json/responses/dateTimeResponse.json new file mode 100644 index 0000000000..77fe8d442a --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/responses/dateTimeResponse.json @@ -0,0 +1,7 @@ +{ + "description": "A date-time response", + "schema": { + "type": "string", + "format": "date-time" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/responses/int32Response.json b/vendor/github.com/go-openapi/loads/fixtures/json/responses/int32Response.json new file mode 100644 index 0000000000..b9470c8f23 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/responses/int32Response.json @@ -0,0 +1,7 @@ +{ + "description": "A simple string response", + "schema": { + "type": "integer", + "format": "int32" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/responses/int64Response.json b/vendor/github.com/go-openapi/loads/fixtures/json/responses/int64Response.json new file mode 100644 index 0000000000..16a4d1c1c7 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/responses/int64Response.json @@ -0,0 +1,7 @@ +{ + "description": "A simple string response", + "schema": { + "type": "integer", + "format": "int64" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/responses/multipleResponses.json b/vendor/github.com/go-openapi/loads/fixtures/json/responses/multipleResponses.json new file mode 100644 index 0000000000..b7c51544e6 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/responses/multipleResponses.json @@ -0,0 +1,18 @@ +{ + "200": { + "description": "simple string response", + "schema": { + "type": "string" + } + }, + "201": { + "description": "object created" + }, + "default": { + "description": "oops", + "schema": { + "type": "integer", + "format": "int32" + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/responses/stringArrayResponse.json b/vendor/github.com/go-openapi/loads/fixtures/json/responses/stringArrayResponse.json new file mode 100644 index 0000000000..4640ea04ba --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/responses/stringArrayResponse.json @@ -0,0 +1,9 @@ +{ + "description": "A string array response", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/responses/stringResponse.json b/vendor/github.com/go-openapi/loads/fixtures/json/responses/stringResponse.json new file mode 100644 index 0000000000..f794027371 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/responses/stringResponse.json @@ -0,0 +1,6 @@ +{ + "description": "A simple string response", + "schema": { + "type": "string" + } +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/responses/stringResponseWithHeader.json b/vendor/github.com/go-openapi/loads/fixtures/json/responses/stringResponseWithHeader.json new file mode 100644 index 0000000000..57a5f80b4d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/responses/stringResponseWithHeader.json @@ -0,0 +1,10 @@ +{ + "description": "A simple string response", + "schema": { + "type": "string" + }, + "headers": { + "is-dog": {"type": "boolean"}, + "is-cat": {"type": "boolean"} + } +} diff --git a/vendor/github.com/go-openapi/loads/fixtures/json/responses/voidResponse.json b/vendor/github.com/go-openapi/loads/fixtures/json/responses/voidResponse.json new file mode 100644 index 0000000000..a7edcadb32 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/json/responses/voidResponse.json @@ -0,0 +1,3 @@ +{ + "description": "object created" +} \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/.gitkeep b/vendor/github.com/go-openapi/loads/fixtures/yaml/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithArrayRef.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithArrayRef.yaml new file mode 100644 index 0000000000..b32a35901d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithArrayRef.yaml @@ -0,0 +1,5 @@ +required: + - id +properties: + id: {type: integer, format: int64} + children: {type: array, items: {$ref: Person}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithComposition.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithComposition.yaml new file mode 100644 index 0000000000..f0ea5e80f2 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithComposition.yaml @@ -0,0 +1,5 @@ +definitions: + Cat: {description: 'A representation of a cat', allOf: [{$ref: '#/models/Pet'}, {properties: {huntingSkill: {type: string, description: 'The measured skill for hunting', default: lazy, enum: [clueless, lazy, adventerous, aggressive]}}, required: [huntingSkill]}]} + Dog: {description: 'A representation of a dog', allOf: [{$ref: '#/models/Pet'}, {properties: {packSize: {type: integer, format: int32, description: 'the size of the pack the dog is from', default: 0}}, required: [name, packSize]}]} + Fish: {description: 'A representation of a fish', allOf: [{$ref: '#/models/Pet'}, {properties: {fins: {type: integer, format: int32, description: 'count of fins'}}, required: [fins]}]} + Pet: {discriminator: petType, properties: {name: {type: string}, petType: {type: string}}, required: [name, petType]} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithDateTimeMap.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithDateTimeMap.yaml new file mode 100644 index 0000000000..653cbd1825 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithDateTimeMap.yaml @@ -0,0 +1,4 @@ +description: 'true' +additionalProperties: + type: string + format: date-time diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithExamples.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithExamples.yaml new file mode 100644 index 0000000000..0252ec176c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithExamples.yaml @@ -0,0 +1,3 @@ +definitions: + Pet: {properties: {name: {type: string}}, required: [name]} + Dog: {properties: {id: {type: integer, format: int64}, name: {type: string}}, required: [name]} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithInt32Map.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithInt32Map.yaml new file mode 100644 index 0000000000..88ab02447a --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithInt32Map.yaml @@ -0,0 +1,4 @@ +description: 'This is a Map[String, Integer]' +additionalProperties: + type: integer + format: int32 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithInt64Map.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithInt64Map.yaml new file mode 100644 index 0000000000..16c790e42d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithInt64Map.yaml @@ -0,0 +1,4 @@ +description: 'true' +additionalProperties: + type: integer + format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithMultipleProperties.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithMultipleProperties.yaml new file mode 100644 index 0000000000..f69d27ef29 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithMultipleProperties.yaml @@ -0,0 +1,14 @@ +description: 'true' +properties: + booleanValue: {type: boolean} + byteValue: {type: string, format: byte} + dateTimeValue: {type: string, format: date-time} + int32Value: {type: integer, format: int32} + int64Value: {type: integer, format: int64} + stringValue: {type: string} + booleanArrayValue: {type: array, items: {type: boolean}} + byteArrayValue: {type: array, items: {type: string, format: byte}} + dateTimeArrayValue: {type: array, items: {type: string, format: date-time}} + int32ArrayValue: {type: array, items: {type: integer, format: int32}} + int64ArrayValue: {type: array, items: {type: integer, format: int64}} + stringArrayValue: {type: array, items: {type: string}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithObjectMap.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithObjectMap.yaml new file mode 100644 index 0000000000..e712e0f220 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithObjectMap.yaml @@ -0,0 +1,9 @@ +description: "This is a Map[String, { id: Long, name: String}]" +additionalProperties: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithPrimitiveArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithPrimitiveArray.yaml new file mode 100644 index 0000000000..0837bad52b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithPrimitiveArray.yaml @@ -0,0 +1,5 @@ +required: + - id +properties: + id: {type: integer, format: int64} + childrensAges: {type: array, items: {type: integer, format: int32}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithStringProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithStringProperty.yaml new file mode 100644 index 0000000000..a17d21e5a1 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithStringProperty.yaml @@ -0,0 +1,3 @@ +description: 'true' +properties: + name: {type: string} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithXmlAttributes.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithXmlAttributes.yaml new file mode 100644 index 0000000000..2176983f89 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/modelWithXmlAttributes.yaml @@ -0,0 +1,6 @@ +description: 'this model serves xml and json structures' +xml: + name: XMLModel +properties: + id: {type: integer, format: int64, xml: {attribute: true, namespace: ns1, prefix: urn1}} + items: {type: array, items: {type: string}, xml: {wrapped: true}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/models.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/models.yaml new file mode 100644 index 0000000000..71f8efeb42 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/models.yaml @@ -0,0 +1,2 @@ +definitions: + Pet: {properties: {name: {type: string}}, required: [name]} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/multipleModels.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/multipleModels.yaml new file mode 100644 index 0000000000..0252ec176c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/multipleModels.yaml @@ -0,0 +1,3 @@ +definitions: + Pet: {properties: {name: {type: string}}, required: [name]} + Dog: {properties: {id: {type: integer, format: int64}, name: {type: string}}, required: [name]} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithBooleanArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithBooleanArray.yaml new file mode 100644 index 0000000000..aa02d0e742 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithBooleanArray.yaml @@ -0,0 +1,3 @@ +type: array +items: + type: boolean diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithByteArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithByteArray.yaml new file mode 100644 index 0000000000..f31b350362 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithByteArray.yaml @@ -0,0 +1,4 @@ +type: array +items: + type: string + format: byte diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithComplexArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithComplexArray.yaml new file mode 100644 index 0000000000..69e0b17658 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithComplexArray.yaml @@ -0,0 +1,3 @@ +type: array +items: + $ref: ComplexType diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithDateTimeArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithDateTimeArray.yaml new file mode 100644 index 0000000000..6efef25d8f --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithDateTimeArray.yaml @@ -0,0 +1,4 @@ +type: array +items: + type: string + format: date-time diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithInt32Array.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithInt32Array.yaml new file mode 100644 index 0000000000..26fd271b00 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithInt32Array.yaml @@ -0,0 +1,4 @@ +type: array +items: + type: integer + format: int32 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithInt64Array.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithInt64Array.yaml new file mode 100644 index 0000000000..e800895ebc --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithInt64Array.yaml @@ -0,0 +1,4 @@ +type: array +items: + type: integer + format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithRef.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithRef.yaml new file mode 100644 index 0000000000..d78956949e --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithRef.yaml @@ -0,0 +1,3 @@ +$ref: Foo +description: 'a boolean' +readOnly: true diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithStringArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithStringArray.yaml new file mode 100644 index 0000000000..3a9108235c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/propertyWithStringArray.yaml @@ -0,0 +1,3 @@ +type: array +items: + type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleBooleanProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleBooleanProperty.yaml new file mode 100644 index 0000000000..9d1e27382b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleBooleanProperty.yaml @@ -0,0 +1,3 @@ +type: boolean +description: 'a boolean' +readOnly: true diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleByteProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleByteProperty.yaml new file mode 100644 index 0000000000..6af2139f99 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleByteProperty.yaml @@ -0,0 +1,2 @@ +type: string +format: byte diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleDateTimeProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleDateTimeProperty.yaml new file mode 100644 index 0000000000..407b1d7e8f --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleDateTimeProperty.yaml @@ -0,0 +1,2 @@ +type: string +format: date-time diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleInt32Property.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleInt32Property.yaml new file mode 100644 index 0000000000..8ed513dba0 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleInt32Property.yaml @@ -0,0 +1,2 @@ +type: integer +format: int32 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleInt64Property.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleInt64Property.yaml new file mode 100644 index 0000000000..69f359f3fd --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleInt64Property.yaml @@ -0,0 +1,2 @@ +type: integer +format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleStringProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleStringProperty.yaml new file mode 100644 index 0000000000..5c21d88b9e --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/models/properties/simpleStringProperty.yaml @@ -0,0 +1 @@ +type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/cascadingSchemes.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/cascadingSchemes.yaml new file mode 100644 index 0000000000..d108027742 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/cascadingSchemes.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{petId}': {get: {description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}, schemes: [https]}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/commonParameters.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/commonParameters.yaml new file mode 100644 index 0000000000..9851b7448c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/commonParameters.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{id}': {parameters: [{name: id, in: path, description: 'ID of pet to use', required: true, type: array, items: {type: string}, collectionFormat: csv}], get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, produces: [application/json, text/html], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/multipleMimeTypes.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/multipleMimeTypes.yaml new file mode 100644 index 0000000000..23bdc2d2a3 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/multipleMimeTypes.yaml @@ -0,0 +1,32 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - 'text/plain; charset=utf-8' + - application/json + - application/vnd.github+json + - application/vnd.github.v3+json + - application/vnd.github.v3.raw+json + - application/vnd.github.v3.text+json + - application/vnd.github.v3.html+json + - application/vnd.github.v3.full+json + - application/vnd.github.v3.diff + - application/vnd.github.v3.patch +produces: + - application/json + - application/xml +paths: + '/pets/{id}': {parameters: [{name: id, in: path, description: 'ID of pet to use', required: true, type: array, items: {type: string}, collectionFormat: csv}], get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, produces: [application/json, text/html], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/operationWithTags.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/operationWithTags.yaml new file mode 100644 index 0000000000..a3c85b26a3 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/operationWithTags.yaml @@ -0,0 +1,14 @@ +description: 'Returns a pet based on ID' +summary: 'Find pet by ID' +operationId: getPetsById +tags: + - foo + - bar +produces: + - application/json + - text/html +parameters: + - {name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: integer, format: int64} +responses: + '200': {description: 'a pet to be returned', schema: {$ref: Pet}} + default: {description: 'Unexpected error', schema: {$ref: ErrorModel}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/stringPathAndBoolQueryParamResource.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/stringPathAndBoolQueryParamResource.yaml new file mode 100644 index 0000000000..a00b8c469c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/stringPathAndBoolQueryParamResource.yaml @@ -0,0 +1,12 @@ +description: 'Returns a pet based on ID' +summary: 'Find pet by ID' +operationId: getPetsById +produces: + - application/json + - text/html +parameters: + - {name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: integer, format: int64} + - {name: includeDetails, in: query, description: 'include details in response', required: true, type: boolean} +responses: + '200': {description: 'a pet to be returned', schema: {$ref: Pet}} + default: {description: 'Unexpected error', schema: {$ref: ErrorModel}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/stringPathParamResource.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/stringPathParamResource.yaml new file mode 100644 index 0000000000..8c46cc7ee8 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/operations/stringPathParamResource.yaml @@ -0,0 +1,12 @@ +description: 'Returns a pet based on ID' +summary: 'Find pet by ID' +operationId: getPetsById +produces: + - application/json + - text/html +parameters: + - {name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: integer, format: int64} +responses: + '200': {description: fun, schema: {$ref: Pet}} + '400': {description: 'Invalid ID supplied <= this is purely for documentation', schema: {$ref: ErrorModel}} + default: {description: 'Unexpected error', schema: {$ref: ErrorModel}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyComplexArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyComplexArrayParameter.yaml new file mode 100644 index 0000000000..511f8dc2b3 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyComplexArrayParameter.yaml @@ -0,0 +1,8 @@ +name: user +in: body +description: 'user to add to the system' +required: true +schema: + type: array + items: {type: string} + format: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyComplexParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyComplexParameter.yaml new file mode 100644 index 0000000000..13f8fd171b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyComplexParameter.yaml @@ -0,0 +1,6 @@ +name: user +in: body +description: 'user to add to the system' +required: true +schema: + $ref: User diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyInt64Parameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyInt64Parameter.yaml new file mode 100644 index 0000000000..a270d94cb5 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyInt64Parameter.yaml @@ -0,0 +1,7 @@ +name: id +in: body +description: 'id to add' +required: true +schema: + type: integer + format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyStringArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyStringArrayParameter.yaml new file mode 100644 index 0000000000..7d88b10dc9 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyStringArrayParameter.yaml @@ -0,0 +1,7 @@ +name: user +in: body +description: 'user to add to the system' +required: true +schema: + type: array + items: {type: string} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyStringParameter.yaml new file mode 100644 index 0000000000..7fe9dbd1e0 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/bodyStringParameter.yaml @@ -0,0 +1,6 @@ +name: user +in: body +description: 'user to add to the system' +required: true +schema: + type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataComplexParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataComplexParameter.yaml new file mode 100644 index 0000000000..b49dd9e3d6 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataComplexParameter.yaml @@ -0,0 +1,5 @@ +name: firstName +in: formData +description: 'users first name' +required: true +$ref: Nothing diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataInt64Parameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataInt64Parameter.yaml new file mode 100644 index 0000000000..0faaa7f62d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataInt64Parameter.yaml @@ -0,0 +1,6 @@ +name: id +in: formData +description: 'username to fetch' +required: true +type: integer +format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataStringArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataStringArrayParameter.yaml new file mode 100644 index 0000000000..f6534662a5 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataStringArrayParameter.yaml @@ -0,0 +1,7 @@ +name: user +in: formData +description: 'user to add to the system' +required: true +type: array +items: + type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataStringParameter.yaml new file mode 100644 index 0000000000..43411cf047 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/formDataStringParameter.yaml @@ -0,0 +1,5 @@ +name: firstName +in: formData +description: 'users first name' +required: true +type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerInt64ArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerInt64ArrayParameter.yaml new file mode 100644 index 0000000000..87ec99cabc --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerInt64ArrayParameter.yaml @@ -0,0 +1,9 @@ +name: token +in: header +description: 'token to be passed as a header' +required: true +type: array +items: + type: integer + format: int64 +collectionFormat: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerStringArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerStringArrayParameter.yaml new file mode 100644 index 0000000000..70e0a0a680 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerStringArrayParameter.yaml @@ -0,0 +1,8 @@ +name: token +in: header +description: 'token to be passed as a header' +required: true +type: array +items: + type: string +collectionFormat: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerStringParameter.yaml new file mode 100644 index 0000000000..ac99c2f62c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/headerStringParameter.yaml @@ -0,0 +1,5 @@ +name: token +in: header +description: 'token to be passed as a header' +required: true +type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathInt64Parameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathInt64Parameter.yaml new file mode 100644 index 0000000000..3bd860aacd --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathInt64Parameter.yaml @@ -0,0 +1,6 @@ +name: id +in: path +description: 'username to fetch' +required: true +type: integer +format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathStringArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathStringArrayParameter.yaml new file mode 100644 index 0000000000..ebb24a7e22 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathStringArrayParameter.yaml @@ -0,0 +1,8 @@ +name: usernames +in: path +description: 'usernames to pass' +required: true +type: array +items: + type: string +collectionFormat: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathStringParameter.yaml new file mode 100644 index 0000000000..2cb4fb2eec --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/pathStringParameter.yaml @@ -0,0 +1,5 @@ +name: username +in: path +description: 'username to fetch' +required: true +type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryInt64ArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryInt64ArrayParameter.yaml new file mode 100644 index 0000000000..453e24f5d1 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryInt64ArrayParameter.yaml @@ -0,0 +1,9 @@ +name: id +in: query +description: 'ID of the object to fetch' +required: true +type: array +items: + type: integer + format: int64 +collectionFormat: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryStringParameter.yaml new file mode 100644 index 0000000000..e1df685309 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryStringParameter.yaml @@ -0,0 +1,6 @@ +name: id +in: query +description: 'ID of the object to fetch' +required: true +type: integer +format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryWithComplexParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryWithComplexParameter.yaml new file mode 100644 index 0000000000..80bc7951b8 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/parameters/queryWithComplexParameter.yaml @@ -0,0 +1,6 @@ +name: id +in: query +description: 'a complex object which should not validate' +required: true +schema: + $ref: Pet diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithExamplePayload.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithExamplePayload.yaml new file mode 100644 index 0000000000..9828d96050 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithExamplePayload.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{petId}': {get: {description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}, examples: {application/json: {id: 9, category: {name: domestic}, name: monster, tags: [{name: 'for sale'}], status: alive}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string, example: cat}, tag: {type: string, example: 'for sale'}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithLinkedDefinitions.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithLinkedDefinitions.yaml new file mode 100644 index 0000000000..b9b00c47f1 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithLinkedDefinitions.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{petId}': {$ref: 'https://raw.githubusercontent.com/reverb/swagger-spec/master/fixtures/v2.0/json/resources/resourceWithLinkedDefinitions_part1.json'} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithLinkedDefinitions_part1.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithLinkedDefinitions_part1.yaml new file mode 100644 index 0000000000..7d358fbf10 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithLinkedDefinitions_part1.yaml @@ -0,0 +1,7 @@ +get: + description: 'Returns a pet based on ID' + summary: 'Find pet by ID' + operationId: getPetsById + produces: [application/json, text/html] + parameters: [{name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}] + responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithRelativeHost.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithRelativeHost.yaml new file mode 100644 index 0000000000..744aa72e9a --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/resourceWithRelativeHost.yaml @@ -0,0 +1,22 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{id}': {parameters: [{name: id, in: path, description: 'ID of pet to use', required: true, type: array, items: {type: string}, collectionFormat: csv}], get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, produces: [application/json, text/html], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/reusableParameters.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/reusableParameters.yaml new file mode 100644 index 0000000000..1d258d0827 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/reusableParameters.yaml @@ -0,0 +1,26 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{id}': {get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, parameters: [{$ref: '#/parameters/skipParam'}, {$ref: '#/parameters/limitParam'}], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +parameters: + skipParam: {name: skip, in: query, description: 'number of items to skip', required: true, type: integer, format: int32} + limitParam: {name: limit, in: query, description: 'max records to return', required: true, type: integer, format: int32} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/securityExample.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/securityExample.yaml new file mode 100644 index 0000000000..007d26db43 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/securityExample.yaml @@ -0,0 +1,29 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +security: + - {githubAccessCode: [user, gist]} + - {internalApiKey: []} +paths: + '/pets/{id}': {parameters: [{name: id, in: path, description: 'ID of pet to use', required: true, type: array, items: {type: string}, collectionFormat: csv}], get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, security: [{githubAuth: ['user:read', 'user:write']}, {internalApiKey: []}], produces: [application/json, text/html], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +securityDefinitions: + githubAccessCode: {type: oauth2, scopes: {user: 'Grants read/write access to profile info only. Note that this scope includes user:email and user:follow.', 'user:email': 'Grants read access to a user’s email addresses.', 'user:follow': 'Grants access to follow or unfollow other users.', public_repo: 'Grants read/write access to code, commit statuses, and deployment statuses for public repositories and organizations.', repo: 'Grants read/write access to code, commit statuses, and deployment statuses for public and private repositories and organizations.', repo_deployment: 'Grants access to deployment statuses for public and private repositories. This scope is only necessary to grant other users or services access to deployment statuses, without granting access to the code.', 'repo:status': 'Grants read/write access to public and private repository commit statuses. This scope is only necessary to grant other users or services access to private repository commit statuses without granting access to the code.', delete_repo: 'Grants access to delete adminable repositories.', notifications: 'Grants read access to a user’s notifications. repo also provides this access.', gist: 'Grants write access to gists.', 'read:repo_hook': 'Grants read and ping access to hooks in public or private repositories.', 'write:repo_hook': 'Grants read, write, and ping access to hooks in public or private repositories.', 'admin:repo_hook': 'Grants read, write, ping, and delete access to hooks in public or private repositories.', 'read:org': 'Read-only access to organization, teams, and membership.', 'write:org': 'Publicize and unpublicize organization membership.', 'admin:org': 'Fully manage organization, teams, and memberships.', 'read:public_key': 'List and view details for public keys.', 'write:public_key': 'Create, list, and view details for public keys.', 'admin:public_key': 'Fully manage public keys.'}, flow: accessCode, authorizationUrl: 'https://github.com/login/oauth/authorize', tokenUrl: 'https://github.com/login/oauth/access_token'} + petstoreImplicit: {type: oauth2, scopes: {user: 'Grants read/write access to profile info only. Note that this scope includes user:email and user:follow.', 'user:email': 'Grants read access to a user’s email addresses.', 'user:follow': 'Grants access to follow or unfollow other users.', public_repo: 'Grants read/write access to code, commit statuses, and deployment statuses for public repositories and organizations.', repo: 'Grants read/write access to code, commit statuses, and deployment statuses for public and private repositories and organizations.', repo_deployment: 'Grants access to deployment statuses for public and private repositories. This scope is only necessary to grant other users or services access to deployment statuses, without granting access to the code.', 'repo:status': 'Grants read/write access to public and private repository commit statuses. This scope is only necessary to grant other users or services access to private repository commit statuses without granting access to the code.', delete_repo: 'Grants access to delete adminable repositories.', notifications: 'Grants read access to a user’s notifications. repo also provides this access.', gist: 'Grants write access to gists.', 'read:repo_hook': 'Grants read and ping access to hooks in public or private repositories.', 'write:repo_hook': 'Grants read, write, and ping access to hooks in public or private repositories.', 'admin:repo_hook': 'Grants read, write, ping, and delete access to hooks in public or private repositories.', 'read:org': 'Read-only access to organization, teams, and membership.', 'write:org': 'Publicize and unpublicize organization membership.', 'admin:org': 'Fully manage organization, teams, and memberships.', 'read:public_key': 'List and view details for public keys.', 'write:public_key': 'Create, list, and view details for public keys.', 'admin:public_key': 'Fully manage public keys.'}, flow: implicit, authorizationUrl: 'http://petstore.swagger.wordnik.com/oauth/dialog'} + internalApiKey: {type: apiKey, in: header, name: api_key} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/stringPathParamResource.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/stringPathParamResource.yaml new file mode 100644 index 0000000000..a4a83fea0f --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/stringPathParamResource.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{petId}': {get: {description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/taggedResource.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/taggedResource.yaml new file mode 100644 index 0000000000..1b8620e52c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/taggedResource.yaml @@ -0,0 +1,29 @@ +swagger: '2.0' +x-reverb: + addAnythingYouWant: true +info: + x-reverb-info: 'this is an example' + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +tags: + - {name: pets} +paths: + x-reverb-path-info: 'vendor info' + /pets: {x-vendor-method: {}, get: {x-vendor-operation-property: {}, description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{x-vendor-parameter-property: {}, name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, x-vendor-operation-response-property: {}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {x-vendor-model-property: {}, required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/vendorExtensionExamples.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/vendorExtensionExamples.yaml new file mode 100644 index 0000000000..59bba0f3d0 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/resources/vendorExtensionExamples.yaml @@ -0,0 +1,27 @@ +swagger: '2.0' +x-reverb: + addAnythingYouWant: true +info: + x-reverb-info: 'this is an example' + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + x-reverb-path-info: 'vendor info' + /pets: {x-vendor-method: {}, get: {x-vendor-operation-property: {}, description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{x-vendor-parameter-property: {}, name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, x-vendor-operation-response-property: {}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {x-vendor-model-property: {}, required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/complexArrayResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/complexArrayResponse.yaml new file mode 100644 index 0000000000..bc5ce95341 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/complexArrayResponse.yaml @@ -0,0 +1,4 @@ +description: 'A complex object array response' +schema: + type: array + items: {$ref: VeryComplexType} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/dateTimeResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/dateTimeResponse.yaml new file mode 100644 index 0000000000..9bc3e8043b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/dateTimeResponse.yaml @@ -0,0 +1,4 @@ +description: 'A date-time response' +schema: + type: string + format: date-time diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/int32Response.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/int32Response.yaml new file mode 100644 index 0000000000..e4456c9fe8 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/int32Response.yaml @@ -0,0 +1,4 @@ +description: 'A simple string response' +schema: + type: integer + format: int32 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/int64Response.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/int64Response.yaml new file mode 100644 index 0000000000..ca58b2a5f8 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/int64Response.yaml @@ -0,0 +1,4 @@ +description: 'A simple string response' +schema: + type: integer + format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/multipleResponses.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/multipleResponses.yaml new file mode 100644 index 0000000000..4cd1312c51 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/multipleResponses.yaml @@ -0,0 +1,8 @@ +'200': + description: 'simple string response' + schema: {type: string} +'201': + description: 'object created' +default: + description: oops + schema: {type: integer, format: int32} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringArrayResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringArrayResponse.yaml new file mode 100644 index 0000000000..cab5fad8c6 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringArrayResponse.yaml @@ -0,0 +1,4 @@ +description: 'A string array response' +schema: + type: array + items: {type: string} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringResponse.yaml new file mode 100644 index 0000000000..61a25e5109 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringResponse.yaml @@ -0,0 +1,3 @@ +description: 'A simple string response' +schema: + type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringResponseWithHeader.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringResponseWithHeader.yaml new file mode 100644 index 0000000000..77c2c75618 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/stringResponseWithHeader.yaml @@ -0,0 +1,6 @@ +description: 'A simple string response' +schema: + type: string +headers: + is-dog: {type: boolean} + is-cat: {type: boolean} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/voidResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/voidResponse.yaml new file mode 100644 index 0000000000..f2aa5e1241 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/responses/voidResponse.yaml @@ -0,0 +1 @@ +description: 'object created' diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/1/2/3/4/swagger.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/1/2/3/4/swagger.yaml new file mode 100644 index 0000000000..dcaf3ff806 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/1/2/3/4/swagger.yaml @@ -0,0 +1,42 @@ +swagger: '2.0' +info: + title: Something + contact: + name: Somebody + url: https://url.com + email: email@url.com + description: Something + version: v1 +host: security.sonusnet.com +schemes: +- https +- http +basePath: /api +produces: +- application/json +- plain/text + +paths: + /whatnot: + get: + description: Get something + responses: + 200: + description: The something + schema: + $ref: '#/definitions/Something' + 500: + description: Oops + +definitions: + Something: + description: A collection of service events + type: object + properties: + page: + $ref: '../../../../shared/definitions/page.yaml#/definitions/Page' + something: + #type: array + #description: An array of something + #items: + $ref: '../../../../shared/something.yaml#/definitions/Something' diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/shared/definitions/page.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/shared/definitions/page.yaml new file mode 100644 index 0000000000..29355d42d1 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/shared/definitions/page.yaml @@ -0,0 +1,18 @@ +definitions: + Page: + description: A description of a paged result + type: object + properties: + page: + type: integer + description: the page that was requested + pages: + type: integer + description: the total number of pages available + total_items: + type: integer + description: the total number of items available + format: int64 + page_items: + type: integer + description: the number of items per page requested diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/shared/something.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/shared/something.yaml new file mode 100644 index 0000000000..f5f2e39197 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/swagger/shared/something.yaml @@ -0,0 +1,44 @@ +swagger: '2.0' +info: + title: Something definitions + contact: + name: Somebody + url: https://url.com + email: email@url.com + description: Something + version: v1 +host: security.sonusnet.com +schemes: +- https +- http +basePath: /api/something/definitions +produces: +- application/json +- plain/text + +paths: + /shared: + get: + operationId: Get + tags: + - Shared + responses: + 200: + description: OK + schema: + properties: + name: + type: string + +definitions: + Something: + description: Something + type: object + properties: + p1: + type: string + description: A string + p2: + type: integer + description: An integer + diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/.gitkeep b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithArrayRef.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithArrayRef.yaml new file mode 100644 index 0000000000..b32a35901d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithArrayRef.yaml @@ -0,0 +1,5 @@ +required: + - id +properties: + id: {type: integer, format: int64} + children: {type: array, items: {$ref: Person}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithComposition.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithComposition.yaml new file mode 100644 index 0000000000..f0ea5e80f2 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithComposition.yaml @@ -0,0 +1,5 @@ +definitions: + Cat: {description: 'A representation of a cat', allOf: [{$ref: '#/models/Pet'}, {properties: {huntingSkill: {type: string, description: 'The measured skill for hunting', default: lazy, enum: [clueless, lazy, adventerous, aggressive]}}, required: [huntingSkill]}]} + Dog: {description: 'A representation of a dog', allOf: [{$ref: '#/models/Pet'}, {properties: {packSize: {type: integer, format: int32, description: 'the size of the pack the dog is from', default: 0}}, required: [name, packSize]}]} + Fish: {description: 'A representation of a fish', allOf: [{$ref: '#/models/Pet'}, {properties: {fins: {type: integer, format: int32, description: 'count of fins'}}, required: [fins]}]} + Pet: {discriminator: petType, properties: {name: {type: string}, petType: {type: string}}, required: [name, petType]} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithDateTimeMap.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithDateTimeMap.yaml new file mode 100644 index 0000000000..653cbd1825 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithDateTimeMap.yaml @@ -0,0 +1,4 @@ +description: 'true' +additionalProperties: + type: string + format: date-time diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithExamples.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithExamples.yaml new file mode 100644 index 0000000000..0252ec176c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithExamples.yaml @@ -0,0 +1,3 @@ +definitions: + Pet: {properties: {name: {type: string}}, required: [name]} + Dog: {properties: {id: {type: integer, format: int64}, name: {type: string}}, required: [name]} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithInt32Map.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithInt32Map.yaml new file mode 100644 index 0000000000..88ab02447a --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithInt32Map.yaml @@ -0,0 +1,4 @@ +description: 'This is a Map[String, Integer]' +additionalProperties: + type: integer + format: int32 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithInt64Map.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithInt64Map.yaml new file mode 100644 index 0000000000..16c790e42d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithInt64Map.yaml @@ -0,0 +1,4 @@ +description: 'true' +additionalProperties: + type: integer + format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithMultipleProperties.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithMultipleProperties.yaml new file mode 100644 index 0000000000..f69d27ef29 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithMultipleProperties.yaml @@ -0,0 +1,14 @@ +description: 'true' +properties: + booleanValue: {type: boolean} + byteValue: {type: string, format: byte} + dateTimeValue: {type: string, format: date-time} + int32Value: {type: integer, format: int32} + int64Value: {type: integer, format: int64} + stringValue: {type: string} + booleanArrayValue: {type: array, items: {type: boolean}} + byteArrayValue: {type: array, items: {type: string, format: byte}} + dateTimeArrayValue: {type: array, items: {type: string, format: date-time}} + int32ArrayValue: {type: array, items: {type: integer, format: int32}} + int64ArrayValue: {type: array, items: {type: integer, format: int64}} + stringArrayValue: {type: array, items: {type: string}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithObjectMap.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithObjectMap.yaml new file mode 100644 index 0000000000..e712e0f220 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithObjectMap.yaml @@ -0,0 +1,9 @@ +description: "This is a Map[String, { id: Long, name: String}]" +additionalProperties: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithPrimitiveArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithPrimitiveArray.yaml new file mode 100644 index 0000000000..0837bad52b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithPrimitiveArray.yaml @@ -0,0 +1,5 @@ +required: + - id +properties: + id: {type: integer, format: int64} + childrensAges: {type: array, items: {type: integer, format: int32}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithStringProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithStringProperty.yaml new file mode 100644 index 0000000000..a17d21e5a1 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithStringProperty.yaml @@ -0,0 +1,3 @@ +description: 'true' +properties: + name: {type: string} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithXmlAttributes.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithXmlAttributes.yaml new file mode 100644 index 0000000000..2176983f89 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/modelWithXmlAttributes.yaml @@ -0,0 +1,6 @@ +description: 'this model serves xml and json structures' +xml: + name: XMLModel +properties: + id: {type: integer, format: int64, xml: {attribute: true, namespace: ns1, prefix: urn1}} + items: {type: array, items: {type: string}, xml: {wrapped: true}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/models.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/models.yaml new file mode 100644 index 0000000000..71f8efeb42 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/models.yaml @@ -0,0 +1,2 @@ +definitions: + Pet: {properties: {name: {type: string}}, required: [name]} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/multipleModels.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/multipleModels.yaml new file mode 100644 index 0000000000..0252ec176c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/multipleModels.yaml @@ -0,0 +1,3 @@ +definitions: + Pet: {properties: {name: {type: string}}, required: [name]} + Dog: {properties: {id: {type: integer, format: int64}, name: {type: string}}, required: [name]} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithBooleanArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithBooleanArray.yaml new file mode 100644 index 0000000000..aa02d0e742 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithBooleanArray.yaml @@ -0,0 +1,3 @@ +type: array +items: + type: boolean diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithByteArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithByteArray.yaml new file mode 100644 index 0000000000..f31b350362 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithByteArray.yaml @@ -0,0 +1,4 @@ +type: array +items: + type: string + format: byte diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithComplexArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithComplexArray.yaml new file mode 100644 index 0000000000..69e0b17658 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithComplexArray.yaml @@ -0,0 +1,3 @@ +type: array +items: + $ref: ComplexType diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithDateTimeArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithDateTimeArray.yaml new file mode 100644 index 0000000000..6efef25d8f --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithDateTimeArray.yaml @@ -0,0 +1,4 @@ +type: array +items: + type: string + format: date-time diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithInt32Array.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithInt32Array.yaml new file mode 100644 index 0000000000..26fd271b00 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithInt32Array.yaml @@ -0,0 +1,4 @@ +type: array +items: + type: integer + format: int32 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithInt64Array.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithInt64Array.yaml new file mode 100644 index 0000000000..e800895ebc --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithInt64Array.yaml @@ -0,0 +1,4 @@ +type: array +items: + type: integer + format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithRef.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithRef.yaml new file mode 100644 index 0000000000..d78956949e --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithRef.yaml @@ -0,0 +1,3 @@ +$ref: Foo +description: 'a boolean' +readOnly: true diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithStringArray.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithStringArray.yaml new file mode 100644 index 0000000000..3a9108235c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/propertyWithStringArray.yaml @@ -0,0 +1,3 @@ +type: array +items: + type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleBooleanProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleBooleanProperty.yaml new file mode 100644 index 0000000000..9d1e27382b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleBooleanProperty.yaml @@ -0,0 +1,3 @@ +type: boolean +description: 'a boolean' +readOnly: true diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleByteProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleByteProperty.yaml new file mode 100644 index 0000000000..6af2139f99 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleByteProperty.yaml @@ -0,0 +1,2 @@ +type: string +format: byte diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleDateTimeProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleDateTimeProperty.yaml new file mode 100644 index 0000000000..407b1d7e8f --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleDateTimeProperty.yaml @@ -0,0 +1,2 @@ +type: string +format: date-time diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleInt32Property.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleInt32Property.yaml new file mode 100644 index 0000000000..8ed513dba0 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleInt32Property.yaml @@ -0,0 +1,2 @@ +type: integer +format: int32 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleInt64Property.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleInt64Property.yaml new file mode 100644 index 0000000000..69f359f3fd --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleInt64Property.yaml @@ -0,0 +1,2 @@ +type: integer +format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleStringProperty.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleStringProperty.yaml new file mode 100644 index 0000000000..5c21d88b9e --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/models/properties/simpleStringProperty.yaml @@ -0,0 +1 @@ +type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/cascadingSchemes.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/cascadingSchemes.yaml new file mode 100644 index 0000000000..d108027742 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/cascadingSchemes.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{petId}': {get: {description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}, schemes: [https]}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/commonParameters.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/commonParameters.yaml new file mode 100644 index 0000000000..9851b7448c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/commonParameters.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{id}': {parameters: [{name: id, in: path, description: 'ID of pet to use', required: true, type: array, items: {type: string}, collectionFormat: csv}], get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, produces: [application/json, text/html], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/multipleMimeTypes.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/multipleMimeTypes.yaml new file mode 100644 index 0000000000..23bdc2d2a3 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/multipleMimeTypes.yaml @@ -0,0 +1,32 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - 'text/plain; charset=utf-8' + - application/json + - application/vnd.github+json + - application/vnd.github.v3+json + - application/vnd.github.v3.raw+json + - application/vnd.github.v3.text+json + - application/vnd.github.v3.html+json + - application/vnd.github.v3.full+json + - application/vnd.github.v3.diff + - application/vnd.github.v3.patch +produces: + - application/json + - application/xml +paths: + '/pets/{id}': {parameters: [{name: id, in: path, description: 'ID of pet to use', required: true, type: array, items: {type: string}, collectionFormat: csv}], get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, produces: [application/json, text/html], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/operationWithTags.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/operationWithTags.yaml new file mode 100644 index 0000000000..a3c85b26a3 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/operationWithTags.yaml @@ -0,0 +1,14 @@ +description: 'Returns a pet based on ID' +summary: 'Find pet by ID' +operationId: getPetsById +tags: + - foo + - bar +produces: + - application/json + - text/html +parameters: + - {name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: integer, format: int64} +responses: + '200': {description: 'a pet to be returned', schema: {$ref: Pet}} + default: {description: 'Unexpected error', schema: {$ref: ErrorModel}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/stringPathAndBoolQueryParamResource.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/stringPathAndBoolQueryParamResource.yaml new file mode 100644 index 0000000000..a00b8c469c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/stringPathAndBoolQueryParamResource.yaml @@ -0,0 +1,12 @@ +description: 'Returns a pet based on ID' +summary: 'Find pet by ID' +operationId: getPetsById +produces: + - application/json + - text/html +parameters: + - {name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: integer, format: int64} + - {name: includeDetails, in: query, description: 'include details in response', required: true, type: boolean} +responses: + '200': {description: 'a pet to be returned', schema: {$ref: Pet}} + default: {description: 'Unexpected error', schema: {$ref: ErrorModel}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/stringPathParamResource.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/stringPathParamResource.yaml new file mode 100644 index 0000000000..8c46cc7ee8 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/operations/stringPathParamResource.yaml @@ -0,0 +1,12 @@ +description: 'Returns a pet based on ID' +summary: 'Find pet by ID' +operationId: getPetsById +produces: + - application/json + - text/html +parameters: + - {name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: integer, format: int64} +responses: + '200': {description: fun, schema: {$ref: Pet}} + '400': {description: 'Invalid ID supplied <= this is purely for documentation', schema: {$ref: ErrorModel}} + default: {description: 'Unexpected error', schema: {$ref: ErrorModel}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyComplexArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyComplexArrayParameter.yaml new file mode 100644 index 0000000000..511f8dc2b3 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyComplexArrayParameter.yaml @@ -0,0 +1,8 @@ +name: user +in: body +description: 'user to add to the system' +required: true +schema: + type: array + items: {type: string} + format: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyComplexParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyComplexParameter.yaml new file mode 100644 index 0000000000..13f8fd171b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyComplexParameter.yaml @@ -0,0 +1,6 @@ +name: user +in: body +description: 'user to add to the system' +required: true +schema: + $ref: User diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyInt64Parameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyInt64Parameter.yaml new file mode 100644 index 0000000000..a270d94cb5 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyInt64Parameter.yaml @@ -0,0 +1,7 @@ +name: id +in: body +description: 'id to add' +required: true +schema: + type: integer + format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyStringArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyStringArrayParameter.yaml new file mode 100644 index 0000000000..7d88b10dc9 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyStringArrayParameter.yaml @@ -0,0 +1,7 @@ +name: user +in: body +description: 'user to add to the system' +required: true +schema: + type: array + items: {type: string} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyStringParameter.yaml new file mode 100644 index 0000000000..7fe9dbd1e0 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/bodyStringParameter.yaml @@ -0,0 +1,6 @@ +name: user +in: body +description: 'user to add to the system' +required: true +schema: + type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataComplexParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataComplexParameter.yaml new file mode 100644 index 0000000000..b49dd9e3d6 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataComplexParameter.yaml @@ -0,0 +1,5 @@ +name: firstName +in: formData +description: 'users first name' +required: true +$ref: Nothing diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataInt64Parameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataInt64Parameter.yaml new file mode 100644 index 0000000000..0faaa7f62d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataInt64Parameter.yaml @@ -0,0 +1,6 @@ +name: id +in: formData +description: 'username to fetch' +required: true +type: integer +format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataStringArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataStringArrayParameter.yaml new file mode 100644 index 0000000000..f6534662a5 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataStringArrayParameter.yaml @@ -0,0 +1,7 @@ +name: user +in: formData +description: 'user to add to the system' +required: true +type: array +items: + type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataStringParameter.yaml new file mode 100644 index 0000000000..43411cf047 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/formDataStringParameter.yaml @@ -0,0 +1,5 @@ +name: firstName +in: formData +description: 'users first name' +required: true +type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerInt64ArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerInt64ArrayParameter.yaml new file mode 100644 index 0000000000..87ec99cabc --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerInt64ArrayParameter.yaml @@ -0,0 +1,9 @@ +name: token +in: header +description: 'token to be passed as a header' +required: true +type: array +items: + type: integer + format: int64 +collectionFormat: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerStringArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerStringArrayParameter.yaml new file mode 100644 index 0000000000..70e0a0a680 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerStringArrayParameter.yaml @@ -0,0 +1,8 @@ +name: token +in: header +description: 'token to be passed as a header' +required: true +type: array +items: + type: string +collectionFormat: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerStringParameter.yaml new file mode 100644 index 0000000000..ac99c2f62c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/headerStringParameter.yaml @@ -0,0 +1,5 @@ +name: token +in: header +description: 'token to be passed as a header' +required: true +type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathInt64Parameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathInt64Parameter.yaml new file mode 100644 index 0000000000..3bd860aacd --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathInt64Parameter.yaml @@ -0,0 +1,6 @@ +name: id +in: path +description: 'username to fetch' +required: true +type: integer +format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathStringArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathStringArrayParameter.yaml new file mode 100644 index 0000000000..ebb24a7e22 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathStringArrayParameter.yaml @@ -0,0 +1,8 @@ +name: usernames +in: path +description: 'usernames to pass' +required: true +type: array +items: + type: string +collectionFormat: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathStringParameter.yaml new file mode 100644 index 0000000000..2cb4fb2eec --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/pathStringParameter.yaml @@ -0,0 +1,5 @@ +name: username +in: path +description: 'username to fetch' +required: true +type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryInt64ArrayParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryInt64ArrayParameter.yaml new file mode 100644 index 0000000000..453e24f5d1 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryInt64ArrayParameter.yaml @@ -0,0 +1,9 @@ +name: id +in: query +description: 'ID of the object to fetch' +required: true +type: array +items: + type: integer + format: int64 +collectionFormat: csv diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryStringParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryStringParameter.yaml new file mode 100644 index 0000000000..e1df685309 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryStringParameter.yaml @@ -0,0 +1,6 @@ +name: id +in: query +description: 'ID of the object to fetch' +required: true +type: integer +format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryWithComplexParameter.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryWithComplexParameter.yaml new file mode 100644 index 0000000000..80bc7951b8 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/parameters/queryWithComplexParameter.yaml @@ -0,0 +1,6 @@ +name: id +in: query +description: 'a complex object which should not validate' +required: true +schema: + $ref: Pet diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithExamplePayload.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithExamplePayload.yaml new file mode 100644 index 0000000000..9828d96050 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithExamplePayload.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{petId}': {get: {description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}, examples: {application/json: {id: 9, category: {name: domestic}, name: monster, tags: [{name: 'for sale'}], status: alive}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string, example: cat}, tag: {type: string, example: 'for sale'}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithLinkedDefinitions.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithLinkedDefinitions.yaml new file mode 100644 index 0000000000..b9b00c47f1 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithLinkedDefinitions.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{petId}': {$ref: 'https://raw.githubusercontent.com/reverb/swagger-spec/master/fixtures/v2.0/json/resources/resourceWithLinkedDefinitions_part1.json'} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithLinkedDefinitions_part1.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithLinkedDefinitions_part1.yaml new file mode 100644 index 0000000000..7d358fbf10 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithLinkedDefinitions_part1.yaml @@ -0,0 +1,7 @@ +get: + description: 'Returns a pet based on ID' + summary: 'Find pet by ID' + operationId: getPetsById + produces: [application/json, text/html] + parameters: [{name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}] + responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithRelativeHost.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithRelativeHost.yaml new file mode 100644 index 0000000000..744aa72e9a --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/resourceWithRelativeHost.yaml @@ -0,0 +1,22 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{id}': {parameters: [{name: id, in: path, description: 'ID of pet to use', required: true, type: array, items: {type: string}, collectionFormat: csv}], get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, produces: [application/json, text/html], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/reusableParameters.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/reusableParameters.yaml new file mode 100644 index 0000000000..1d258d0827 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/reusableParameters.yaml @@ -0,0 +1,26 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{id}': {get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, parameters: [{$ref: '#/parameters/skipParam'}, {$ref: '#/parameters/limitParam'}], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +parameters: + skipParam: {name: skip, in: query, description: 'number of items to skip', required: true, type: integer, format: int32} + limitParam: {name: limit, in: query, description: 'max records to return', required: true, type: integer, format: int32} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/securityExample.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/securityExample.yaml new file mode 100644 index 0000000000..007d26db43 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/securityExample.yaml @@ -0,0 +1,29 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +security: + - {githubAccessCode: [user, gist]} + - {internalApiKey: []} +paths: + '/pets/{id}': {parameters: [{name: id, in: path, description: 'ID of pet to use', required: true, type: array, items: {type: string}, collectionFormat: csv}], get: {description: 'Returns pets based on ID', summary: 'Find pets by ID', operationId: getPetsById, security: [{githubAuth: ['user:read', 'user:write']}, {internalApiKey: []}], produces: [application/json, text/html], responses: {'200': {description: 'pet response', schema: {type: array, items: {$ref: Pet}}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +securityDefinitions: + githubAccessCode: {type: oauth2, scopes: {user: 'Grants read/write access to profile info only. Note that this scope includes user:email and user:follow.', 'user:email': 'Grants read access to a user’s email addresses.', 'user:follow': 'Grants access to follow or unfollow other users.', public_repo: 'Grants read/write access to code, commit statuses, and deployment statuses for public repositories and organizations.', repo: 'Grants read/write access to code, commit statuses, and deployment statuses for public and private repositories and organizations.', repo_deployment: 'Grants access to deployment statuses for public and private repositories. This scope is only necessary to grant other users or services access to deployment statuses, without granting access to the code.', 'repo:status': 'Grants read/write access to public and private repository commit statuses. This scope is only necessary to grant other users or services access to private repository commit statuses without granting access to the code.', delete_repo: 'Grants access to delete adminable repositories.', notifications: 'Grants read access to a user’s notifications. repo also provides this access.', gist: 'Grants write access to gists.', 'read:repo_hook': 'Grants read and ping access to hooks in public or private repositories.', 'write:repo_hook': 'Grants read, write, and ping access to hooks in public or private repositories.', 'admin:repo_hook': 'Grants read, write, ping, and delete access to hooks in public or private repositories.', 'read:org': 'Read-only access to organization, teams, and membership.', 'write:org': 'Publicize and unpublicize organization membership.', 'admin:org': 'Fully manage organization, teams, and memberships.', 'read:public_key': 'List and view details for public keys.', 'write:public_key': 'Create, list, and view details for public keys.', 'admin:public_key': 'Fully manage public keys.'}, flow: accessCode, authorizationUrl: 'https://github.com/login/oauth/authorize', tokenUrl: 'https://github.com/login/oauth/access_token'} + petstoreImplicit: {type: oauth2, scopes: {user: 'Grants read/write access to profile info only. Note that this scope includes user:email and user:follow.', 'user:email': 'Grants read access to a user’s email addresses.', 'user:follow': 'Grants access to follow or unfollow other users.', public_repo: 'Grants read/write access to code, commit statuses, and deployment statuses for public repositories and organizations.', repo: 'Grants read/write access to code, commit statuses, and deployment statuses for public and private repositories and organizations.', repo_deployment: 'Grants access to deployment statuses for public and private repositories. This scope is only necessary to grant other users or services access to deployment statuses, without granting access to the code.', 'repo:status': 'Grants read/write access to public and private repository commit statuses. This scope is only necessary to grant other users or services access to private repository commit statuses without granting access to the code.', delete_repo: 'Grants access to delete adminable repositories.', notifications: 'Grants read access to a user’s notifications. repo also provides this access.', gist: 'Grants write access to gists.', 'read:repo_hook': 'Grants read and ping access to hooks in public or private repositories.', 'write:repo_hook': 'Grants read, write, and ping access to hooks in public or private repositories.', 'admin:repo_hook': 'Grants read, write, ping, and delete access to hooks in public or private repositories.', 'read:org': 'Read-only access to organization, teams, and membership.', 'write:org': 'Publicize and unpublicize organization membership.', 'admin:org': 'Fully manage organization, teams, and memberships.', 'read:public_key': 'List and view details for public keys.', 'write:public_key': 'Create, list, and view details for public keys.', 'admin:public_key': 'Fully manage public keys.'}, flow: implicit, authorizationUrl: 'http://petstore.swagger.wordnik.com/oauth/dialog'} + internalApiKey: {type: apiKey, in: header, name: api_key} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/stringPathParamResource.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/stringPathParamResource.yaml new file mode 100644 index 0000000000..a4a83fea0f --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/stringPathParamResource.yaml @@ -0,0 +1,23 @@ +swagger: '2.0' +info: + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + '/pets/{petId}': {get: {description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/taggedResource.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/taggedResource.yaml new file mode 100644 index 0000000000..1b8620e52c --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/taggedResource.yaml @@ -0,0 +1,29 @@ +swagger: '2.0' +x-reverb: + addAnythingYouWant: true +info: + x-reverb-info: 'this is an example' + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +tags: + - {name: pets} +paths: + x-reverb-path-info: 'vendor info' + /pets: {x-vendor-method: {}, get: {x-vendor-operation-property: {}, description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{x-vendor-parameter-property: {}, name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, x-vendor-operation-response-property: {}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {x-vendor-model-property: {}, required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/vendorExtensionExamples.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/vendorExtensionExamples.yaml new file mode 100644 index 0000000000..59bba0f3d0 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/resources/vendorExtensionExamples.yaml @@ -0,0 +1,27 @@ +swagger: '2.0' +x-reverb: + addAnythingYouWant: true +info: + x-reverb-info: 'this is an example' + version: 1.0.9-abcd + title: 'Swagger Sample API' + description: 'A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification' + termsOfService: 'http://helloreverb.com/terms/' + contact: {name: 'wordnik api team', url: 'http://developer.wordnik.com'} + license: {name: 'Creative Commons 4.0 International', url: 'http://creativecommons.org/licenses/by/4.0/'} +host: my.api.com +basePath: /v1 +schemes: + - http + - https +consumes: + - application/json +produces: + - application/json + - application/xml +paths: + x-reverb-path-info: 'vendor info' + /pets: {x-vendor-method: {}, get: {x-vendor-operation-property: {}, description: 'Returns a pet based on ID', summary: 'Find pet by ID', operationId: getPetsById, produces: [application/json, text/html], parameters: [{x-vendor-parameter-property: {}, name: petId, in: path, description: 'ID of pet that needs to be fetched', required: true, type: array, items: {type: string}, collectionFormat: csv}], responses: {'200': {description: 'pet response', schema: {$ref: Pet}}, x-vendor-operation-response-property: {}, default: {description: 'error payload', schema: {$ref: ErrorModel}}}}} +definitions: + Pet: {x-vendor-model-property: {}, required: [name], properties: {name: {type: string}, tag: {type: string}}} + ErrorModel: {required: [code, message], properties: {code: {type: integer, format: int32}, message: {type: string}}} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/complexArrayResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/complexArrayResponse.yaml new file mode 100644 index 0000000000..bc5ce95341 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/complexArrayResponse.yaml @@ -0,0 +1,4 @@ +description: 'A complex object array response' +schema: + type: array + items: {$ref: VeryComplexType} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/dateTimeResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/dateTimeResponse.yaml new file mode 100644 index 0000000000..9bc3e8043b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/dateTimeResponse.yaml @@ -0,0 +1,4 @@ +description: 'A date-time response' +schema: + type: string + format: date-time diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/int32Response.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/int32Response.yaml new file mode 100644 index 0000000000..e4456c9fe8 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/int32Response.yaml @@ -0,0 +1,4 @@ +description: 'A simple string response' +schema: + type: integer + format: int32 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/int64Response.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/int64Response.yaml new file mode 100644 index 0000000000..ca58b2a5f8 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/int64Response.yaml @@ -0,0 +1,4 @@ +description: 'A simple string response' +schema: + type: integer + format: int64 diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/multipleResponses.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/multipleResponses.yaml new file mode 100644 index 0000000000..4cd1312c51 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/multipleResponses.yaml @@ -0,0 +1,8 @@ +'200': + description: 'simple string response' + schema: {type: string} +'201': + description: 'object created' +default: + description: oops + schema: {type: integer, format: int32} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringArrayResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringArrayResponse.yaml new file mode 100644 index 0000000000..cab5fad8c6 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringArrayResponse.yaml @@ -0,0 +1,4 @@ +description: 'A string array response' +schema: + type: array + items: {type: string} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringResponse.yaml new file mode 100644 index 0000000000..61a25e5109 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringResponse.yaml @@ -0,0 +1,3 @@ +description: 'A simple string response' +schema: + type: string diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringResponseWithHeader.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringResponseWithHeader.yaml new file mode 100644 index 0000000000..77c2c75618 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/stringResponseWithHeader.yaml @@ -0,0 +1,6 @@ +description: 'A simple string response' +schema: + type: string +headers: + is-dog: {type: boolean} + is-cat: {type: boolean} diff --git a/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/voidResponse.yaml b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/voidResponse.yaml new file mode 100644 index 0000000000..f2aa5e1241 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fixtures/yaml/yaml/responses/voidResponse.yaml @@ -0,0 +1 @@ +description: 'object created' diff --git a/vendor/github.com/go-openapi/loads/fmts/fixture_test.go b/vendor/github.com/go-openapi/loads/fmts/fixture_test.go new file mode 100644 index 0000000000..6213ca57c4 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fmts/fixture_test.go @@ -0,0 +1,298 @@ +// 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 fmts + +import ( + "encoding/json" + "io/ioutil" + "path/filepath" + "strings" + "testing" + + "github.com/go-openapi/spec" + "github.com/stretchr/testify/assert" +) + +var extensions = []string{"json"} + +func assertSpecJSON(t testing.TB, specJSON []byte) bool { + var expected map[string]interface{} + if !assert.NoError(t, json.Unmarshal(specJSON, &expected)) { + return false + } + + obj := spec.Swagger{} + if !assert.NoError(t, json.Unmarshal(specJSON, &obj)) { + return false + } + + cb, err := json.MarshalIndent(obj, "", " ") + if assert.NoError(t, err) { + return false + } + var actual map[string]interface{} + if !assert.NoError(t, json.Unmarshal(cb, &actual)) { + return false + } + return assertSpecMaps(t, actual, expected) +} + +func assertSpecMaps(t testing.TB, actual, expected map[string]interface{}) bool { + res := true + if id, ok := expected["id"]; ok { + res = assert.Equal(t, id, actual["id"]) + } + res = res && assert.Equal(t, expected["consumes"], actual["consumes"]) + res = res && assert.Equal(t, expected["produces"], actual["produces"]) + res = res && assert.Equal(t, expected["schemes"], actual["schemes"]) + res = res && assert.Equal(t, expected["swagger"], actual["swagger"]) + res = res && assert.Equal(t, expected["info"], actual["info"]) + res = res && assert.Equal(t, expected["host"], actual["host"]) + res = res && assert.Equal(t, expected["basePath"], actual["basePath"]) + res = res && assert.Equal(t, expected["paths"], actual["paths"]) + res = res && assert.Equal(t, expected["definitions"], actual["definitions"]) + res = res && assert.Equal(t, expected["responses"], actual["responses"]) + res = res && assert.Equal(t, expected["securityDefinitions"], actual["securityDefinitions"]) + res = res && assert.Equal(t, expected["tags"], actual["tags"]) + res = res && assert.Equal(t, expected["externalDocs"], actual["externalDocs"]) + res = res && assert.Equal(t, expected["x-some-extension"], actual["x-some-extension"]) + res = res && assert.Equal(t, expected["x-schemes"], actual["x-schemes"]) + + return res +} + +func roundTripTest(t *testing.T, fixtureType, extension, fileName string, schema interface{}) bool { + if extension == "yaml" { + return roundTripTestYAML(t, fixtureType, fileName, schema) + } + return roundTripTestJSON(t, fixtureType, fileName, schema) +} + +func roundTripTestJSON(t *testing.T, fixtureType, fileName string, schema interface{}) bool { + specName := strings.TrimSuffix(fileName, filepath.Ext(fileName)) + t.Logf("verifying %s JSON fixture %q", fixtureType, specName) + + b, err := ioutil.ReadFile(fileName) + if !assert.NoError(t, err) { + return false + } + + var expected map[string]interface{} + if !assert.NoError(t, json.Unmarshal(b, &expected)) { + return false + } + + if !assert.NoError(t, json.Unmarshal(b, schema)) { + return false + } + + cb, err := json.MarshalIndent(schema, "", " ") + if !assert.NoError(t, err) { + return false + } + + var actual map[string]interface{} + if !assert.NoError(t, json.Unmarshal(cb, &actual)) { + return false + } + + return assert.EqualValues(t, expected, actual) +} + +func roundTripTestYAML(t *testing.T, fixtureType, fileName string, schema interface{}) bool { + specName := strings.TrimSuffix(fileName, filepath.Ext(fileName)) + t.Logf("verifying %s YAML fixture %q", fixtureType, specName) + + b, err := YAMLDoc(fileName) + if !assert.NoError(t, err) { + return false + } + + var expected map[string]interface{} + if !assert.NoError(t, json.Unmarshal(b, &expected)) { + return false + } + + if !assert.NoError(t, json.Unmarshal(b, schema)) { + return false + } + + cb, err := json.MarshalIndent(schema, "", " ") + if !assert.NoError(t, err) { + return false + } + + var actual map[string]interface{} + if !assert.NoError(t, json.Unmarshal(cb, &actual)) { + return false + } + + return assert.EqualValues(t, expected, actual) +} + +func TestPropertyFixtures(t *testing.T) { + for _, extension := range extensions { + path := filepath.Join("..", "fixtures", extension, "models", "properties") + files, err := ioutil.ReadDir(path) + if err != nil { + t.Fatal(err) + } + + // for _, f := range files { + // roundTripTest(t, "property", extension, filepath.Join(path, f.Name()), &Schema{}) + // } + f := files[0] + roundTripTest(t, "property", extension, filepath.Join(path, f.Name()), &spec.Schema{}) + } +} + +func TestAdditionalPropertiesWithObject(t *testing.T) { + schema := new(spec.Schema) + b, err := YAMLDoc("../fixtures/yaml/models/modelWithObjectMap.yaml") + if assert.NoError(t, err) { + var expected map[string]interface{} + if assert.NoError(t, json.Unmarshal(b, &expected)) && assert.NoError(t, json.Unmarshal(b, schema)) { + cb, err := json.MarshalIndent(schema, "", " ") + if assert.NoError(t, err) { + var actual map[string]interface{} + if assert.NoError(t, json.Unmarshal(cb, &actual)) { + assert.Equal(t, expected, actual) + } + } + } + } + +} + +func TestModelFixtures(t *testing.T) { + path := filepath.Join("..", "fixtures", "json", "models") + files, err := ioutil.ReadDir(path) + if err != nil { + t.Fatal(err) + } + specs := []string{"modelWithObjectMap", "models", "modelWithComposition", "modelWithExamples", "multipleModels"} +FILES: + for _, f := range files { + if f.IsDir() { + continue + } + for _, sp := range specs { + if strings.HasPrefix(f.Name(), sp) { + roundTripTest(t, "model", "json", filepath.Join(path, f.Name()), &spec.Schema{}) + continue FILES + } + } + //fmt.Println("trying", f.Name()) + roundTripTest(t, "model", "json", filepath.Join(path, f.Name()), &spec.Schema{}) + } + path = filepath.Join("..", "fixtures", "yaml", "models") + files, err = ioutil.ReadDir(path) + if err != nil { + t.Fatal(err) + } +YAMLFILES: + for _, f := range files { + if f.IsDir() { + continue + } + for _, sp := range specs { + if strings.HasPrefix(f.Name(), sp) { + roundTripTest(t, "model", "yaml", filepath.Join(path, f.Name()), &spec.Schema{}) + continue YAMLFILES + } + } + // fmt.Println("trying", f.Name()) + roundTripTest(t, "model", "yaml", filepath.Join(path, f.Name()), &spec.Schema{}) + } +} + +func TestParameterFixtures(t *testing.T) { + path := filepath.Join("..", "fixtures", "json", "resources", "parameters") + files, err := ioutil.ReadDir(path) + if err != nil { + t.Fatal(err) + } + + for _, f := range files { + roundTripTest(t, "parameter", "json", filepath.Join(path, f.Name()), &spec.Parameter{}) + } +} + +func TestOperationFixtures(t *testing.T) { + path := filepath.Join("..", "fixtures", "json", "resources", "operations") + files, err := ioutil.ReadDir(path) + if err != nil { + t.Fatal(err) + } + + for _, f := range files { + roundTripTest(t, "operation", "json", filepath.Join(path, f.Name()), &spec.Operation{}) + } +} + +func TestResponseFixtures(t *testing.T) { + path := filepath.Join("..", "fixtures", "json", "responses") + files, err := ioutil.ReadDir(path) + if err != nil { + t.Fatal(err) + } + + for _, f := range files { + if !strings.HasPrefix(f.Name(), "multiple") { + roundTripTest(t, "response", "json", filepath.Join(path, f.Name()), &spec.Response{}) + } else { + roundTripTest(t, "responses", "json", filepath.Join(path, f.Name()), &spec.Responses{}) + } + } +} + +func TestResourcesFixtures(t *testing.T) { + path := filepath.Join("..", "fixtures", "json", "resources") + files, err := ioutil.ReadDir(path) + if err != nil { + t.Fatal(err) + } + pathItems := []string{"resourceWithLinkedDefinitions_part1"} + toSkip := []string{} +FILES: + for _, f := range files { + if f.IsDir() { + continue + } + for _, ts := range toSkip { + if strings.HasPrefix(f.Name(), ts) { + t.Log("verifying resource" + strings.TrimSuffix(f.Name(), filepath.Ext(f.Name()))) + b, err := ioutil.ReadFile(filepath.Join(path, f.Name())) + if assert.NoError(t, err) { + assertSpecJSON(t, b) + } + continue FILES + } + } + for _, pi := range pathItems { + if strings.HasPrefix(f.Name(), pi) { + roundTripTest(t, "path items", "json", filepath.Join(path, f.Name()), &spec.PathItem{}) + continue FILES + } + } + + t.Logf("verifying resource %q", strings.TrimSuffix(f.Name(), filepath.Ext(f.Name()))) + b2, err := ioutil.ReadFile(filepath.Join(path, f.Name())) + if assert.NoError(t, err) { + assertSpecJSON(t, b2) + } + + } +} diff --git a/vendor/github.com/go-openapi/loads/fmts/yaml.go b/vendor/github.com/go-openapi/loads/fmts/yaml.go new file mode 100644 index 0000000000..1cef2ac22b --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fmts/yaml.go @@ -0,0 +1,30 @@ +// 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 fmts + +import "github.com/go-openapi/swag" + +var ( + // YAMLMatcher matches yaml + YAMLMatcher = swag.YAMLMatcher + // YAMLToJSON converts YAML unmarshaled data into json compatible data + YAMLToJSON = swag.YAMLToJSON + // BytesToYAMLDoc converts raw bytes to a map[string]interface{} + BytesToYAMLDoc = swag.BytesToYAMLDoc + // YAMLDoc loads a yaml document from either http or a file and converts it to json + YAMLDoc = swag.YAMLDoc + // YAMLData loads a yaml document from either http or a file + YAMLData = swag.YAMLData +) diff --git a/vendor/github.com/go-openapi/loads/fmts/yaml_test.go b/vendor/github.com/go-openapi/loads/fmts/yaml_test.go new file mode 100644 index 0000000000..e347805d31 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/fmts/yaml_test.go @@ -0,0 +1,445 @@ +// 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 fmts + +import ( + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "testing" + + yaml "gopkg.in/yaml.v2" + + "github.com/go-openapi/swag" + "github.com/stretchr/testify/assert" +) + +type failJSONMarhal struct { +} + +func (f failJSONMarhal) MarshalJSON() ([]byte, error) { + return nil, errors.New("expected") +} + +func TestLoadHTTPBytes(t *testing.T) { + _, err := swag.LoadFromFileOrHTTP("httx://12394:abd") + assert.Error(t, err) + + serv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.WriteHeader(http.StatusNotFound) + })) + defer serv.Close() + + _, err = swag.LoadFromFileOrHTTP(serv.URL) + assert.Error(t, err) + + ts2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.WriteHeader(http.StatusOK) + rw.Write([]byte("the content")) + })) + defer ts2.Close() + + d, err := swag.LoadFromFileOrHTTP(ts2.URL) + assert.NoError(t, err) + assert.Equal(t, []byte("the content"), d) +} + +func TestYAMLToJSON(t *testing.T) { + + sd := `--- +1: the int key value +name: a string value +'y': some value +` + var data yaml.MapSlice + yaml.Unmarshal([]byte(sd), &data) + + d, err := YAMLToJSON(data) + if assert.NoError(t, err) { + assert.Equal(t, `{"1":"the int key value","name":"a string value","y":"some value"}`, string(d)) + } + + data = append(data, yaml.MapItem{Key: true, Value: "the bool value"}) + d, err = YAMLToJSON(data) + assert.Error(t, err) + assert.Nil(t, d) + + data = data[:len(data)-1] + + tag := yaml.MapSlice{{Key: "name", Value: "tag name"}} + data = append(data, yaml.MapItem{Key: "tag", Value: tag}) + + d, err = YAMLToJSON(data) + assert.NoError(t, err) + assert.Equal(t, `{"1":"the int key value","name":"a string value","y":"some value","tag":{"name":"tag name"}}`, string(d)) + + tag = yaml.MapSlice{{Key: true, Value: "bool tag name"}} + data = append(data[:len(data)-1], yaml.MapItem{Key: "tag", Value: tag}) + + d, err = YAMLToJSON(data) + assert.Error(t, err) + assert.Nil(t, d) + + var lst []interface{} + lst = append(lst, "hello") + + d, err = YAMLToJSON(lst) + assert.NoError(t, err) + assert.Equal(t, []byte(`["hello"]`), []byte(d)) + + lst = append(lst, data) + + d, err = YAMLToJSON(lst) + assert.Error(t, err) + assert.Nil(t, d) + + // _, err := yamlToJSON(failJSONMarhal{}) + // assert.Error(t, err) + + _, err = BytesToYAMLDoc([]byte("- name: hello\n")) + assert.Error(t, err) + + dd, err := BytesToYAMLDoc([]byte("description: 'object created'\n")) + assert.NoError(t, err) + + d, err = YAMLToJSON(dd) + assert.NoError(t, err) + assert.Equal(t, json.RawMessage(`{"description":"object created"}`), d) +} + +func TestLoadStrategy(t *testing.T) { + + loader := func(p string) ([]byte, error) { + return []byte(yamlPetStore), nil + } + remLoader := func(p string) ([]byte, error) { + return []byte("not it"), nil + } + + ld := swag.LoadStrategy("blah", loader, remLoader) + b, _ := ld("") + assert.Equal(t, []byte(yamlPetStore), b) + + serv := httptest.NewServer(http.HandlerFunc(yamlPestoreServer)) + defer serv.Close() + + s, err := YAMLDoc(serv.URL) + assert.NoError(t, err) + assert.NotNil(t, s) + + ts2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.WriteHeader(http.StatusNotFound) + rw.Write([]byte("\n")) + })) + defer ts2.Close() + _, err = YAMLDoc(ts2.URL) + assert.Error(t, err) +} + +var yamlPestoreServer = func(rw http.ResponseWriter, r *http.Request) { + rw.WriteHeader(http.StatusOK) + rw.Write([]byte(yamlPetStore)) +} + +func TestWithYKey(t *testing.T) { + doc, err := BytesToYAMLDoc([]byte(withYKey)) + if assert.NoError(t, err) { + _, err := YAMLToJSON(doc) + if assert.Error(t, err) { + doc, err := BytesToYAMLDoc([]byte(withQuotedYKey)) + if assert.NoError(t, err) { + jsond, err := YAMLToJSON(doc) + if assert.NoError(t, err) { + var yt struct { + Definitions struct { + Viewbox struct { + Properties struct { + Y struct { + Type string `json:"type"` + } `json:"y"` + } `json:"properties"` + } `json:"viewbox"` + } `json:"definitions"` + } + if assert.NoError(t, json.Unmarshal(jsond, &yt)) { + assert.Equal(t, "integer", yt.Definitions.Viewbox.Properties.Y.Type) + } + } + } + } + + } +} + +const withQuotedYKey = `consumes: +- application/json +definitions: + viewBox: + type: object + properties: + x: + type: integer + format: int16 + # y -> types don't match: expect map key string or int get: bool + "y": + type: integer + format: int16 + width: + type: integer + format: int16 + height: + type: integer + format: int16 +info: + description: Test RESTful APIs + title: Test Server + version: 1.0.0 +basePath: /api +paths: + /test: + get: + operationId: findAll + parameters: + - name: since + in: query + type: integer + format: int64 + - name: limit + in: query + type: integer + format: int32 + default: 20 + responses: + 200: + description: Array[Trigger] + schema: + type: array + items: + $ref: "#/definitions/viewBox" +produces: +- application/json +schemes: +- https +swagger: "2.0" +` + +const withYKey = `consumes: +- application/json +definitions: + viewBox: + type: object + properties: + x: + type: integer + format: int16 + # y -> types don't match: expect map key string or int get: bool + y: + type: integer + format: int16 + width: + type: integer + format: int16 + height: + type: integer + format: int16 +info: + description: Test RESTful APIs + title: Test Server + version: 1.0.0 +basePath: /api +paths: + /test: + get: + operationId: findAll + parameters: + - name: since + in: query + type: integer + format: int64 + - name: limit + in: query + type: integer + format: int32 + default: 20 + responses: + 200: + description: Array[Trigger] + schema: + type: array + items: + $ref: "#/definitions/viewBox" +produces: +- application/json +schemes: +- https +swagger: "2.0" +` + +const yamlPetStore = `swagger: '2.0' +info: + version: '1.0.0' + title: Swagger Petstore + description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification + termsOfService: http://helloreverb.com/terms/ + contact: + name: Swagger API team + email: foo@example.com + url: http://swagger.io + license: + name: MIT + url: http://opensource.org/licenses/MIT +host: petstore.swagger.wordnik.com +basePath: /api +schemes: + - http +consumes: + - application/json +produces: + - application/json +paths: + /pets: + get: + description: Returns all pets from the system that the user has access to + operationId: findPets + produces: + - application/json + - application/xml + - text/xml + - text/html + parameters: + - name: tags + in: query + description: tags to filter by + required: false + type: array + items: + type: string + collectionFormat: csv + - name: limit + in: query + description: maximum number of results to return + required: false + type: integer + format: int32 + responses: + '200': + description: pet response + schema: + type: array + items: + $ref: '#/definitions/pet' + default: + description: unexpected error + schema: + $ref: '#/definitions/errorModel' + post: + description: Creates a new pet in the store. Duplicates are allowed + operationId: addPet + produces: + - application/json + parameters: + - name: pet + in: body + description: Pet to add to the store + required: true + schema: + $ref: '#/definitions/newPet' + responses: + '200': + description: pet response + schema: + $ref: '#/definitions/pet' + default: + description: unexpected error + schema: + $ref: '#/definitions/errorModel' + /pets/{id}: + get: + description: Returns a user based on a single ID, if the user does not have access to the pet + operationId: findPetById + produces: + - application/json + - application/xml + - text/xml + - text/html + parameters: + - name: id + in: path + description: ID of pet to fetch + required: true + type: integer + format: int64 + responses: + '200': + description: pet response + schema: + $ref: '#/definitions/pet' + default: + description: unexpected error + schema: + $ref: '#/definitions/errorModel' + delete: + description: deletes a single pet based on the ID supplied + operationId: deletePet + parameters: + - name: id + in: path + description: ID of pet to delete + required: true + type: integer + format: int64 + responses: + '204': + description: pet deleted + default: + description: unexpected error + schema: + $ref: '#/definitions/errorModel' +definitions: + pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + newPet: + allOf: + - $ref: '#/definitions/pet' + - required: + - name + properties: + id: + type: integer + format: int64 + name: + type: string + errorModel: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string +` diff --git a/vendor/github.com/go-openapi/loads/hack/build-drone.sh b/vendor/github.com/go-openapi/loads/hack/build-drone.sh new file mode 100755 index 0000000000..52b1180cc9 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/hack/build-drone.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e -o pipefail + + mkdir -p /drone/{testresults,coverage,dist} + go test -race -timeout 20m -v ./... | go-junit-report -dir /drone/testresults + +# Run test coverage on each subdirectories and merge the coverage profile. +echo "mode: ${GOCOVMODE-count}" > profile.cov + +# Standard go tooling behavior is to ignore dirs with leading underscores +# skip generator for race detection and coverage +for dir in $(go list ./...) +do + pth="$GOPATH/src/$dir" + go test -covermode=${GOCOVMODE-count} -coverprofile=${pth}/profile.out $dir + if [ -f $pth/profile.out ] + then + cat $pth/profile.out | tail -n +2 >> profile.cov + # rm $pth/profile.out + fi +done + +go tool cover -func profile.cov +gocov convert profile.cov | gocov report +gocov convert profile.cov | gocov-html > /drone/coverage/coverage-${CI_BUILD_NUM-"0"}.html \ No newline at end of file diff --git a/vendor/github.com/go-openapi/loads/hack/coverage b/vendor/github.com/go-openapi/loads/hack/coverage new file mode 100755 index 0000000000..b8e6dbd0c5 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/hack/coverage @@ -0,0 +1,20 @@ +#!/bin/bash +set -e -o pipefail + +# Run test coverage on each subdirectories and merge the coverage profile. +echo "mode: ${GOCOVMODE-atomic}" > coverage.txt + +# Standard go tooling behavior is to ignore dirs with leading underscores +# skip generator for race detection and coverage +for dir in $(go list ./...) +do + pth="$GOPATH/src/$dir" + go test -race -timeout 20m -covermode=${GOCOVMODE-atomic} -coverprofile=${pth}/profile.out $dir + if [ -f $pth/profile.out ] + then + cat $pth/profile.out | tail -n +2 >> coverage.txt + rm $pth/profile.out + fi +done + +go tool cover -func coverage.txt diff --git a/vendor/github.com/go-openapi/loads/json_test.go b/vendor/github.com/go-openapi/loads/json_test.go new file mode 100644 index 0000000000..8b60eb19f4 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/json_test.go @@ -0,0 +1,318 @@ +// 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 loads + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLoadJSON(t *testing.T) { + serv := httptest.NewServer(http.HandlerFunc(jsonPestoreServer)) + defer serv.Close() + + s, err := JSONSpec(serv.URL) + assert.NoError(t, err) + assert.NotNil(t, s) + + ts2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.WriteHeader(http.StatusNotFound) + rw.Write([]byte("{}")) + })) + defer ts2.Close() + _, err = JSONSpec(ts2.URL) + assert.Error(t, err) +} + +var jsonPestoreServer = func(rw http.ResponseWriter, r *http.Request) { + rw.WriteHeader(http.StatusOK) + rw.Write([]byte(petstoreJSON)) +} + +const petstoreJSON = `{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "contact": { + "name": "Wordnik API Team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "petstore.swagger.wordnik.com", + "basePath": "/api", + "schemes": [ + "http" + ], + "paths": { + "/pets": { + "get": { + "security": [ + { + "oauth2": ["read"] + } + ], + "tags": [ "Pet Operations" ], + "operationId": "getAllPets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "The status to filter by", + "type": "string" + } + ], + "summary": "Finds all pets in the system", + "responses": { + "200": { + "description": "Pet response", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "post": { + "security": [ + { + "oauth2": ["write"] + } + ], + "tags": [ "Pet Operations" ], + "operationId": "createPet", + "summary": "Creates a new pet", + "parameters": [ + { + "name": "pet", + "in": "body", + "description": "The Pet to create", + "required": true, + "schema": { + "$ref": "#/definitions/newPet" + } + } + ], + "responses": { + "200": { + "description": "Created Pet response", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/pets/{id}": { + "delete": { + "security": [ + { + "oauth2": ["write"] + } + ], + "description": "Deletes the Pet by id", + "operationId": "deletePet", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "204": { + "description": "pet deleted" + }, + "default": { + "description": "unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "security": [ + { + "oauth2": ["read"] + } + ], + "tags": [ "Pet Operations" ], + "operationId": "getPetById", + "summary": "Finds the pet by id", + "responses": { + "200": { + "description": "Pet response", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet", + "required": true, + "type": "integer", + "format": "int64" + } + ] + } + }, + "definitions": { + "Category": { + "id": "Category", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "Pet": { + "id": "Pet", + "properties": { + "category": { + "$ref": "#/definitions/Category" + }, + "id": { + "description": "unique identifier for the pet", + "format": "int64", + "maximum": 100.0, + "minimum": 0.0, + "type": "integer" + }, + "name": { + "type": "string" + }, + "photoUrls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ], + "type": "string" + }, + "tags": { + "items": { + "$ref": "#/definitions/Tag" + }, + "type": "array" + } + }, + "required": [ + "id", + "name" + ] + }, + "newPet": { + "allOf": [ + { + "$ref": "#/definitions/Pet" + } + ], + "required": [ + "name" + ] + }, + "Tag": { + "id": "Tag", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "Error": { + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + }, + "produces": [ + "application/json", + "application/xml", + "text/plain", + "text/html" + ], + "securityDefinitions": { + "oauth2": { + "type": "oauth2", + "scopes": { + "read": "Read access.", + "write": "Write access" + }, + "flow": "accessCode", + "authorizationUrl": "http://petstore.swagger.wordnik.com/oauth/authorize", + "tokenUrl": "http://petstore.swagger.wordnik.com/oauth/token" + } + } +}` diff --git a/vendor/github.com/go-openapi/loads/spec.go b/vendor/github.com/go-openapi/loads/spec.go new file mode 100644 index 0000000000..2db5cb558d --- /dev/null +++ b/vendor/github.com/go-openapi/loads/spec.go @@ -0,0 +1,264 @@ +// 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 loads + +import ( + "bytes" + "encoding/json" + "fmt" + "net/url" + + "path/filepath" + + "github.com/go-openapi/analysis" + "github.com/go-openapi/spec" + "github.com/go-openapi/swag" +) + +// JSONDoc loads a json document from either a file or a remote url +func JSONDoc(path string) (json.RawMessage, error) { + data, err := swag.LoadFromFileOrHTTP(path) + if err != nil { + return nil, err + } + return json.RawMessage(data), nil +} + +// DocLoader represents a doc loader type +type DocLoader func(string) (json.RawMessage, error) + +// DocMatcher represents a predicate to check if a loader matches +type DocMatcher func(string) bool + +var ( + loaders *loader + defaultLoader *loader +) + +func init() { + defaultLoader = &loader{Match: func(_ string) bool { return true }, Fn: JSONDoc} + loaders = defaultLoader + spec.PathLoader = loaders.Fn + AddLoader(swag.YAMLMatcher, swag.YAMLDoc) +} + +// AddLoader for a document +func AddLoader(predicate DocMatcher, load DocLoader) { + prev := loaders + loaders = &loader{ + Match: predicate, + Fn: load, + Next: prev, + } + spec.PathLoader = loaders.Fn +} + +type loader struct { + Fn DocLoader + Match DocMatcher + Next *loader +} + +// JSONSpec loads a spec from a json document +func JSONSpec(path string) (*Document, error) { + data, err := JSONDoc(path) + if err != nil { + return nil, err + } + // convert to json + return Analyzed(json.RawMessage(data), "") +} + +// Document represents a swagger spec document +type Document struct { + // specAnalyzer + Analyzer *analysis.Spec + spec *spec.Swagger + specFilePath string + origSpec *spec.Swagger + schema *spec.Schema + raw json.RawMessage +} + +// Spec loads a new spec document +func Spec(path string) (*Document, error) { + specURL, err := url.Parse(path) + if err != nil { + return nil, err + } + var lastErr error + for l := loaders.Next; l != nil; l = l.Next { + if loaders.Match(specURL.Path) { + b, err2 := loaders.Fn(path) + if err2 != nil { + lastErr = err2 + continue + } + doc, err := Analyzed(b, "") + if err != nil { + return nil, err + } + if doc != nil { + doc.specFilePath = path + } + return doc, nil + } + } + if lastErr != nil { + return nil, lastErr + } + b, err := defaultLoader.Fn(path) + if err != nil { + return nil, err + } + + document, err := Analyzed(b, "") + if document != nil { + document.specFilePath = path + } + + return document, err +} + +// Analyzed creates a new analyzed spec document +func Analyzed(data json.RawMessage, version string) (*Document, error) { + if version == "" { + version = "2.0" + } + if version != "2.0" { + return nil, fmt.Errorf("spec version %q is not supported", version) + } + + raw := data + trimmed := bytes.TrimSpace(data) + if len(trimmed) > 0 { + if trimmed[0] != '{' && trimmed[0] != '[' { + yml, err := swag.BytesToYAMLDoc(trimmed) + if err != nil { + return nil, fmt.Errorf("analyzed: %v", err) + } + d, err := swag.YAMLToJSON(yml) + if err != nil { + return nil, fmt.Errorf("analyzed: %v", err) + } + raw = d + } + } + + swspec := new(spec.Swagger) + if err := json.Unmarshal(raw, swspec); err != nil { + return nil, err + } + + origsqspec := new(spec.Swagger) + if err := json.Unmarshal(raw, origsqspec); err != nil { + return nil, err + } + + d := &Document{ + Analyzer: analysis.New(swspec), + schema: spec.MustLoadSwagger20Schema(), + spec: swspec, + raw: raw, + origSpec: origsqspec, + } + return d, nil +} + +// Expanded expands the ref fields in the spec document and returns a new spec document +func (d *Document) Expanded(options ...*spec.ExpandOptions) (*Document, error) { + swspec := new(spec.Swagger) + if err := json.Unmarshal(d.raw, swspec); err != nil { + return nil, err + } + + var expandOptions *spec.ExpandOptions + if len(options) > 0 { + expandOptions = options[0] + } else { + expandOptions = &spec.ExpandOptions{ + RelativeBase: filepath.Dir(d.specFilePath), + } + } + + if err := spec.ExpandSpec(swspec, expandOptions); err != nil { + return nil, err + } + + dd := &Document{ + Analyzer: analysis.New(swspec), + spec: swspec, + schema: spec.MustLoadSwagger20Schema(), + raw: d.raw, + origSpec: d.origSpec, + } + return dd, nil +} + +// BasePath the base path for this spec +func (d *Document) BasePath() string { + return d.spec.BasePath +} + +// Version returns the version of this spec +func (d *Document) Version() string { + return d.spec.Swagger +} + +// Schema returns the swagger 2.0 schema +func (d *Document) Schema() *spec.Schema { + return d.schema +} + +// Spec returns the swagger spec object model +func (d *Document) Spec() *spec.Swagger { + return d.spec +} + +// Host returns the host for the API +func (d *Document) Host() string { + return d.spec.Host +} + +// Raw returns the raw swagger spec as json bytes +func (d *Document) Raw() json.RawMessage { + return d.raw +} + +func (d *Document) OrigSpec() *spec.Swagger { + return d.origSpec +} + +// ResetDefinitions gives a shallow copy with the models reset +func (d *Document) ResetDefinitions() *Document { + defs := make(map[string]spec.Schema, len(d.origSpec.Definitions)) + for k, v := range d.origSpec.Definitions { + defs[k] = v + } + + d.spec.Definitions = defs + return d +} + +// Pristine creates a new pristine document instance based on the input data +func (d *Document) Pristine() *Document { + dd, _ := Analyzed(d.Raw(), d.Version()) + return dd +} + +// SpecFilePath returns the file path of the spec if one is defined +func (d *Document) SpecFilePath() string { + return d.specFilePath +} diff --git a/vendor/github.com/go-openapi/loads/spec_test.go b/vendor/github.com/go-openapi/loads/spec_test.go new file mode 100644 index 0000000000..a3b241d957 --- /dev/null +++ b/vendor/github.com/go-openapi/loads/spec_test.go @@ -0,0 +1,643 @@ +package loads + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUnknownSpecVersion(t *testing.T) { + _, err := Analyzed([]byte{}, "0.9") + assert.Error(t, err) +} + +func TestDefaultsTo20(t *testing.T) { + d, err := Analyzed(PetStoreJSONMessage, "") + + assert.NoError(t, err) + assert.NotNil(t, d) + assert.Equal(t, "2.0", d.Version()) + // assert.Equal(t, "2.0", d.data["swagger"].(string)) + assert.Equal(t, "/api", d.BasePath()) +} + +func TestLoadsYAMLContent(t *testing.T) { + d, err := Analyzed(json.RawMessage([]byte(YAMLSpec)), "") + if assert.NoError(t, err) { + if assert.NotNil(t, d) { + sw := d.Spec() + assert.Equal(t, "1.0.0", sw.Info.Version) + } + } +} + +// for issue 11 +func TestRegressionExpand(t *testing.T) { + swaggerFile := "fixtures/yaml/swagger/1/2/3/4/swagger.yaml" + document, err := Spec(swaggerFile) + assert.NoError(t, err) + assert.NotNil(t, document) + d, err := document.Expanded() + assert.NoError(t, err) + assert.NotNil(t, d) + b, _ := d.Spec().MarshalJSON() + assert.JSONEq(t, expectedExpanded, string(b)) +} + +func TestFailsInvalidJSON(t *testing.T) { + _, err := Analyzed(json.RawMessage([]byte("{]")), "") + + assert.Error(t, err) +} + +var YAMLSpec = `swagger: '2.0' + +info: + version: "1.0.0" + title: Simple Search API + description: | + A very simple api description that makes a x-www-form-urlencoded only API to submit searches. + +produces: + - application/json + +consumes: + - application/json + +paths: + /search: + post: + operationId: search + summary: searches tasks + description: searches the task titles and descriptions for a match + consumes: + - application/x-www-form-urlencoded + parameters: + - name: q + in: formData + type: string + description: the search string + required: true + /tasks: + get: + operationId: getTasks + summary: Gets Task objects. + description: | + Optional query param of **size** determines + size of returned array + tags: + - tasks + parameters: + - name: size + in: query + description: Size of task list + type: integer + format: int32 + default: 20 + - name: completed + in: query + description: when true shows completed tasks + type: boolean + + responses: + default: + description: Generic Error + 200: + description: Successful response + headers: + X-Rate-Limit: + type: integer + format: int32 + X-Rate-Limit-Remaining: + type: integer + format: int32 + default: 42 + X-Rate-Limit-Reset: + type: integer + format: int32 + default: "1449875311" + X-Rate-Limit-Reset-Human: + type: string + default: 3 days + X-Rate-Limit-Reset-Human-Number: + type: string + default: 3 + Access-Control-Allow-Origin: + type: string + default: "*" + schema: + type: array + items: + $ref: "#/definitions/Task" + post: + operationId: createTask + summary: Creates a 'Task' object. + description: | + Validates the content property for length etc. + parameters: + - name: body + in: body + schema: + $ref: "#/definitions/Task" + tags: + - tasks + responses: + default: + description: Generic Error + 201: + description: Task Created + + /tasks/{id}: + parameters: + - name: id + in: path + type: integer + format: int32 + description: The id of the task + required: true + minimum: 1 + put: + operationId: updateTask + summary: updates a task. + description: | + Validates the content property for length etc. + tags: + - tasks + parameters: + - name: body + in: body + description: the updated task + schema: + $ref: "#/definitions/Task" + responses: + default: + description: Generic Error + 200: + description: Task updated + schema: + $ref: "#/definitions/Task" + delete: + operationId: deleteTask + summary: deletes a task + description: | + Deleting a task is irrevocable. + tags: + - tasks + responses: + default: + description: Generic Error + 204: + description: Task Deleted + + +definitions: + Task: + title: A Task object + description: | + This describes a task. Tasks require a content property to be set. + required: + - content + type: object + properties: + id: + title: the unique id of the task + description: | + This id property is autogenerated when a task is created. + type: integer + format: int64 + readOnly: true + content: + title: The content of the task + description: | + Task content can contain [GFM](https://help.github.com/articles/github-flavored-markdown/). + type: string + minLength: 5 + completed: + title: when true this task is completed + type: boolean + creditcard: + title: the credit card format usage + type: string + format: creditcard + createdAt: + title: task creation time + type: string + format: date-time + readOnly: true +` + +// PetStoreJSONMessage json raw message for Petstore20 +var PetStoreJSONMessage = json.RawMessage([]byte(PetStore20)) + +// PetStore20 json doc for swagger 2.0 pet store +const PetStore20 = `{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "contact": { + "name": "Wordnik API Team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "petstore.swagger.wordnik.com", + "basePath": "/api", + "schemes": [ + "http" + ], + "paths": { + "/pets": { + "get": { + "security": [ + { + "basic": [] + } + ], + "tags": [ "Pet Operations" ], + "operationId": "getAllPets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "The status to filter by", + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "The maximum number of results to return", + "type": "integer", + "format": "int64" + } + ], + "summary": "Finds all pets in the system", + "responses": { + "200": { + "description": "Pet response", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "post": { + "security": [ + { + "basic": [] + } + ], + "tags": [ "Pet Operations" ], + "operationId": "createPet", + "summary": "Creates a new pet", + "consumes": ["application/x-yaml"], + "produces": ["application/x-yaml"], + "parameters": [ + { + "name": "pet", + "in": "body", + "description": "The Pet to create", + "required": true, + "schema": { + "$ref": "#/definitions/newPet" + } + } + ], + "responses": { + "200": { + "description": "Created Pet response", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/pets/{id}": { + "delete": { + "security": [ + { + "apiKey": [] + } + ], + "description": "Deletes the Pet by id", + "operationId": "deletePet", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "204": { + "description": "pet deleted" + }, + "default": { + "description": "unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "tags": [ "Pet Operations" ], + "operationId": "getPetById", + "summary": "Finds the pet by id", + "responses": { + "200": { + "description": "Pet response", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet", + "required": true, + "type": "integer", + "format": "int64" + } + ] + } + }, + "definitions": { + "Category": { + "id": "Category", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "Pet": { + "id": "Pet", + "properties": { + "category": { + "$ref": "#/definitions/Category" + }, + "id": { + "description": "unique identifier for the pet", + "format": "int64", + "maximum": 100.0, + "minimum": 0.0, + "type": "integer" + }, + "name": { + "type": "string" + }, + "photoUrls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ], + "type": "string" + }, + "tags": { + "items": { + "$ref": "#/definitions/Tag" + }, + "type": "array" + } + }, + "required": [ + "id", + "name" + ] + }, + "newPet": { + "anyOf": [ + { + "$ref": "#/definitions/Pet" + }, + { + "required": [ + "name" + ] + } + ] + }, + "Tag": { + "id": "Tag", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "Error": { + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + }, + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/json", + "application/xml", + "text/plain", + "text/html" + ], + "securityDefinitions": { + "basic": { + "type": "basic" + }, + "apiKey": { + "type": "apiKey", + "in": "header", + "name": "X-API-KEY" + } + } +} +` + +const expectedExpanded = ` +{ + "produces":[ + "application/json", + "plain/text" + ], + "schemes":[ + "https", + "http" + ], + "swagger":"2.0", + "info":{ + "description":"Something", + "title":"Something", + "contact":{ + "name":"Somebody", + "url":"https://url.com", + "email":"email@url.com" + }, + "version":"v1" + }, + "host":"security.sonusnet.com", + "basePath":"/api", + "paths":{ + "/whatnot":{ + "get":{ + "description":"Get something", + "responses":{ + "200":{ + "description":"The something", + "schema":{ + "description":"A collection of service events", + "type":"object", + "properties":{ + "page":{ + "description":"A description of a paged result", + "type":"object", + "properties":{ + "page":{ + "description":"the page that was requested", + "type":"integer" + }, + "page_items":{ + "description":"the number of items per page requested", + "type":"integer" + }, + "pages":{ + "description":"the total number of pages available", + "type":"integer" + }, + "total_items":{ + "description":"the total number of items available", + "type":"integer", + "format":"int64" + } + } + }, + "something":{ + "description":"Something", + "type":"object", + "properties":{ + "p1":{ + "description":"A string", + "type":"string" + }, + "p2":{ + "description":"An integer", + "type":"integer" + } + } + } + } + } + }, + "500":{ + "description":"Oops" + } + } + } + } + }, + "definitions":{ + "Something":{ + "description":"A collection of service events", + "type":"object", + "properties":{ + "page":{ + "description":"A description of a paged result", + "type":"object", + "properties":{ + "page":{ + "description":"the page that was requested", + "type":"integer" + }, + "page_items":{ + "description":"the number of items per page requested", + "type":"integer" + }, + "pages":{ + "description":"the total number of pages available", + "type":"integer" + }, + "total_items":{ + "description":"the total number of items available", + "type":"integer", + "format":"int64" + } + } + }, + "something":{ + "description":"Something", + "type":"object", + "properties":{ + "p1":{ + "description":"A string", + "type":"string" + }, + "p2":{ + "description":"An integer", + "type":"integer" + } + } + } + } + } + } +} +` diff --git a/vendor/github.com/go-openapi/runtime/.editorconfig b/vendor/github.com/go-openapi/runtime/.editorconfig new file mode 100644 index 0000000000..3152da69a5 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/.editorconfig @@ -0,0 +1,26 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +# Set default charset +[*.{js,py,go,scala,rb,java,html,css,less,sass,md}] +charset = utf-8 + +# Tab indentation (no size specified) +[*.go] +indent_style = tab + +[*.md] +trim_trailing_whitespace = false + +# Matches the exact files either package.json or .travis.yml +[{package.json,.travis.yml}] +indent_style = space +indent_size = 2 diff --git a/vendor/github.com/go-openapi/runtime/.github/CONTRIBUTING.md b/vendor/github.com/go-openapi/runtime/.github/CONTRIBUTING.md new file mode 100644 index 0000000000..7dea4240d7 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/.github/CONTRIBUTING.md @@ -0,0 +1,117 @@ +## Contribution Guidelines + +### Pull requests are always welcome + +We are always thrilled to receive pull requests, and do our best to +process them as fast as possible. Not sure if that typo is worth a pull +request? Do it! We will appreciate it. + +If your pull request is not accepted on the first try, don't be +discouraged! If there's a problem with the implementation, hopefully you +received feedback on what to improve. + +We're trying very hard to keep go-swagger lean and focused. We don't want it +to do everything for everybody. This means that we might decide against +incorporating a new feature. However, there might be a way to implement +that feature *on top of* go-swagger. + + +### Conventions + +Fork the repo and make changes on your fork in a feature branch: + +- If it's a bugfix branch, name it XXX-something where XXX is the number of the + issue +- If it's a feature branch, create an enhancement issue to announce your + intentions, and name it XXX-something where XXX is the number of the issue. + +Submit unit tests for your changes. Go has a great test framework built in; use +it! Take a look at existing tests for inspiration. Run the full test suite on +your branch before submitting a pull request. + +Update the documentation when creating or modifying features. Test +your documentation changes for clarity, concision, and correctness, as +well as a clean documentation build. See ``docs/README.md`` for more +information on building the docs and how docs get released. + +Write clean code. Universally formatted code promotes ease of writing, reading, +and maintenance. Always run `gofmt -s -w file.go` on each changed file before +committing your changes. Most editors have plugins that do this automatically. + +Pull requests descriptions should be as clear as possible and include a +reference to all the issues that they address. + +Pull requests must not contain commits from other users or branches. + +Commit messages must start with a capitalized and short summary (max. 50 +chars) written in the imperative, followed by an optional, more detailed +explanatory text which is separated from the summary by an empty line. + +Code review comments may be added to your pull request. Discuss, then make the +suggested modifications and push additional commits to your feature branch. Be +sure to post a comment after pushing. The new commits will show up in the pull +request automatically, but the reviewers will not be notified unless you +comment. + +Before the pull request is merged, make sure that you squash your commits into +logical units of work using `git rebase -i` and `git push -f`. After every +commit the test suite should be passing. Include documentation changes in the +same commit so that a revert would remove all traces of the feature or fix. + +Commits that fix or close an issue should include a reference like `Closes #XXX` +or `Fixes #XXX`, which will automatically close the issue when merged. + +### Sign your work + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right to +pass it on as an open-source patch. The rules are pretty simple: if you +can certify the below (from +[developercertificate.org](http://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +You can add the sign off when creating the git commit via `git commit -s`. diff --git a/vendor/github.com/go-openapi/runtime/.gitignore b/vendor/github.com/go-openapi/runtime/.gitignore new file mode 100644 index 0000000000..fea8b84eca --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/.gitignore @@ -0,0 +1,5 @@ +secrets.yml +coverage.out +*.cov +*.out +playground diff --git a/vendor/github.com/go-openapi/runtime/.travis.yml b/vendor/github.com/go-openapi/runtime/.travis.yml new file mode 100644 index 0000000000..192d6d27b9 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/.travis.yml @@ -0,0 +1,25 @@ +language: go +dist: trusty +go: +- 1.7.x +- 1.8.x +install: +- go get -u github.com/axw/gocov/gocov +- go get -u gopkg.in/matm/v1/gocov-html +- go get -u github.com/cee-dub/go-junit-report +- go get -u github.com/stretchr/testify/assert +- go get -u golang.org/x/net/context +- go get -u gopkg.in/yaml.v2 +- go get -u github.com/go-openapi/analysis +- go get -u github.com/go-openapi/errors +- go get -u github.com/go-openapi/loads +- go get -u github.com/go-openapi/strfmt +- go get -u github.com/go-openapi/validate +- go get -u github.com/docker/go-units +script: +- ./hack/coverage +after_success: +- bash <(curl -s https://codecov.io/bash) +notifications: + slack: + secure: EmObnQuM9Mw8J9vpFaKKHqSMN4Wsr/A9+v7ewAD5cEhA0T1P4m7MbJMiJOhxUhj/X+BFh2DamW+P2lT8mybj5wg8wnkQ2BteKA8Tawi6f9PRw2NRheO8tAi8o/npLnlmet0kc93mn+oLuqHw36w4+j5mkOl2FghkfGiUVhwrhkCP7KXQN+3TU87e+/HzQumlJ3nsE+6terVxkH3PmaUTsS5ONaODZfuxFpfb7RsoEl3skHf6d+tr+1nViLxxly7558Nc33C+W1mr0qiEvMLZ+kJ/CpGWBJ6CUJM3jm6hNe2eMuIPwEK2hxZob8c7n22VPap4K6a0bBRoydoDXaba+2sD7Ym6ivDO/DVyL44VeBBLyIiIBylDGQdZH+6SoWm90Qe/i7tnY/T5Ao5igT8f3cfQY1c3EsTfqmlDfrhmACBmwSlgkdVBLTprHL63JMY24LWmh4jhxsmMRZhCL4dze8su1w6pLN/pD1pGHtKYCEVbdTmaM3PblNRFf12XB7qosmQsgUndH4Vq3bTbU0s1pKjeDhRyLvFzvR0TBbo0pDLEoF1A/i5GVFWa7yLZNUDudQERRh7qv/xBl2excIaQ1sV4DSVm7bAE9l6Kp+yeHQJW2uN6Y3X8wu9gB9nv9l5HBze7wh8KE6PyWAOLYYqZg9/sAtsv/2GcQqXcKFF1zcA= diff --git a/vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..9322b065e3 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at ivan+abuse@flanders.co.nz. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/runtime/LICENSE b/vendor/github.com/go-openapi/runtime/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/go-openapi/runtime/README.md b/vendor/github.com/go-openapi/runtime/README.md new file mode 100644 index 0000000000..92c40705b8 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/README.md @@ -0,0 +1,5 @@ +# runtime [![Build Status](https://travis-ci.org/go-openapi/runtime.svg?branch=client-context)](https://travis-ci.org/go-openapi/runtime) [![codecov](https://codecov.io/gh/go-openapi/runtime/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/runtime) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) + +[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/runtime/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/runtime?status.svg)](http://godoc.org/github.com/go-openapi/runtime) + +The runtime component for use in codegeneration or as untyped usage. diff --git a/vendor/github.com/go-openapi/runtime/authinfo_test.go b/vendor/github.com/go-openapi/runtime/authinfo_test.go new file mode 100644 index 0000000000..0768df3b7c --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/authinfo_test.go @@ -0,0 +1,33 @@ +// 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 runtime + +import ( + "testing" + + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +func TestAuthInfoWriter(t *testing.T) { + hand := ClientAuthInfoWriterFunc(func(r ClientRequest, _ strfmt.Registry) error { + return r.SetHeaderParam("authorization", "Bearer the-token-goes-here") + }) + + tr := new(trw) + err := hand.AuthenticateRequest(tr, nil) + assert.NoError(t, err) + assert.Equal(t, "Bearer the-token-goes-here", tr.Headers.Get("Authorization")) +} diff --git a/vendor/github.com/go-openapi/runtime/bytestream.go b/vendor/github.com/go-openapi/runtime/bytestream.go new file mode 100644 index 0000000000..10b88ad488 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/bytestream.go @@ -0,0 +1,116 @@ +// 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 runtime + +import ( + "bytes" + "encoding" + "errors" + "fmt" + "io" + "reflect" + + "github.com/go-openapi/swag" +) + +// ByteStreamConsumer creates a consmer for byte streams, +// takes a Writer/BinaryUnmarshaler interface or binary slice by reference, +// and reads from the provided reader +func ByteStreamConsumer() Consumer { + return ConsumerFunc(func(reader io.Reader, data interface{}) error { + if reader == nil { + return errors.New("ByteStreamConsumer requires a reader") // early exit + } + + if wrtr, ok := data.(io.Writer); ok { + _, err := io.Copy(wrtr, reader) + return err + } + + buf := new(bytes.Buffer) + _, err := buf.ReadFrom(reader) + if err != nil { + return err + } + b := buf.Bytes() + + if bu, ok := data.(encoding.BinaryUnmarshaler); ok { + return bu.UnmarshalBinary(b) + } + + if t := reflect.TypeOf(data); data != nil && t.Kind() == reflect.Ptr { + v := reflect.Indirect(reflect.ValueOf(data)) + if t = v.Type(); t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 { + v.SetBytes(b) + return nil + } + } + + return fmt.Errorf("%v (%T) is not supported by the ByteStreamConsumer, %s", + data, data, "can be resolved by supporting Writer/BinaryUnmarshaler interface") + }) +} + +// ByteStreamProducer creates a producer for byte streams, +// takes a Reader/BinaryMarshaler interface or binary slice, +// and writes to a writer (essentially a pipe) +func ByteStreamProducer() Producer { + return ProducerFunc(func(writer io.Writer, data interface{}) error { + if writer == nil { + return errors.New("ByteStreamProducer requires a writer") // early exit + } + + if rdr, ok := data.(io.Reader); ok { + _, err := io.Copy(writer, rdr) + return err + } + + if bm, ok := data.(encoding.BinaryMarshaler); ok { + bytes, err := bm.MarshalBinary() + if err != nil { + return err + } + + _, err = writer.Write(bytes) + return err + } + + if data != nil { + if e, ok := data.(error); ok { + _, err := writer.Write([]byte(e.Error())) + return err + } + } + + if data != nil { + v := reflect.Indirect(reflect.ValueOf(data)) + if t := v.Type(); t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 { + _, err := writer.Write(v.Bytes()) + return err + } + if t := v.Type(); t.Kind() == reflect.Struct || t.Kind() == reflect.Slice { + b, err := swag.WriteJSON(data) + if err != nil { + return err + } + _, err = writer.Write(b) + return err + } + } + + return fmt.Errorf("%v (%T) is not supported by the ByteStreamProducer, %s", + data, data, "can be resolved by supporting Reader/BinaryMarshaler interface") + }) +} diff --git a/vendor/github.com/go-openapi/runtime/bytestream_test.go b/vendor/github.com/go-openapi/runtime/bytestream_test.go new file mode 100644 index 0000000000..72435b0175 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/bytestream_test.go @@ -0,0 +1,140 @@ +package runtime + +import ( + "bytes" + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestByteStreamConsumer(t *testing.T) { + cons := ByteStreamConsumer() + + expected := "the data for the stream to be sent over the wire" + + // can consume as a Writer + var b bytes.Buffer + if assert.NoError(t, cons.Consume(bytes.NewBufferString(expected), &b)) { + assert.Equal(t, expected, b.String()) + } + + // can consume as an UnmarshalBinary + var bu binaryUnmarshalDummy + if assert.NoError(t, cons.Consume(bytes.NewBufferString(expected), &bu)) { + assert.Equal(t, expected, bu.str) + } + + // can consume as a binary slice + var bs []byte + if assert.NoError(t, cons.Consume(bytes.NewBufferString(expected), &bs)) { + assert.Equal(t, expected, string(bs)) + } + type binarySlice []byte + var bs2 binarySlice + if assert.NoError(t, cons.Consume(bytes.NewBufferString(expected), &bs2)) { + assert.Equal(t, expected, string(bs2)) + } + + // passing in a nilslice wil result in an error + var ns *[]byte + assert.Error(t, cons.Consume(bytes.NewBufferString(expected), &ns)) + + // passing in nil wil result in an error as well + assert.Error(t, cons.Consume(bytes.NewBufferString(expected), nil)) + + // a reader who results in an error, will make it fail + assert.Error(t, cons.Consume(new(nopReader), &bu)) + assert.Error(t, cons.Consume(new(nopReader), &bs)) + + // the readers can also not be nil + assert.Error(t, cons.Consume(nil, &bs)) +} + +type binaryUnmarshalDummy struct { + str string +} + +func (b *binaryUnmarshalDummy) UnmarshalBinary(bytes []byte) error { + if len(bytes) == 0 { + return errors.New("no text given") + } + + b.str = string(bytes) + return nil +} + +func TestByteStreamProducer(t *testing.T) { + cons := ByteStreamProducer() + expected := "the data for the stream to be sent over the wire" + + var rdr bytes.Buffer + + // can produce using a reader + if assert.NoError(t, cons.Produce(&rdr, bytes.NewBufferString(expected))) { + assert.Equal(t, expected, rdr.String()) + rdr.Reset() + } + + // can produce using a binary marshaller + if assert.NoError(t, cons.Produce(&rdr, &binaryMarshalDummy{expected})) { + assert.Equal(t, expected, rdr.String()) + rdr.Reset() + } + + // binary slices can also be used to produce + if assert.NoError(t, cons.Produce(&rdr, []byte(expected))) { + assert.Equal(t, expected, rdr.String()) + rdr.Reset() + } + + // errors can also be used to produce + if assert.NoError(t, cons.Produce(&rdr, errors.New(expected))) { + assert.Equal(t, expected, rdr.String()) + rdr.Reset() + } + + // structs can also be used to produce + if assert.NoError(t, cons.Produce(&rdr, Error{Message: expected})) { + assert.Equal(t, fmt.Sprintf(`{"message":%q}`, expected), rdr.String()) + rdr.Reset() + } + + // struct pointers can also be used to produce + if assert.NoError(t, cons.Produce(&rdr, &Error{Message: expected})) { + assert.Equal(t, fmt.Sprintf(`{"message":%q}`, expected), rdr.String()) + rdr.Reset() + } + + // slices can also be used to produce + if assert.NoError(t, cons.Produce(&rdr, []string{expected})) { + assert.Equal(t, fmt.Sprintf(`[%q]`, expected), rdr.String()) + rdr.Reset() + } + + type binarySlice []byte + if assert.NoError(t, cons.Produce(&rdr, binarySlice(expected))) { + assert.Equal(t, expected, rdr.String()) + rdr.Reset() + } + + // when binaryMarshal data is used, its potential error gets propagated + assert.Error(t, cons.Produce(&rdr, new(binaryMarshalDummy))) + // nil data should never be accepted either + assert.Error(t, cons.Produce(&rdr, nil)) + // nil readers should also never be acccepted + assert.Error(t, cons.Produce(nil, bytes.NewBufferString(expected))) +} + +type binaryMarshalDummy struct { + str string +} + +func (b *binaryMarshalDummy) MarshalBinary() ([]byte, error) { + if len(b.str) == 0 { + return nil, errors.New("no text set") + } + + return []byte(b.str), nil +} diff --git a/vendor/github.com/go-openapi/runtime/client/auth_info.go b/vendor/github.com/go-openapi/runtime/client/auth_info.go new file mode 100644 index 0000000000..9e18222b5e --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/auth_info.go @@ -0,0 +1,60 @@ +// 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 client + +import ( + "encoding/base64" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" +) + +// PassThroughAuth never manipulates the request +var PassThroughAuth runtime.ClientAuthInfoWriter + +func init() { + PassThroughAuth = runtime.ClientAuthInfoWriterFunc(func(_ runtime.ClientRequest, _ strfmt.Registry) error { return nil }) +} + +// BasicAuth provides a basic auth info writer +func BasicAuth(username, password string) runtime.ClientAuthInfoWriter { + return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error { + encoded := base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) + return r.SetHeaderParam("Authorization", "Basic "+encoded) + }) +} + +// APIKeyAuth provides an API key auth info writer +func APIKeyAuth(name, in, value string) runtime.ClientAuthInfoWriter { + if in == "query" { + return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error { + return r.SetQueryParam(name, value) + }) + } + + if in == "header" { + return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error { + return r.SetHeaderParam(name, value) + }) + } + return nil +} + +// BearerToken provides a header based oauth2 bearer access token auth info writer +func BearerToken(token string) runtime.ClientAuthInfoWriter { + return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error { + return r.SetHeaderParam("Authorization", "Bearer "+token) + }) +} diff --git a/vendor/github.com/go-openapi/runtime/client/auth_info_test.go b/vendor/github.com/go-openapi/runtime/client/auth_info_test.go new file mode 100644 index 0000000000..ef88594437 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/auth_info_test.go @@ -0,0 +1,69 @@ +// 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 client + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBasicAuth(t *testing.T) { + r, _ := newRequest("GET", "/", nil) + + writer := BasicAuth("someone", "with a password") + err := writer.AuthenticateRequest(r, nil) + assert.NoError(t, err) + + req := new(http.Request) + req.Header = make(http.Header) + req.Header.Set("Authorization", r.header.Get("Authorization")) + usr, pw, ok := req.BasicAuth() + if assert.True(t, ok) { + assert.Equal(t, "someone", usr) + assert.Equal(t, "with a password", pw) + } +} + +func TestAPIKeyAuth_Query(t *testing.T) { + r, _ := newRequest("GET", "/", nil) + + writer := APIKeyAuth("api_key", "query", "the-shared-key") + err := writer.AuthenticateRequest(r, nil) + assert.NoError(t, err) + + assert.Equal(t, "the-shared-key", r.query.Get("api_key")) +} + +func TestAPIKeyAuth_Header(t *testing.T) { + r, _ := newRequest("GET", "/", nil) + + writer := APIKeyAuth("x-api-token", "header", "the-shared-key") + err := writer.AuthenticateRequest(r, nil) + assert.NoError(t, err) + + assert.Equal(t, "the-shared-key", r.header.Get("x-api-token")) +} + +func TestBearerTokenAuth(t *testing.T) { + r, _ := newRequest("GET", "/", nil) + + writer := BearerToken("the-shared-token") + err := writer.AuthenticateRequest(r, nil) + assert.NoError(t, err) + + assert.Equal(t, "Bearer the-shared-token", r.header.Get("Authorization")) +} diff --git a/vendor/github.com/go-openapi/runtime/client/request.go b/vendor/github.com/go-openapi/runtime/client/request.go new file mode 100644 index 0000000000..4b1ac0805e --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/request.go @@ -0,0 +1,282 @@ +// 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 client + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "log" + "mime/multipart" + "net/http" + "net/url" + "os" + "path/filepath" + "strings" + "time" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" +) + +// NewRequest creates a new swagger http client request +func newRequest(method, pathPattern string, writer runtime.ClientRequestWriter) (*request, error) { + return &request{ + pathPattern: pathPattern, + method: method, + writer: writer, + header: make(http.Header), + query: make(url.Values), + timeout: DefaultTimeout, + }, nil +} + +// Request represents a swagger client request. +// +// This Request struct converts to a HTTP request. +// There might be others that convert to other transports. +// There is no error checking here, it is assumed to be used after a spec has been validated. +// so impossible combinations should not arise (hopefully). +// +// The main purpose of this struct is to hide the machinery of adding params to a transport request. +// The generated code only implements what is necessary to turn a param into a valid value for these methods. +type request struct { + pathPattern string + method string + writer runtime.ClientRequestWriter + + pathParams map[string]string + header http.Header + query url.Values + formFields url.Values + fileFields map[string]runtime.NamedReadCloser + payload interface{} + timeout time.Duration +} + +var ( + // ensure interface compliance + _ runtime.ClientRequest = new(request) +) + +// BuildHTTP creates a new http request based on the data from the params +func (r *request) BuildHTTP(mediaType string, producers map[string]runtime.Producer, registry strfmt.Registry) (*http.Request, error) { + // build the data + if err := r.writer.WriteToRequest(r, registry); err != nil { + return nil, err + } + + // create http request + path := r.pathPattern + for k, v := range r.pathParams { + path = strings.Replace(path, "{"+k+"}", v, -1) + } + + var body io.ReadCloser + var pr *io.PipeReader + var pw *io.PipeWriter + buf := bytes.NewBuffer(nil) + if r.payload != nil || len(r.formFields) > 0 || len(r.fileFields) > 0 { + body = ioutil.NopCloser(buf) + if r.fileFields != nil { + pr, pw = io.Pipe() + body = pr + } + } + req, err := http.NewRequest(r.method, path, body) + if err != nil { + return nil, err + } + req.URL.RawQuery = r.query.Encode() + req.Header = r.header + + // check if this is a form type request + if len(r.formFields) > 0 || len(r.fileFields) > 0 { + // check if this is multipart + if len(r.fileFields) > 0 { + mp := multipart.NewWriter(pw) + req.Header.Set(runtime.HeaderContentType, mp.FormDataContentType()) + + go func() { + defer func() { + mp.Close() + pw.Close() + }() + + for fn, v := range r.formFields { + if len(v) > 0 { + if err := mp.WriteField(fn, v[0]); err != nil { + pw.CloseWithError(err) + log.Println(err) + } + } + } + + for fn, f := range r.fileFields { + wrtr, err := mp.CreateFormFile(fn, filepath.Base(f.Name())) + if err != nil { + pw.CloseWithError(err) + log.Println(err) + } + defer func() { + for _, ff := range r.fileFields { + ff.Close() + } + + }() + if _, err := io.Copy(wrtr, f); err != nil { + pw.CloseWithError(err) + log.Println(err) + } + } + + }() + return req, nil + } + + req.Header.Set(runtime.HeaderContentType, mediaType) + formString := r.formFields.Encode() + // set content length before writing to the buffer + req.ContentLength = int64(len(formString)) + // write the form values as the body + buf.WriteString(formString) + return req, nil + } + + // if there is payload, use the producer to write the payload, and then + // set the header to the content-type appropriate for the payload produced + if r.payload != nil { + // TODO: infer most appropriate content type based on the producer used, + // and the `consumers` section of the spec/operation + req.Header.Set(runtime.HeaderContentType, mediaType) + if rdr, ok := r.payload.(io.ReadCloser); ok { + req.Body = rdr + return req, nil + } + + if rdr, ok := r.payload.(io.Reader); ok { + req.Body = ioutil.NopCloser(rdr) + return req, nil + } + + // set the content length of the request or else a chunked transfer is + // declared, and this corrupts outgoing JSON payloads. the content's + // length must be set prior to the body being written per the spec at + // https://golang.org/pkg/net/http + // + // If Body is present, Content-Length is <= 0 and TransferEncoding + // hasn't been set to "identity", Write adds + // "Transfer-Encoding: chunked" to the header. Body is closed + // after it is sent. + // + // to that end a temporary buffer, b, is created to produce the payload + // body, and then its size is used to set the request's content length + var b bytes.Buffer + producer := producers[mediaType] + if err := producer.Produce(&b, r.payload); err != nil { + return nil, err + } + req.ContentLength = int64(b.Len()) + if _, err := buf.Write(b.Bytes()); err != nil { + return nil, err + } + } + + if runtime.CanHaveBody(req.Method) && req.Body == nil && req.Header.Get(runtime.HeaderContentType) == "" { + req.Header.Set(runtime.HeaderContentType, mediaType) + } + + return req, nil +} + +// SetHeaderParam adds a header param to the request +// when there is only 1 value provided for the varargs, it will set it. +// when there are several values provided for the varargs it will add it (no overriding) +func (r *request) SetHeaderParam(name string, values ...string) error { + if r.header == nil { + r.header = make(http.Header) + } + r.header[http.CanonicalHeaderKey(name)] = values + return nil +} + +// SetQueryParam adds a query param to the request +// when there is only 1 value provided for the varargs, it will set it. +// when there are several values provided for the varargs it will add it (no overriding) +func (r *request) SetQueryParam(name string, values ...string) error { + if r.query == nil { + r.query = make(url.Values) + } + r.query[name] = values + return nil +} + +// SetFormParam adds a forn param to the request +// when there is only 1 value provided for the varargs, it will set it. +// when there are several values provided for the varargs it will add it (no overriding) +func (r *request) SetFormParam(name string, values ...string) error { + if r.formFields == nil { + r.formFields = make(url.Values) + } + r.formFields[name] = values + return nil +} + +// SetPathParam adds a path param to the request +func (r *request) SetPathParam(name string, value string) error { + if r.pathParams == nil { + r.pathParams = make(map[string]string) + } + + r.pathParams[name] = value + return nil +} + +// SetFileParam adds a file param to the request +func (r *request) SetFileParam(name string, file runtime.NamedReadCloser) error { + if actualFile, ok := file.(*os.File); ok { + fi, err := os.Stat(actualFile.Name()) + if err != nil { + return err + } + if fi.IsDir() { + return fmt.Errorf("%q is a directory, only files are supported", file.Name()) + } + } + + if r.fileFields == nil { + r.fileFields = make(map[string]runtime.NamedReadCloser) + } + if r.formFields == nil { + r.formFields = make(url.Values) + } + + r.fileFields[name] = file + return nil +} + +// SetBodyParam sets a body parameter on the request. +// This does not yet serialze the object, this happens as late as possible. +func (r *request) SetBodyParam(payload interface{}) error { + r.payload = payload + return nil +} + +// SetTimeout sets the timeout for a request +func (r *request) SetTimeout(timeout time.Duration) error { + r.timeout = timeout + return nil +} diff --git a/vendor/github.com/go-openapi/runtime/client/request_test.go b/vendor/github.com/go-openapi/runtime/client/request_test.go new file mode 100644 index 0000000000..0f1d602671 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/request_test.go @@ -0,0 +1,287 @@ +// 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 client + +import ( + "encoding/json" + "encoding/xml" + "io/ioutil" + "mime" + "mime/multipart" + "os" + "path/filepath" + "testing" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +var testProducers = map[string]runtime.Producer{ + runtime.JSONMime: runtime.JSONProducer(), + runtime.XMLMime: runtime.XMLProducer(), + runtime.TextMime: runtime.TextProducer(), +} + +func TestBuildRequest_SetHeaders(t *testing.T) { + r, _ := newRequest("GET", "/flats/{id}/", nil) + // single value + _ = r.SetHeaderParam("X-Rate-Limit", "500") + assert.Equal(t, "500", r.header.Get("X-Rate-Limit")) + _ = r.SetHeaderParam("X-Rate-Limit", "400") + assert.Equal(t, "400", r.header.Get("X-Rate-Limit")) + + // multi value + _ = r.SetHeaderParam("X-Accepts", "json", "xml", "yaml") + assert.EqualValues(t, []string{"json", "xml", "yaml"}, r.header["X-Accepts"]) +} + +func TestBuildRequest_SetPath(t *testing.T) { + r, _ := newRequest("GET", "/flats/{id}/?hello=world", nil) + + _ = r.SetPathParam("id", "1345") + assert.Equal(t, "1345", r.pathParams["id"]) +} + +func TestBuildRequest_SetQuery(t *testing.T) { + r, _ := newRequest("GET", "/flats/{id}/", nil) + + // single value + _ = r.SetQueryParam("hello", "there") + assert.Equal(t, "there", r.query.Get("hello")) + + // multi value + _ = r.SetQueryParam("goodbye", "cruel", "world") + assert.Equal(t, []string{"cruel", "world"}, r.query["goodbye"]) +} + +func TestBuildRequest_SetForm(t *testing.T) { + // non-multipart + r, _ := newRequest("POST", "/flats", nil) + _ = r.SetFormParam("hello", "world") + assert.Equal(t, "world", r.formFields.Get("hello")) + _ = r.SetFormParam("goodbye", "cruel", "world") + assert.Equal(t, []string{"cruel", "world"}, r.formFields["goodbye"]) +} + +func TestBuildRequest_SetFile(t *testing.T) { + // needs to convert form to multipart + r, _ := newRequest("POST", "/flats/{id}/image", nil) + // error if it isn't there + err := r.SetFileParam("not there", os.NewFile(0, "./i-dont-exist")) + assert.Error(t, err) + // error if it isn't a file + err = r.SetFileParam("directory", os.NewFile(0, "../client")) + assert.Error(t, err) + // success adds it to the map + err = r.SetFileParam("file", mustGetFile("./runtime.go")) + if assert.NoError(t, err) { + fl, ok := r.fileFields["file"] + if assert.True(t, ok) { + assert.Equal(t, "runtime.go", filepath.Base(fl.Name())) + } + } +} + +func mustGetFile(path string) *os.File { + f, err := os.Open(path) + if err != nil { + panic(err) + } + return f +} + +func TestBuildRequest_SetBody(t *testing.T) { + r, _ := newRequest("GET", "/flats/{id}/?hello=world", nil) + bd := []struct{ Name, Hobby string }{{"Tom", "Organ trail"}, {"John", "Bird watching"}} + + _ = r.SetBodyParam(bd) + assert.Equal(t, bd, r.payload) +} + +func TestBuildRequest_BuildHTTP_NoPayload(t *testing.T) { + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetBodyParam(nil) + _ = req.SetQueryParam("hello", "world") + _ = req.SetPathParam("id", "1234") + _ = req.SetHeaderParam("X-Rate-Limit", "200") + return nil + }) + r, _ := newRequest("POST", "/flats/{id}/", reqWrtr) + + req, err := r.BuildHTTP(runtime.JSONMime, testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "200", req.Header.Get("x-rate-limit")) + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "/flats/1234/", req.URL.Path) + assert.Equal(t, runtime.JSONMime, req.Header.Get(runtime.HeaderContentType)) + } +} + +func TestBuildRequest_BuildHTTP_Payload(t *testing.T) { + bd := []struct{ Name, Hobby string }{{"Tom", "Organ trail"}, {"John", "Bird watching"}} + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetBodyParam(bd) + _ = req.SetQueryParam("hello", "world") + _ = req.SetPathParam("id", "1234") + _ = req.SetHeaderParam("X-Rate-Limit", "200") + return nil + }) + r, _ := newRequest("GET", "/flats/{id}/", reqWrtr) + _ = r.SetHeaderParam(runtime.HeaderContentType, runtime.JSONMime) + + req, err := r.BuildHTTP(runtime.JSONMime, testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "200", req.Header.Get("x-rate-limit")) + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "/flats/1234/", req.URL.Path) + expectedBody, _ := json.Marshal(bd) + actualBody, _ := ioutil.ReadAll(req.Body) + assert.Equal(t, append(expectedBody, '\n'), actualBody) + } +} + +func TestBuildRequest_BuildHTTP_XMLPayload(t *testing.T) { + bd := []struct { + XMLName xml.Name `xml:"person"` + Name string `xml:"name"` + Hobby string `xml:"hobby"` + }{{xml.Name{}, "Tom", "Organ trail"}, {xml.Name{}, "John", "Bird watching"}} + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetBodyParam(bd) + _ = req.SetQueryParam("hello", "world") + _ = req.SetPathParam("id", "1234") + _ = req.SetHeaderParam("X-Rate-Limit", "200") + return nil + }) + r, _ := newRequest("GET", "/flats/{id}/", reqWrtr) + _ = r.SetHeaderParam(runtime.HeaderContentType, runtime.XMLMime) + + req, err := r.BuildHTTP(runtime.XMLMime, testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "200", req.Header.Get("x-rate-limit")) + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "/flats/1234/", req.URL.Path) + expectedBody, _ := xml.Marshal(bd) + actualBody, _ := ioutil.ReadAll(req.Body) + assert.Equal(t, expectedBody, actualBody) + } +} + +func TestBuildRequest_BuildHTTP_TextPayload(t *testing.T) { + bd := "Tom: Organ trail; John: Bird watching" + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetBodyParam(bd) + _ = req.SetQueryParam("hello", "world") + _ = req.SetPathParam("id", "1234") + _ = req.SetHeaderParam("X-Rate-Limit", "200") + return nil + }) + r, _ := newRequest("GET", "/flats/{id}/", reqWrtr) + _ = r.SetHeaderParam(runtime.HeaderContentType, runtime.TextMime) + + req, err := r.BuildHTTP(runtime.TextMime, testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "200", req.Header.Get("x-rate-limit")) + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "/flats/1234/", req.URL.Path) + expectedBody := []byte(bd) + actualBody, _ := ioutil.ReadAll(req.Body) + assert.Equal(t, expectedBody, actualBody) + } +} + +func TestBuildRequest_BuildHTTP_Form(t *testing.T) { + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetFormParam("something", "some value") + _ = req.SetQueryParam("hello", "world") + _ = req.SetPathParam("id", "1234") + _ = req.SetHeaderParam("X-Rate-Limit", "200") + return nil + }) + r, _ := newRequest("GET", "/flats/{id}/", reqWrtr) + _ = r.SetHeaderParam(runtime.HeaderContentType, runtime.JSONMime) + + req, err := r.BuildHTTP(runtime.JSONMime, testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "200", req.Header.Get("x-rate-limit")) + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "/flats/1234/", req.URL.Path) + expected := []byte("something=some+value") + actual, _ := ioutil.ReadAll(req.Body) + assert.Equal(t, expected, actual) + } +} + +func TestBuildRequest_BuildHTTP_Form_Content_Length(t *testing.T) { + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetFormParam("something", "some value") + _ = req.SetQueryParam("hello", "world") + _ = req.SetPathParam("id", "1234") + _ = req.SetHeaderParam("X-Rate-Limit", "200") + return nil + }) + r, _ := newRequest("GET", "/flats/{id}/", reqWrtr) + _ = r.SetHeaderParam(runtime.HeaderContentType, runtime.MultipartFormMime) + + req, err := r.BuildHTTP(runtime.JSONMime, testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "200", req.Header.Get("x-rate-limit")) + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "/flats/1234/", req.URL.Path) + assert.Condition(t, func() bool { return req.ContentLength > 0 }, + "ContentLength must great than 0. got %d", req.ContentLength) + expected := []byte("something=some+value") + actual, _ := ioutil.ReadAll(req.Body) + assert.Equal(t, expected, actual) + } +} + +func TestBuildRequest_BuildHTTP_Files(t *testing.T) { + cont, _ := ioutil.ReadFile("./runtime.go") + reqWrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, reg strfmt.Registry) error { + _ = req.SetFormParam("something", "some value") + _ = req.SetFileParam("file", mustGetFile("./runtime.go")) + _ = req.SetQueryParam("hello", "world") + _ = req.SetPathParam("id", "1234") + _ = req.SetHeaderParam("X-Rate-Limit", "200") + return nil + }) + r, _ := newRequest("GET", "/flats/{id}/", reqWrtr) + _ = r.SetHeaderParam(runtime.HeaderContentType, runtime.JSONMime) + req, err := r.BuildHTTP(runtime.JSONMime, testProducers, nil) + if assert.NoError(t, err) && assert.NotNil(t, req) { + assert.Equal(t, "200", req.Header.Get("x-rate-limit")) + assert.Equal(t, "world", req.URL.Query().Get("hello")) + assert.Equal(t, "/flats/1234/", req.URL.Path) + mediaType, params, err := mime.ParseMediaType(req.Header.Get(runtime.HeaderContentType)) + if assert.NoError(t, err) { + assert.Equal(t, runtime.MultipartFormMime, mediaType) + boundary := params["boundary"] + mr := multipart.NewReader(req.Body, boundary) + defer req.Body.Close() + frm, err := mr.ReadForm(1 << 20) + if assert.NoError(t, err) { + assert.Equal(t, "some value", frm.Value["something"][0]) + mpff := frm.File["file"][0] + mpf, _ := mpff.Open() + defer mpf.Close() + assert.Equal(t, "runtime.go", mpff.Filename) + actual, _ := ioutil.ReadAll(mpf) + assert.Equal(t, cont, actual) + } + } + } +} diff --git a/vendor/github.com/go-openapi/runtime/client/response.go b/vendor/github.com/go-openapi/runtime/client/response.go new file mode 100644 index 0000000000..bd238588b7 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/response.go @@ -0,0 +1,44 @@ +// 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 client + +import ( + "io" + "net/http" + + "github.com/go-openapi/runtime" +) + +var _ runtime.ClientResponse = response{} + +type response struct { + resp *http.Response +} + +func (r response) Code() int { + return r.resp.StatusCode +} + +func (r response) Message() string { + return r.resp.Status +} + +func (r response) GetHeader(name string) string { + return r.resp.Header.Get(name) +} + +func (r response) Body() io.ReadCloser { + return r.resp.Body +} diff --git a/vendor/github.com/go-openapi/runtime/client/response_test.go b/vendor/github.com/go-openapi/runtime/client/response_test.go new file mode 100644 index 0000000000..6b63426ad6 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/response_test.go @@ -0,0 +1,40 @@ +// 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 client + +import ( + "bytes" + "io/ioutil" + "net/http" + "testing" + + "github.com/go-openapi/runtime" + "github.com/stretchr/testify/assert" +) + +func TestResponse(t *testing.T) { + under := new(http.Response) + under.Status = "the status message" + under.StatusCode = 392 + under.Header = make(http.Header) + under.Header.Set("Blah", "blah blah") + under.Body = ioutil.NopCloser(bytes.NewBufferString("some content")) + + var resp runtime.ClientResponse = response{under} + assert.EqualValues(t, under.StatusCode, resp.Code()) + assert.Equal(t, under.Status, resp.Message()) + assert.Equal(t, "blah blah", resp.GetHeader("blah")) + assert.Equal(t, under.Body, resp.Body()) +} diff --git a/vendor/github.com/go-openapi/runtime/client/runtime.go b/vendor/github.com/go-openapi/runtime/client/runtime.go new file mode 100644 index 0000000000..69e33e802d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/runtime.go @@ -0,0 +1,330 @@ +// 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 client + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "io/ioutil" + "mime" + "net/http" + "net/http/httputil" + "os" + "path" + "strings" + "sync" + "time" + + "golang.org/x/net/context" + "golang.org/x/net/context/ctxhttp" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" +) + +// TLSClientOptions to configure client authentication with mutual TLS +type TLSClientOptions struct { + Certificate string + Key string + CA string + ServerName string + InsecureSkipVerify bool + _ struct{} +} + +// TLSClientAuth creates a tls.Config for mutual auth +func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) { + // create client tls config + cfg := &tls.Config{} + + // load client cert if specified + if opts.Certificate != "" { + cert, err := tls.LoadX509KeyPair(opts.Certificate, opts.Key) + if err != nil { + return nil, fmt.Errorf("tls client cert: %v", err) + } + cfg.Certificates = []tls.Certificate{cert} + } + + cfg.InsecureSkipVerify = opts.InsecureSkipVerify + + // 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.CA != "" { + // load ca cert + caCert, err := ioutil.ReadFile(opts.CA) + if err != nil { + return nil, fmt.Errorf("tls client ca: %v", err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + cfg.RootCAs = caCertPool + } + + // apply servername overrride + if opts.ServerName != "" { + cfg.InsecureSkipVerify = false + cfg.ServerName = opts.ServerName + } + + cfg.BuildNameToCertificate() + + return cfg, nil +} + +// TLSTransport creates a http client transport suitable for mutual tls auth +func TLSTransport(opts TLSClientOptions) (http.RoundTripper, error) { + cfg, err := TLSClientAuth(opts) + if err != nil { + return nil, err + } + + return &http.Transport{TLSClientConfig: cfg}, nil +} + +// TLSClient creates a http.Client for mutual auth +func TLSClient(opts TLSClientOptions) (*http.Client, error) { + transport, err := TLSTransport(opts) + if err != nil { + return nil, err + } + return &http.Client{Transport: transport}, nil +} + +// DefaultTimeout the default request timeout +var DefaultTimeout = 30 * time.Second + +// Runtime represents an API client that uses the transport +// to make http requests based on a swagger specification. +type Runtime struct { + DefaultMediaType string + DefaultAuthentication runtime.ClientAuthInfoWriter + Consumers map[string]runtime.Consumer + Producers map[string]runtime.Producer + + Transport http.RoundTripper + Jar http.CookieJar + //Spec *spec.Document + Host string + BasePath string + Formats strfmt.Registry + Debug bool + Context context.Context + + clientOnce *sync.Once + client *http.Client + schemes []string + do func(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) +} + +// New creates a new default runtime for a swagger api runtime.Client +func New(host, basePath string, schemes []string) *Runtime { + var rt Runtime + rt.DefaultMediaType = runtime.JSONMime + + // TODO: actually infer this stuff from the spec + rt.Consumers = map[string]runtime.Consumer{ + runtime.JSONMime: runtime.JSONConsumer(), + runtime.XMLMime: runtime.XMLConsumer(), + runtime.TextMime: runtime.TextConsumer(), + runtime.DefaultMime: runtime.ByteStreamConsumer(), + } + rt.Producers = map[string]runtime.Producer{ + runtime.JSONMime: runtime.JSONProducer(), + runtime.XMLMime: runtime.XMLProducer(), + runtime.TextMime: runtime.TextProducer(), + runtime.DefaultMime: runtime.ByteStreamProducer(), + } + rt.Transport = http.DefaultTransport + rt.Jar = nil + rt.Host = host + rt.BasePath = basePath + rt.Context = context.Background() + rt.clientOnce = new(sync.Once) + if !strings.HasPrefix(rt.BasePath, "/") { + rt.BasePath = "/" + rt.BasePath + } + rt.Debug = len(os.Getenv("DEBUG")) > 0 + if len(schemes) > 0 { + rt.schemes = schemes + } + rt.do = ctxhttp.Do + return &rt +} + +// NewWithClient allows you to create a new transport with a configured http.Client +func NewWithClient(host, basePath string, schemes []string, client *http.Client) *Runtime { + rt := New(host, basePath, schemes) + if client != nil { + rt.clientOnce.Do(func() { + rt.client = client + }) + } + return rt +} + +func (r *Runtime) pickScheme(schemes []string) string { + if v := r.selectScheme(r.schemes); v != "" { + return v + } + if v := r.selectScheme(schemes); v != "" { + return v + } + return "http" +} + +func (r *Runtime) selectScheme(schemes []string) string { + schLen := len(schemes) + if schLen == 0 { + return "" + } + + scheme := schemes[0] + // prefer https, but skip when not possible + if scheme != "https" && schLen > 1 { + for _, sch := range schemes { + if sch == "https" { + scheme = sch + break + } + } + } + return scheme +} + +// Submit a request and when there is a body on success it will turn that into the result +// all other things are turned into an api error for swagger which retains the status code +func (r *Runtime) Submit(operation *runtime.ClientOperation) (interface{}, error) { + params, readResponse, auth := operation.Params, operation.Reader, operation.AuthInfo + + request, err := newRequest(operation.Method, operation.PathPattern, params) + if err != nil { + return nil, err + } + + var accept []string + accept = append(accept, operation.ProducesMediaTypes...) + if err = request.SetHeaderParam(runtime.HeaderAccept, accept...); err != nil { + return nil, err + } + + if auth == nil && r.DefaultAuthentication != nil { + auth = r.DefaultAuthentication + } + if auth != nil { + if err := auth.AuthenticateRequest(request, r.Formats); err != nil { + return nil, err + } + } + + // TODO: pick appropriate media type + cmt := r.DefaultMediaType + for _, mediaType := range operation.ConsumesMediaTypes { + // Pick first non-empty media type + if mediaType != "" { + cmt = mediaType + break + } + } + + req, err := request.BuildHTTP(cmt, r.Producers, r.Formats) + if err != nil { + return nil, err + } + req.URL.Scheme = r.pickScheme(operation.Schemes) + req.URL.Host = r.Host + var reinstateSlash bool + if req.URL.Path != "" && req.URL.Path != "/" && req.URL.Path[len(req.URL.Path)-1] == '/' { + reinstateSlash = true + } + req.URL.Path = path.Join(r.BasePath, req.URL.Path) + if reinstateSlash { + req.URL.Path = req.URL.Path + "/" + } + + r.clientOnce.Do(func() { + r.client = &http.Client{ + Transport: r.Transport, + Jar: r.Jar, + } + }) + + if r.Debug { + b, err2 := httputil.DumpRequestOut(req, true) + if err2 != nil { + return nil, err2 + } + fmt.Fprintln(os.Stderr, string(b)) + } + + var hasTimeout bool + pctx := operation.Context + if pctx == nil { + pctx = r.Context + } else { + hasTimeout = true + } + if pctx == nil { + pctx = context.Background() + } + var ctx context.Context + var cancel context.CancelFunc + if hasTimeout { + ctx, cancel = context.WithCancel(pctx) + } else { + ctx, cancel = context.WithTimeout(pctx, request.timeout) + } + defer cancel() + + client := operation.Client + if client == nil { + client = r.client + } + if r.do == nil { + r.do = ctxhttp.Do + } + res, err := r.do(ctx, client, req) // make requests, by default follows 10 redirects before failing + if err != nil { + return nil, err + } + defer res.Body.Close() + + if r.Debug { + b, err2 := httputil.DumpResponse(res, true) + if err2 != nil { + return nil, err2 + } + fmt.Fprintln(os.Stderr, string(b)) + } + + ct := res.Header.Get(runtime.HeaderContentType) + if ct == "" { // this should really really never occur + ct = r.DefaultMediaType + } + + mt, _, err := mime.ParseMediaType(ct) + if err != nil { + return nil, fmt.Errorf("parse content type: %s", err) + } + + cons, ok := r.Consumers[mt] + if !ok { + // scream about not knowing what to do + return nil, fmt.Errorf("no consumer: %q", ct) + } + return readResponse.ReadResponse(response{res}, cons) +} diff --git a/vendor/github.com/go-openapi/runtime/client/runtime_test.go b/vendor/github.com/go-openapi/runtime/client/runtime_test.go new file mode 100644 index 0000000000..1d878f22f1 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client/runtime_test.go @@ -0,0 +1,721 @@ +// 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 client + +import ( + "bytes" + "encoding/json" + "encoding/xml" + "errors" + "io/ioutil" + "net/http" + "net/http/cookiejar" + "net/http/httptest" + "net/url" + "os" + "testing" + "time" + + "golang.org/x/net/context" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +// task This describes a task. Tasks require a content property to be set. +type task struct { + + // Completed + Completed bool `json:"completed" xml:"completed"` + + // Content Task content can contain [GFM](https://help.github.com/articles/github-flavored-markdown/). + Content string `json:"content" xml:"content"` + + // ID This id property is autogenerated when a task is created. + ID int64 `json:"id" xml:"id"` +} + +func TestRuntime_TLSAuthConfig(t *testing.T) { + var opts TLSClientOptions + opts.CA = "../fixtures/certs/myCA.crt" + opts.Key = "../fixtures/certs/myclient.key" + opts.Certificate = "../fixtures/certs/myclient.crt" + opts.ServerName = "somewhere" + + cfg, err := TLSClientAuth(opts) + if assert.NoError(t, err) { + if assert.NotNil(t, cfg) { + assert.Len(t, cfg.Certificates, 1) + assert.NotNil(t, cfg.RootCAs) + assert.Equal(t, "somewhere", cfg.ServerName) + } + } +} + +func TestRuntime_Concurrent(t *testing.T) { + // test that it can make a simple request + // and get the response for it. + // defaults all the way down + result := []task{ + {false, "task 1 content", 1}, + {false, "task 2 content", 2}, + } + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime) + rw.WriteHeader(http.StatusOK) + jsongen := json.NewEncoder(rw) + _ = jsongen.Encode(result) + })) + defer server.Close() + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + hu, _ := url.Parse(server.URL) + rt := New(hu.Host, "/", []string{"http"}) + resCC := make(chan interface{}) + errCC := make(chan error) + var res interface{} + var err error + + for j := 0; j < 6; j++ { + go func() { + resC := make(chan interface{}) + errC := make(chan error) + + go func() { + var resp interface{} + var errp error + for i := 0; i < 3; i++ { + resp, errp = rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "GET", + PathPattern: "/", + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + var result []task + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + }) + <-time.After(100 * time.Millisecond) + } + resC <- resp + errC <- errp + }() + resCC <- <-resC + errCC <- <-errC + }() + } + + c := 6 + for c > 0 { + res = <-resCC + err = <-errCC + c-- + } + + if assert.NoError(t, err) { + assert.IsType(t, []task{}, res) + actual := res.([]task) + assert.EqualValues(t, result, actual) + } +} + +func TestRuntime_Canary(t *testing.T) { + // test that it can make a simple request + // and get the response for it. + // defaults all the way down + result := []task{ + {false, "task 1 content", 1}, + {false, "task 2 content", 2}, + } + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime) + rw.WriteHeader(http.StatusOK) + jsongen := json.NewEncoder(rw) + _ = jsongen.Encode(result) + })) + defer server.Close() + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + hu, _ := url.Parse(server.URL) + rt := New(hu.Host, "/", []string{"http"}) + res, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "GET", + PathPattern: "/", + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + var result []task + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + }) + + if assert.NoError(t, err) { + assert.IsType(t, []task{}, res) + actual := res.([]task) + assert.EqualValues(t, result, actual) + } +} + +type tasks struct { + Tasks []task `xml:"task"` +} + +func TestRuntime_XMLCanary(t *testing.T) { + // test that it can make a simple XML request + // and get the response for it. + result := tasks{ + Tasks: []task{ + {false, "task 1 content", 1}, + {false, "task 2 content", 2}, + }, + } + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Add(runtime.HeaderContentType, runtime.XMLMime) + rw.WriteHeader(http.StatusOK) + xmlgen := xml.NewEncoder(rw) + _ = xmlgen.Encode(result) + })) + defer server.Close() + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + hu, _ := url.Parse(server.URL) + rt := New(hu.Host, "/", []string{"http"}) + res, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "GET", + PathPattern: "/", + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + var result tasks + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + }) + + if assert.NoError(t, err) { + assert.IsType(t, tasks{}, res) + actual := res.(tasks) + assert.EqualValues(t, result, actual) + } +} + +func TestRuntime_TextCanary(t *testing.T) { + // test that it can make a simple text request + // and get the response for it. + result := "1: task 1 content; 2: task 2 content" + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Add(runtime.HeaderContentType, runtime.TextMime) + rw.WriteHeader(http.StatusOK) + _, _ = rw.Write([]byte(result)) + })) + defer server.Close() + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + hu, _ := url.Parse(server.URL) + rt := New(hu.Host, "/", []string{"http"}) + res, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "GET", + PathPattern: "/", + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + var result string + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + }) + + if assert.NoError(t, err) { + assert.IsType(t, "", res) + actual := res.(string) + assert.EqualValues(t, result, actual) + } +} + +type roundTripperFunc func(*http.Request) (*http.Response, error) + +func (fn roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) { + return fn(req) +} + +func TestRuntime_CustomTransport(t *testing.T) { + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + result := []task{ + {false, "task 1 content", 1}, + {false, "task 2 content", 2}, + } + + rt := New("localhost:3245", "/", []string{"ws", "wss", "https"}) + rt.Transport = roundTripperFunc(func(req *http.Request) (*http.Response, error) { + if req.URL.Scheme != "https" { + return nil, errors.New("this was not a https request") + } + var resp http.Response + resp.StatusCode = 200 + resp.Header = make(http.Header) + resp.Header.Set("content-type", "application/json") + buf := bytes.NewBuffer(nil) + enc := json.NewEncoder(buf) + _ = enc.Encode(result) + resp.Body = ioutil.NopCloser(buf) + return &resp, nil + }) + + res, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "GET", + PathPattern: "/", + Schemes: []string{"ws", "wss", "https"}, + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + var result []task + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + }) + + if assert.NoError(t, err) { + assert.IsType(t, []task{}, res) + actual := res.([]task) + assert.EqualValues(t, result, actual) + } +} + +func TestRuntime_CustomCookieJar(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + authenticated := false + for _, cookie := range req.Cookies() { + if cookie.Name == "sessionid" && cookie.Value == "abc" { + authenticated = true + } + } + if !authenticated { + username, password, ok := req.BasicAuth() + if ok && username == "username" && password == "password" { + authenticated = true + http.SetCookie(rw, &http.Cookie{Name: "sessionid", Value: "abc"}) + } + } + if authenticated { + rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime) + rw.WriteHeader(http.StatusOK) + jsongen := json.NewEncoder(rw) + _ = jsongen.Encode([]task{}) + } else { + rw.WriteHeader(http.StatusUnauthorized) + } + })) + defer server.Close() + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + hu, _ := url.Parse(server.URL) + rt := New(hu.Host, "/", []string{"http"}) + rt.Jar, _ = cookiejar.New(nil) + + submit := func(authInfo runtime.ClientAuthInfoWriter) { + _, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "GET", + PathPattern: "/", + Params: rwrtr, + AuthInfo: authInfo, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + return nil, nil + } + return nil, errors.New("Generic error") + }), + }) + + assert.NoError(t, err) + } + + submit(BasicAuth("username", "password")) + submit(nil) +} + +func TestRuntime_AuthCanary(t *testing.T) { + // test that it can make a simple request + // and get the response for it. + // defaults all the way down + result := []task{ + {false, "task 1 content", 1}, + {false, "task 2 content", 2}, + } + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + if req.Header.Get("Authorization") != "Bearer the-super-secret-token" { + rw.WriteHeader(400) + return + } + rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime) + rw.WriteHeader(http.StatusOK) + jsongen := json.NewEncoder(rw) + _ = jsongen.Encode(result) + })) + defer server.Close() + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + hu, _ := url.Parse(server.URL) + + rt := New(hu.Host, "/", []string{"http"}) + res, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + var result []task + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + AuthInfo: BearerToken("the-super-secret-token"), + }) + + if assert.NoError(t, err) { + assert.IsType(t, []task{}, res) + actual := res.([]task) + assert.EqualValues(t, result, actual) + } +} + +func TestRuntime_PickConsumer(t *testing.T) { + result := []task{ + {false, "task 1 content", 1}, + {false, "task 2 content", 2}, + } + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + if req.Header.Get("Content-Type") != "application/octet-stream" { + rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8") + rw.WriteHeader(400) + return + } + rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8") + rw.WriteHeader(http.StatusOK) + jsongen := json.NewEncoder(rw) + _ = jsongen.Encode(result) + })) + defer server.Close() + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return req.SetBodyParam(bytes.NewBufferString("hello")) + }) + + hu, _ := url.Parse(server.URL) + rt := New(hu.Host, "/", []string{"http"}) + res, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "POST", + PathPattern: "/", + Schemes: []string{"http"}, + ConsumesMediaTypes: []string{"application/octet-stream"}, + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + var result []task + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + AuthInfo: BearerToken("the-super-secret-token"), + }) + + if assert.NoError(t, err) { + assert.IsType(t, []task{}, res) + actual := res.([]task) + assert.EqualValues(t, result, actual) + } +} + +func TestRuntime_ContentTypeCanary(t *testing.T) { + // test that it can make a simple request + // and get the response for it. + // defaults all the way down + result := []task{ + {false, "task 1 content", 1}, + {false, "task 2 content", 2}, + } + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + if req.Header.Get("Authorization") != "Bearer the-super-secret-token" { + rw.WriteHeader(400) + return + } + rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8") + rw.WriteHeader(http.StatusOK) + jsongen := json.NewEncoder(rw) + _ = jsongen.Encode(result) + })) + defer server.Close() + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + hu, _ := url.Parse(server.URL) + rt := New(hu.Host, "/", []string{"http"}) + rt.do = nil + res, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "GET", + PathPattern: "/", + Schemes: []string{"http"}, + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + var result []task + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + AuthInfo: BearerToken("the-super-secret-token"), + }) + + if assert.NoError(t, err) { + assert.IsType(t, []task{}, res) + actual := res.([]task) + assert.EqualValues(t, result, actual) + } +} + +func TestRuntime_ChunkedResponse(t *testing.T) { + // test that it can make a simple request + // and get the response for it. + // defaults all the way down + result := []task{ + {false, "task 1 content", 1}, + {false, "task 2 content", 2}, + } + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + if req.Header.Get("Authorization") != "Bearer the-super-secret-token" { + rw.WriteHeader(400) + return + } + rw.Header().Add(runtime.HeaderTransferEncoding, "chunked") + rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8") + rw.WriteHeader(http.StatusOK) + jsongen := json.NewEncoder(rw) + _ = jsongen.Encode(result) + })) + defer server.Close() + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + //specDoc, err := spec.Load("../../fixtures/codegen/todolist.simple.yml") + hu, _ := url.Parse(server.URL) + + rt := New(hu.Host, "/", []string{"http"}) + res, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "GET", + PathPattern: "/", + Schemes: []string{"http"}, + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if response.Code() == 200 { + var result []task + if err := consumer.Consume(response.Body(), &result); err != nil { + return nil, err + } + return result, nil + } + return nil, errors.New("Generic error") + }), + AuthInfo: BearerToken("the-super-secret-token"), + }) + + if assert.NoError(t, err) { + assert.IsType(t, []task{}, res) + actual := res.([]task) + assert.EqualValues(t, result, actual) + } +} + +func TestRuntime_DebugValue(t *testing.T) { + original := os.Getenv("DEBUG") + + // Emtpy DEBUG means Debug is False + _ = os.Setenv("DEBUG", "") + runtime := New("", "/", []string{"https"}) + assert.False(t, runtime.Debug) + + // Non-Empty Debug means Debug is True + + _ = os.Setenv("DEBUG", "1") + runtime = New("", "/", []string{"https"}) + assert.True(t, runtime.Debug) + + _ = os.Setenv("DEBUG", "true") + runtime = New("", "/", []string{"https"}) + assert.True(t, runtime.Debug) + + _ = os.Setenv("DEBUG", "foo") + runtime = New("", "/", []string{"https"}) + assert.True(t, runtime.Debug) + + // Make sure DEBUG is initial value once again + _ = os.Setenv("DEBUG", original) +} + +func TestRuntime_OverrideScheme(t *testing.T) { + runtime := New("", "/", []string{"https"}) + sch := runtime.pickScheme([]string{"http"}) + assert.Equal(t, "https", sch) +} + +func TestRuntime_OverrideClient(t *testing.T) { + client := &http.Client{} + runtime := NewWithClient("", "/", []string{"https"}, client) + var i int + runtime.clientOnce.Do(func() { i++ }) + assert.Equal(t, client, runtime.client) + assert.Equal(t, 0, i) +} + +func TestRuntime_OverrideClientOperation(t *testing.T) { + client := &http.Client{} + rt := NewWithClient("", "/", []string{"https"}, client) + var i int + rt.clientOnce.Do(func() { i++ }) + assert.Equal(t, client, rt.client) + assert.Equal(t, 0, i) + + var seen *http.Client + rt.do = func(_ context.Context, cl *http.Client, _ *http.Request) (*http.Response, error) { + seen = cl + res := new(http.Response) + res.StatusCode = 200 + res.Body = ioutil.NopCloser(bytes.NewBufferString("OK")) + return res, nil + } + + client2 := new(http.Client) + client2.Timeout = 3 * time.Second + if assert.NotEqual(t, client, client2) { + _, err := rt.Submit(&runtime.ClientOperation{ + Client: client2, + Params: runtime.ClientRequestWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }), + Reader: runtime.ClientResponseReaderFunc(func(_ runtime.ClientResponse, _ runtime.Consumer) (interface{}, error) { + return nil, nil + }), + }) + if assert.NoError(t, err) { + + assert.Equal(t, client2, seen) + } + } +} + +func TestRuntime_PreserveTrailingSlash(t *testing.T) { + var redirected bool + + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime+";charset=utf-8") + + if req.URL.Path == "/api/tasks" { + redirected = true + return + } + if req.URL.Path == "/api/tasks/" { + rw.WriteHeader(http.StatusOK) + } + })) + defer server.Close() + + hu, _ := url.Parse(server.URL) + + rt := New(hu.Host, "/", []string{"http"}) + + rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error { + return nil + }) + + _, err := rt.Submit(&runtime.ClientOperation{ + ID: "getTasks", + Method: "GET", + PathPattern: "/api/tasks/", + Params: rwrtr, + Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + if redirected { + return nil, errors.New("expected Submit to preserve trailing slashes - this caused a redirect") + } + if response.Code() == http.StatusOK { + return nil, nil + } + return nil, errors.New("Generic error") + }), + }) + + assert.NoError(t, err) +} diff --git a/vendor/github.com/go-openapi/runtime/client_auth_info.go b/vendor/github.com/go-openapi/runtime/client_auth_info.go new file mode 100644 index 0000000000..c6c97d9a7c --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client_auth_info.go @@ -0,0 +1,30 @@ +// 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 runtime + +import "github.com/go-openapi/strfmt" + +// A ClientAuthInfoWriterFunc converts a function to a request writer interface +type ClientAuthInfoWriterFunc func(ClientRequest, strfmt.Registry) error + +// AuthenticateRequest adds authentication data to the request +func (fn ClientAuthInfoWriterFunc) AuthenticateRequest(req ClientRequest, reg strfmt.Registry) error { + return fn(req, reg) +} + +// A ClientAuthInfoWriter implementor knows how to write authentication info to a request +type ClientAuthInfoWriter interface { + AuthenticateRequest(ClientRequest, strfmt.Registry) error +} diff --git a/vendor/github.com/go-openapi/runtime/client_operation.go b/vendor/github.com/go-openapi/runtime/client_operation.go new file mode 100644 index 0000000000..ccf8ff7227 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client_operation.go @@ -0,0 +1,42 @@ +// 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 runtime + +import ( + "net/http" + + "golang.org/x/net/context" +) + +// ClientOperation represents the context for a swagger operation to be submitted to the transport +type ClientOperation struct { + ID string + Method string + PathPattern string + ProducesMediaTypes []string + ConsumesMediaTypes []string + Schemes []string + AuthInfo ClientAuthInfoWriter + Params ClientRequestWriter + Reader ClientResponseReader + Context context.Context + Client *http.Client +} + +// A ClientTransport implementor knows how to submit Request objects to some destination +type ClientTransport interface { + //Submit(string, RequestWriter, ResponseReader, AuthInfoWriter) (interface{}, error) + Submit(*ClientOperation) (interface{}, error) +} diff --git a/vendor/github.com/go-openapi/runtime/client_request.go b/vendor/github.com/go-openapi/runtime/client_request.go new file mode 100644 index 0000000000..3cf12b6c28 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client_request.go @@ -0,0 +1,59 @@ +// 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 runtime + +import ( + "io" + "time" + + "github.com/go-openapi/strfmt" +) + +// ClientRequestWriterFunc converts a function to a request writer interface +type ClientRequestWriterFunc func(ClientRequest, strfmt.Registry) error + +// WriteToRequest adds data to the request +func (fn ClientRequestWriterFunc) WriteToRequest(req ClientRequest, reg strfmt.Registry) error { + return fn(req, reg) +} + +// ClientRequestWriter is an interface for things that know how to write to a request +type ClientRequestWriter interface { + WriteToRequest(ClientRequest, strfmt.Registry) error +} + +// ClientRequest is an interface for things that know how to +// add information to a swagger client request +type ClientRequest interface { + SetHeaderParam(string, ...string) error + + SetQueryParam(string, ...string) error + + SetFormParam(string, ...string) error + + SetPathParam(string, string) error + + SetFileParam(string, NamedReadCloser) error + + SetBodyParam(interface{}) error + + SetTimeout(time.Duration) error +} + +// NamedReadCloser represents a named ReadCloser interface +type NamedReadCloser interface { + io.ReadCloser + Name() string +} diff --git a/vendor/github.com/go-openapi/runtime/client_request_test.go b/vendor/github.com/go-openapi/runtime/client_request_test.go new file mode 100644 index 0000000000..ea93401d30 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client_request_test.go @@ -0,0 +1,68 @@ +// 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 runtime + +import ( + "net/http" + "testing" + "time" + + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +type trw struct { + Headers http.Header + Body interface{} +} + +func (t *trw) SetHeaderParam(name string, values ...string) error { + if t.Headers == nil { + t.Headers = make(http.Header) + } + t.Headers.Set(name, values[0]) + return nil +} + +func (t *trw) SetQueryParam(_ string, _ ...string) error { return nil } + +func (t *trw) SetFormParam(_ string, _ ...string) error { return nil } + +func (t *trw) SetPathParam(_ string, _ string) error { return nil } + +func (t *trw) SetFileParam(_ string, _ NamedReadCloser) error { return nil } + +func (t *trw) SetBodyParam(body interface{}) error { + t.Body = body + return nil +} + +func (t *trw) SetTimeout(timeout time.Duration) error { + return nil +} + +func TestRequestWriterFunc(t *testing.T) { + + hand := ClientRequestWriterFunc(func(r ClientRequest, reg strfmt.Registry) error { + _ = r.SetHeaderParam("blah", "blah blah") + _ = r.SetBodyParam(struct{ Name string }{"Adriana"}) + return nil + }) + + tr := new(trw) + _ = hand.WriteToRequest(tr, nil) + assert.Equal(t, "blah blah", tr.Headers.Get("blah")) + assert.Equal(t, "Adriana", tr.Body.(struct{ Name string }).Name) +} diff --git a/vendor/github.com/go-openapi/runtime/client_response.go b/vendor/github.com/go-openapi/runtime/client_response.go new file mode 100644 index 0000000000..729e18b228 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client_response.go @@ -0,0 +1,63 @@ +// 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 runtime + +import ( + "fmt" + "io" +) + +// A ClientResponse represents a client response +// This bridges between responses obtained from different transports +type ClientResponse interface { + Code() int + Message() string + GetHeader(string) string + Body() io.ReadCloser +} + +// A ClientResponseReaderFunc turns a function into a ClientResponseReader interface implementation +type ClientResponseReaderFunc func(ClientResponse, Consumer) (interface{}, error) + +// ReadResponse reads the response +func (read ClientResponseReaderFunc) ReadResponse(resp ClientResponse, consumer Consumer) (interface{}, error) { + return read(resp, consumer) +} + +// A ClientResponseReader is an interface for things want to read a response. +// An application of this is to create structs from response values +type ClientResponseReader interface { + ReadResponse(ClientResponse, Consumer) (interface{}, error) +} + +// NewAPIError creates a new API error +func NewAPIError(opName string, payload interface{}, code int) *APIError { + return &APIError{ + OperationName: opName, + Response: payload, + Code: code, + } +} + +// APIError wraps an error model and captures the status code +type APIError struct { + OperationName string + Response interface{} + Code int +} + +func (a *APIError) Error() string { + return fmt.Sprintf("%s (status %d): %+v ", a.OperationName, a.Code, a.Response) +} diff --git a/vendor/github.com/go-openapi/runtime/client_response_test.go b/vendor/github.com/go-openapi/runtime/client_response_test.go new file mode 100644 index 0000000000..7422d349d5 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/client_response_test.go @@ -0,0 +1,60 @@ +// 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 runtime + +import ( + "bytes" + "io" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/assert" +) + +type response struct { +} + +func (r response) Code() int { + return 490 +} +func (r response) Message() string { + return "the message" +} +func (r response) GetHeader(_ string) string { + return "the header" +} +func (r response) Body() io.ReadCloser { + return ioutil.NopCloser(bytes.NewBufferString("the content")) +} + +func TestResponseReaderFunc(t *testing.T) { + var actual struct { + Header, Message, Body string + Code int + } + reader := ClientResponseReaderFunc(func(r ClientResponse, _ Consumer) (interface{}, error) { + b, _ := ioutil.ReadAll(r.Body()) + actual.Body = string(b) + actual.Code = r.Code() + actual.Message = r.Message() + actual.Header = r.GetHeader("blah") + return actual, nil + }) + _, _ = reader.ReadResponse(response{}, nil) + assert.Equal(t, "the content", actual.Body) + assert.Equal(t, "the message", actual.Message) + assert.Equal(t, "the header", actual.Header) + assert.Equal(t, 490, actual.Code) +} diff --git a/vendor/github.com/go-openapi/runtime/constants.go b/vendor/github.com/go-openapi/runtime/constants.go new file mode 100644 index 0000000000..04edda7131 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/constants.go @@ -0,0 +1,41 @@ +// 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 runtime + +const ( + // HeaderContentType represents a http content-type header, it's value is supposed to be a mime type + HeaderContentType = "Content-Type" + + // HeaderTransferEncoding represents a http transfer-encoding header. + HeaderTransferEncoding = "Transfer-Encoding" + + // HeaderAccept the Accept header + HeaderAccept = "Accept" + + charsetKey = "charset" + + // DefaultMime the default fallback mime type + DefaultMime = "application/octet-stream" + // JSONMime the json mime type + JSONMime = "application/json" + // YAMLMime the yaml mime type + YAMLMime = "application/x-yaml" + // XMLMime the xml mime type + XMLMime = "application/xml" + // TextMime the text mime type + TextMime = "text/plain" + // MultipartFormMime the multipart form mime type + MultipartFormMime = "multipart/form-data" +) diff --git a/vendor/github.com/go-openapi/runtime/discard.go b/vendor/github.com/go-openapi/runtime/discard.go new file mode 100644 index 0000000000..0d390cfd64 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/discard.go @@ -0,0 +1,9 @@ +package runtime + +import "io" + +// DiscardConsumer does absolutely nothing, it's a black hole. +var DiscardConsumer = ConsumerFunc(func(_ io.Reader, _ interface{}) error { return nil }) + +// DiscardProducer does absolutely nothing, it's a black hole. +var DiscardProducer = ProducerFunc(func(_ io.Writer, _ interface{}) error { return nil }) diff --git a/vendor/github.com/go-openapi/runtime/file.go b/vendor/github.com/go-openapi/runtime/file.go new file mode 100644 index 0000000000..d1c51ebb3b --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/file.go @@ -0,0 +1,27 @@ +// 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 runtime + +import "mime/multipart" + +// File represents an uploaded file. +type File struct { + Data multipart.File + Header *multipart.FileHeader +} + +func (f File) Read(p []byte) (n int, err error) { + return f.Data.Read(p) +} diff --git a/vendor/github.com/go-openapi/runtime/file_test.go b/vendor/github.com/go-openapi/runtime/file_test.go new file mode 100644 index 0000000000..bbe85f064e --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/file_test.go @@ -0,0 +1,14 @@ +package runtime + +import ( + "github.com/stretchr/testify/assert" + "io" + "testing" +) + +func TestFileImplementsIOReader(t *testing.T) { + var file interface{} = File{} + expected := "that File implements io.Reader" + _, ok := file.(io.Reader) + assert.True(t, ok, expected) +} diff --git a/vendor/github.com/go-openapi/runtime/fixtures/bugs/264/swagger.yml b/vendor/github.com/go-openapi/runtime/fixtures/bugs/264/swagger.yml new file mode 100644 index 0000000000..e26cd855ce --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/bugs/264/swagger.yml @@ -0,0 +1,21 @@ +swagger: '2.0' +info: + version: 1.0.0 + title: 'Test' +schemes: + - http +produces: + - application/json +consumes: + - application/json +paths: + /key/{id}: + delete: + parameters: + - name: id + in: path + type: integer + required: true + responses: + '200': + description: OK diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.crt b/vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.crt new file mode 100644 index 0000000000..8851cac792 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE/TCCAuWgAwIBAgIJAJ0kpLFo4pEzMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV +BAMMCkdvIFN3YWdnZXIwHhcNMTYxMjIxMDgzMzM4WhcNMTgxMjIxMDgzMzM4WjAV +MRMwEQYDVQQDDApHbyBTd2FnZ2VyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAzQ5NC1JBNNP79HPiUBAO59LoUMGbmSU9K9v+cQMuyyOuv0nwuiXc5anU +J1BINqgLR1VJjwTnQsXSlsr2SPs/144KgTsgk/QpMXdlFQwfqLJBIFlsQQBbMx6L +/2Ho6KE7z/qz6cqgKvYrGDu6ELUu016MbUsPWfhPBJE7Ftoajk5AIomDPmiTi0cZ +wdhC8SB0aVVQ2IWrsusfgPeOQ+ZLa/WHmpJ2Syfq41i/VKllEeCrMwtMP2By2kA/ +ufBLCnhr7yZ0u22O1Bl1+0XedWli2GiXyt1h9nQ5blTTKZi5grOzAgCcshb/bw1H +1hdJKMqkzbqt2Mxc/78PJbDgicJU1ap+fhfBmUviWIMML6eum2ObuKd4ihhXKfqp +T/nSUA0P9565W71SLAHFLdZX/VSMZnoehkwIicVGgEzjlYj2j9qBc0CjYzbEtQXH +TRGhbjMX5LSByeE6hwLM6hIbQL4nriRobar63rbOc74Tm1ed02R6BvQjgXgOGqAN +BgCKKjfUIm0Qm2qV4WkwGIAOi+hdUpbNJ0X2dU/B00qLhar+h4NT9TW4PmKf4agk +NZ6O3C1saGxjtuPnIdDxWTdRhPSUyjsllmWhrmkY2bsRB8Z47zqrdfyajXlPOmBM +1f0am4Zeo3ditBTfFqtA2LLQbn1yZwYJQ8+sESu6bsm3S89DFT0CAwEAAaNQME4w +HQYDVR0OBBYEFN4BShcjqDbbgaGvPiGMNrUEi/RZMB8GA1UdIwQYMBaAFN4BShcj +qDbbgaGvPiGMNrUEi/RZMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB +AIqZYn+PFMcOwraYtXtAzJwU4gElWDjIA+xVMMzulHde8t7EWo+I5iDdtn+sHzhG +B1oYFhKv/HIX9GR3XDYWluoUVA4Ed9eBamL0Qqzq4Era6ZN1VQd0egvyOT40UQ7m +2aNw1nLgWadCmsxeVMKQRdzct9G3dOfJp7K5WybINWTibNMTuoSuU5RwtzriK000 +C9pnxCD8boSNY/flOX0M5Mt3kv2JaIH2UsMKNGBf5+rXcKfhTE6JgiXorUEEztHP +PFpZ6VFKDlr8QC/4aLYhOJ9LIloaxZyk/rccCuHbdPPX5XGA3Z9i/lxSoqtShYlS +mt5vmdRwQob/ul6hPch3YRqD4VgeM1O80FEsWBK2WmGGH3wKNKea7u6dZyfQv3t3 +fUVmByAVMllVRA1YiKmBZ/kOeAMku5hpR9kzErCXZd/xrKWVym000RsvRb6apltM +sYnlCyKfIdKxUXavO0Bf4+YoaN4/p3mZchxpLBwrzhPyUpGQ9b3TuGjoEmtG57yn +6I3U40/TouJR0aF7i1bAF5QJWYOS7OycJbHAIZiQx9ENDP3ZMfYNWQO6STFJAjvC +C0u23DyiJWZqE4Uw51O7jWKh7bSEKWutwa0XKWrpxhUjHFX4qGigIvXpO9LMjR60 +YDhdCEmUiu/Hc0tt0QzyTA6w47TP0gXREeBLabzuEDPi +-----END CERTIFICATE----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.key b/vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.key new file mode 100644 index 0000000000..0a8547864c --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/myCA.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKgIBAAKCAgEAzQ5NC1JBNNP79HPiUBAO59LoUMGbmSU9K9v+cQMuyyOuv0nw +uiXc5anUJ1BINqgLR1VJjwTnQsXSlsr2SPs/144KgTsgk/QpMXdlFQwfqLJBIFls +QQBbMx6L/2Ho6KE7z/qz6cqgKvYrGDu6ELUu016MbUsPWfhPBJE7Ftoajk5AIomD +PmiTi0cZwdhC8SB0aVVQ2IWrsusfgPeOQ+ZLa/WHmpJ2Syfq41i/VKllEeCrMwtM +P2By2kA/ufBLCnhr7yZ0u22O1Bl1+0XedWli2GiXyt1h9nQ5blTTKZi5grOzAgCc +shb/bw1H1hdJKMqkzbqt2Mxc/78PJbDgicJU1ap+fhfBmUviWIMML6eum2ObuKd4 +ihhXKfqpT/nSUA0P9565W71SLAHFLdZX/VSMZnoehkwIicVGgEzjlYj2j9qBc0Cj +YzbEtQXHTRGhbjMX5LSByeE6hwLM6hIbQL4nriRobar63rbOc74Tm1ed02R6BvQj +gXgOGqANBgCKKjfUIm0Qm2qV4WkwGIAOi+hdUpbNJ0X2dU/B00qLhar+h4NT9TW4 +PmKf4agkNZ6O3C1saGxjtuPnIdDxWTdRhPSUyjsllmWhrmkY2bsRB8Z47zqrdfya +jXlPOmBM1f0am4Zeo3ditBTfFqtA2LLQbn1yZwYJQ8+sESu6bsm3S89DFT0CAwEA +AQKCAgAjBkBOoLwWg+bTOD/9oOCK5FFeCdPD8sJiDW+Gah7B/9RHRB/kC7eRWtKr +7GCJRWa3xm+MCDBgDV4M95ndmVysOsy8ihbkbp3inxwa3jlCHUBWgC+nYqIxNxR+ +iIC5y2BmA9JbKor1C5sMxpbfZ7MZ01p1CI8UtP76LrxDCPnkOKVnwMk0DbS1420Y +2RGGEh8QJsxqT1qmctastpwMKPfU9tk0o7Ok3qqWLoBvu4dR6GgVjeZ2JMk5UiQQ +ZGTM4wi8jnr90JbGz5qBUsvOjjOd9y+GLQ4ghHWSzNZMkpONKZh3zRb2rErw8vnE +LbIHT6Wapjovf6ia3k1+CJoxrYnDrsOHcWopm2kle7FXjgfHRXubcNU2aLdIAcRg +ZGGyalex3/NXKjhGf8jhaXKkOYDL37ZFtEmaUJVjjhiIE5jGByBHU0pqKk9Tdtv0 +s5r5m0T8Gk8h70+fZ/C+wkYE4h8uzqAlq/yrxBSlGMHEVG9PI9tr9bM1FLM/H92q +CqoVR6YWTC7o5Kasr33RKYJg5vPHfFoIGHX9etbfHPGQsbCLaWhTLIYus+0b4ZS1 +D1jHCoxHCjKzf2PFwogtRsmhyQSS3A3GyEWy7BZgFvgKFpq9hRC66k8Z7pnnkKrW +i4YihK17ivI5uG67Aqlc+kdahRNVWOOaPbwjGosmlULyfCOdGQKCAQEA79dD3caa +zXqFQkYDZwZcthXw9Hn+ChTCcfucJz9I0DUeL8FpUQYCkFZRUoEgF/eNrKSG+ctn +VDgrj0IZAcumpfjc4ZMug8svFYkE+vsUVgSI03KPRJ5NZ+Egn+HExURzCSQY6fK8 +mCp05+gXndiUhoco2H851esmMtCSd/5IyR3d3C64ZfFGSk/Nx66A4Z643ffB6tOH +KYWFgVoQtSb92pgyxuBzZ1JhxuBVihRzAQtuE+uZ14xPoVv52fUlYXUhGmdqtZ3l +Cio3YGZTaUqtF0BP8HshzAWQ2k2vCJUxY99dbFfsE+v8vCojgMz8KmzO7C+j3Pa1 +hq77rT29WFvaHwKCAQEA2t8R3QCkcaCRDMAPomqPJjUHrX2gdPM2zFFCvSqiVkh6 +8ft9NF8sO1aXq600IxTiTf/L8ZvM0HlPlYQSjFzGWsOgNww9MKF7L4NnJ7e/8mwP +jqfajNcqecHIXvNi0AqXOpN/hEhm5MWKce/BPV6GpnRnb5doy8wOG0ESsmUA/5TJ +y/65LVxDKT9SdymDVayRwq2vNn9qW2BBcM9yan5GstkE3zzkrzKcCgz5X09/vO3R +K3fYk0FReE9CY9XAQGtz36Ra19efETzvWPi18zsP96QMUYIS2+Y45sVPhGZbY2aG +HQXTg8xIJN51E+jmWpJ1vv27izFh5TXeloRD4qldIwKCAQEAqkG6+KVy4OjXzlsb +MTiP+eaLfVFYaFmiSv3dNPM0wjDi8+2t0Imeqk3MPvBRExJ17ReChbLB8ERLj8/R +Jrgl3e5TBoLP41kKXJQ/B9fS8NkZNFk/oOtrcZGb8kN3xr23l8abNQBOpwqEoNfe +Y/wKO5GZCk8OhHAAVtQ/FZVaoAJmq1YzKpLjXf9WyihzbzaYb2Hgs81jRrN1OYTx +FVfPnyyp5woQgkk2BdLchj/L//LYOqXmOOBu6tH7BKGE3rEiRbciRjkHDXc4hmM9 +VSJgy3+o/8K5FDbjREUfOs2GGSrIDBBCE0ZTzFNxjo51d7x0C7Ap98Ley/RNzwZj +8mSJ6wKCAQEA0NXvcXPfdBvEyumnAU2zcL1AqiUoKO635pPSnjRD2RgnVySi/omg +5q1k4oXNLXwLwmjD67DA6FoXuY3fNNaA3LGz+VJQQEqUA23Zy2fkWicJYRB/08qp +2KsxyIdqTR8N1PJPxaRfqQFja/tb4naC++gtmahacbot64tXj6gYH8WUFnThs4pI ++t5UjSarDeAu5BZdDB7fGHjrd/w4K6x5QMUZhPfRK+maQWzHtE1ikJ5J6rPbjgXQ ++n6F1kRpwA3G7ikgFLrEJ+qAZeBJm99LCPsaVdtKq08sE+VITghsQpfcd2zLuQH+ +BE/OXkTnJpyAhNANVm6z/cQ8sllZfLglCQKCAQEAkZTQ0xnUeJTV0CqljMNCIN4M +i6Xyqf5uUDPfooY+fILbemT/acYUAkbjamgJlQMQ7yui9WV7Q/9HiCHaVh3o5zrV +zaq3vocA9x9nK998/He7772/uJarINvLFj/p/vTQM4Lni+bJ93bk6XE+FQKPgY9B +GfeFFaVtH7gimB4CjrxYprhAfqyxyE/m6JVMRg1olIFuav37GYP+TJ2K85klQRNa +TEXbm6ZJpSHfNjKZzUczziaIbwnMN9OxJY6M3a1JuEy2h+og5oRdMOoB6RETzhle +mxT5uEtA6mR6KyBZBjWhcl/V/Rw1DVMmtVbHCdc0+Xn/CMemRLCw1bxRUu/iww== +-----END RSA PRIVATE KEY----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.crt b/vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.crt new file mode 100644 index 0000000000..6785310146 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEqzCCApMCCQChJZEdSdrQkjANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDApH +byBTd2FnZ2VyMB4XDTE2MTIyMTA4MzMzOFoXDTE3MTIyMTA4MzMzOFowGjEYMBYG +A1UEAwwPZ29zd2FnZ2VyLmxvY2FsMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAs1MHhleossLBkYKYwOT+82RT651CfCOilpEUhm92KGRSMQXZEk+2TUgc +dGPeQNDNmbpXGzdk1HZkqWR5XKfSjWWxfmBlbBoYnkL3neoiXBdBVsgHkEPdP5ly +uJRkohy6az1vnq2vLaI+YujStutf8hSdcPu9VeALbrR027dMbY2XMC97FteeVaw1 +mXmW9UHDVSV9UPBPswUOQWhjIADBk5IYaYASCY3M4X5BPCWFu1oQhgVMEhodBoBj +pHhHrfoDm1TwtT+dp53TmR10zpUiN+FcaVMsjqN4DWX4ma0uhu+zJew2XjCJkNfX +wVqGFpe2Hx+lupOGs/kwBvQ4PYn5ydgcm5DTggBC45JxCAVi3tQCYGsg2xkX9yPj +aXYc8E4/aeQI9UZxUeR2siBn8ECX4gJTmPJbQ4Xykqn6YOHyxIVoqd+9wo9Z1weH +xCWtPGESg7l7Jn/6WQ5V8z6RzrquGi67asrpYpv2lxNXMQA0f3S8sWYe4f8QVazy +ALtu8+0XE17UPjlbNBqEfCIrMsYmL5VyMVbL0dlXXBxHjzfpXraNGoSD4v6LxRxP +dWQgrhEZ6DmfiWfX8uhLdMwlvUxNXj33UDtM8dtN6mHERA9wF2RQQzPddZ0MYmUF +DI92i9mRC7Yzx6mcv/yUnFw213Jnzg297lW0Xp0ifawyPi2V8f8CAwEAATANBgkq +hkiG9w0BAQsFAAOCAgEAme1gyNQry3E5bj4XfdL4aNvZamzLaQVRlNZSHUzDhhpH +6N/DK/CAw4g4Msty7g3KBZPmldJhxH0bnSoRGMjFdKn9tVQeJOjaHQ2Z3cQWwdte +iXtu2F38SVfP5HCh9ASQ9vQXahGOruUPUUNUnDLfOBea7vrT3DmVugXlMSmaYuSJ +JdrbPzD48yy60AEDlCVpY2m1cEc5SmTkXbrAg2jhQd6ytaPQ28vGQnpZHSS/xWjC +Hh68o5SUoGoFErZxPd0o2brHavi4YybYt7CXlWG2TJ89s3BCSPIHclNF2HjxRq/r +2Q/Ttzo3cRBxi3RBnrLdn4qNgJjZnWaLobjaWcs1fbI32allogLsiurCwZb0ToC0 +fNMzyHVNWY8BqsuyWyF2H0F9rklmqGFJSmrqt8kDLx0xpkZchGPIDSRh+f+PPDmE +jGPPH2qxz4un0foJx99dtw18TPaplFo2LxRK89koTiQNyzAHwSn6PHGlyXhNPsUt +K5GzjAu6B4uyldcg2m+4O/dbNdeqSczYAFenfEO7PRAy3AP7Lxs2xqQaNiA10965 +vYmCNIOuV24CuFEIrjOQkZeFCw+odsgFs5Nv8JfDdA+BRr+Haq8FVX8afEc0BEnr +xY6f2fvgYTMvx0Z3UVT/XJ3POWHRL0HFLj5avHE0eOOkrcPbX6UsANd1v0F2BH8= +-----END CERTIFICATE----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.key b/vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.key new file mode 100644 index 0000000000..90cb03653a --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKQIBAAKCAgEAs1MHhleossLBkYKYwOT+82RT651CfCOilpEUhm92KGRSMQXZ +Ek+2TUgcdGPeQNDNmbpXGzdk1HZkqWR5XKfSjWWxfmBlbBoYnkL3neoiXBdBVsgH +kEPdP5lyuJRkohy6az1vnq2vLaI+YujStutf8hSdcPu9VeALbrR027dMbY2XMC97 +FteeVaw1mXmW9UHDVSV9UPBPswUOQWhjIADBk5IYaYASCY3M4X5BPCWFu1oQhgVM +EhodBoBjpHhHrfoDm1TwtT+dp53TmR10zpUiN+FcaVMsjqN4DWX4ma0uhu+zJew2 +XjCJkNfXwVqGFpe2Hx+lupOGs/kwBvQ4PYn5ydgcm5DTggBC45JxCAVi3tQCYGsg +2xkX9yPjaXYc8E4/aeQI9UZxUeR2siBn8ECX4gJTmPJbQ4Xykqn6YOHyxIVoqd+9 +wo9Z1weHxCWtPGESg7l7Jn/6WQ5V8z6RzrquGi67asrpYpv2lxNXMQA0f3S8sWYe +4f8QVazyALtu8+0XE17UPjlbNBqEfCIrMsYmL5VyMVbL0dlXXBxHjzfpXraNGoSD +4v6LxRxPdWQgrhEZ6DmfiWfX8uhLdMwlvUxNXj33UDtM8dtN6mHERA9wF2RQQzPd +dZ0MYmUFDI92i9mRC7Yzx6mcv/yUnFw213Jnzg297lW0Xp0ifawyPi2V8f8CAwEA +AQKCAgBZtF8/RPqO8f4C3GGtnOAswTN52eE4WFstFsY9ueRRsF2tSE+eaWG4pyoU +zyCPK+St0hlg9ATsg403b5uGTi11rjlsDqyttyA5iyZzSHyHtNpqnwWplUlIV2qc +Cx+MOPLIUqNTrW7EVTUAJZfDCVulrcpUipncK4eMiZkrkDYbV4kaAaaBdrsuAEeP +ztNFPPCJ14coxg4Yb58B+UYc7EPpnlu36uka/mRPKOlZPSv43MUHRf8XzxhV+EPg +Moso7LiBK6x9/qTPBJSlM6cK8G99pK6lwYW4lO2pRilmNsvflGj5v4Ay/fTTECZO +AwqwopPoXdx5yPLJdQ4hbGn13t+k0pB4LYXl1xqLg2Z9QN+pgC2h41OrSx8Ozw9U +KTocbsMV6pafnMRoQ5Fjb+eTy4VE8rZl/OlMDX2cR2XL+a3ypIAA5E4KrYDiIBiU +MSA3EA3GsOOnyrV+fII+f2tVo/qDnvxQO/ZPUr/XG2xtJ+gqThWlrBft/O4/lCju ++kfNg8cMHtahGOmLz1ALsl32ANj5jTZmVOEs9xTG7+TeQ2RzWeBYTB7oNTMNIbaL +pTZTzxoeRyxx8sUvtaTb23IWSpRUiS4+F7Tn97g6ks8fYQPsVkl3WzXeECaL9uNN +hFkAwd0omD4TwQlmOUVm3IH7A0InTAaooC9jJfNqmhhHcLUAgQKCAQEA3N+pR1ed +aCXQit6bgw0rIF6RzjeGp6lLGaPdvCUM7sdAUwSGbFOgkcaw9TELFpCpfZGKFXI9 +IxPOwjFrURY4S2iuyAVv+Cw7trXW4BF1z+08M9RWYGLvyUsO7FIsGUmdYRtasb5L +IfHfGoXttadKWcdFMSF+25CUcbleyCNrJzXOzeMn1/UoN6+qfsyfaAD03nw/ZmhA +mK3UKjR7UOUPXt9gIXVivRaEQBakrLkJtK33fl1hztqxComE3/h6Qmj6iRmyxX3y +v3mzXbyC6jobq1tLUWpxvlQgoAyk+zZ0LNEHlkVfertaz0XdN/L2ZgjoGjJxfn/y +OK0a4jJyCpXXEwKCAQEAz9fJcpqaB25joZsqG+islNljyFjJRT9+E8IU97OglhJM +8T9TFs4RNsAxIqHwYm4KuoSlI4GhYeuOxGk6yUGm8cO314J7Wv4CAgZeJBcmxJUs +C8FbcXKbesK3VIuvATgzI9Vq/UF+GxJCkPctZJ9Oa0t578rVS4JH5ZJQdw2A77Lq +kGunMDboVY7EYDOn/fNMKGfcnH8KIQn/2b6CKLarj39b1fG7MeCuxPRejijaKtZI +ra5n0ofLluGo9HBXLgqgsjhjkSWU79lRypuKS8qOcjI08Xaw3Q8+qn0uLCARd8rN +2+mQy5OAZJCWpYIKPL6E41GaxcaTdOYzlOCs9Oz65QKCAQEAgSqzXitYvC1RFcU1 +AKDU1as4bXZ/YtFYP/halcq9E26mqWX+Dp+hSV7+4YT6zQlwdSSFsiEKq9bLlTk9 +X0A1T7Q6cnLrliCYEzOoI4VSdnRwPocwtFFnlTo10fIEJA2u4bkTgtqcKY+/P02P +RCo/Ct3EEwVZoKGejhsv2K8N3PJUrIbpKBwQlvA+LsUPe80DZpEWqpbRH/iYGM50 +R0yNfpf3KdnyEk52rNwRFYloqacLE3Uc29F8s4LUl/5B0VB/I2pJ58DOEzfiszCp +Br1QrRdIpqYvOnUMV0zNtrOToRnk6/ZJ7gZfBtP+mNeXTPhsc9WIFchRKN/i1uFV +W+dgzQKCAQEArcXTDdio85GeB1395PuyX3kqbjWdgiJFvStF8JvkpdSDNCknxSdh +SQ+DhVsz6nfqzGtezsLxNTeHVDxPBDm55OUobi0QCdHZx+ufBjm9FhtKikGNvNp/ +mDH4qd1n4nMkfs9O9pOtZeDsetvOvhRbsmWWe6BwmQNCLXUZhZBqvv4uE7WOQUeH +FRGaqnxF9pNWl2nPD6E/zMPZgCpCFNw1sHJhTA0h39/k/5L5A46waaRje6MX9vPG +ik39vvG2Ui5ckOWIibCMR8TBF87X3+ppEp1bmo8L7Kd0U4L5+baOJEQRvc4YW7zl +Wi9xZMvG12bLIGv4JWeTnediNRVsRhNk6QKCAQBXYkpxk6LTgP+b6FJ7fiImzDbH +QJ+RbBYJdgYLEarKWdWhNqj3YiDOUJt+ve13reybL4cLmOYoNzeUO9IHyGeTp+WV +gtPf1g2hm2TZannWsoTvnoXJ8yR52ZQQ5JusNosbmlrqWRAN8GhISdYTJDNcS2hD +PnVX/kaJfRDennokD+FWuyygua66LBdZi3UNgGMay15/2CCoC3PoejfQORxDyPP9 +am+e3/U6QG1/VWMHen3Mb0AZKwEBAwX1jL4EpoDZ+Y6jP0tbQ5xL7RivsUNtAVlQ +m7lumflcBy1WqkmviVJ9M2iFuo0HznuH1qlgOJpUiqZZjL/gEvkdDNMcQSmH +-----END RSA PRIVATE KEY----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.req b/vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.req new file mode 100644 index 0000000000..ee4728f012 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/mycert1.req @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEXzCCAkcCAQAwGjEYMBYGA1UEAwwPZ29zd2FnZ2VyLmxvY2FsMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs1MHhleossLBkYKYwOT+82RT651CfCOi +lpEUhm92KGRSMQXZEk+2TUgcdGPeQNDNmbpXGzdk1HZkqWR5XKfSjWWxfmBlbBoY +nkL3neoiXBdBVsgHkEPdP5lyuJRkohy6az1vnq2vLaI+YujStutf8hSdcPu9VeAL +brR027dMbY2XMC97FteeVaw1mXmW9UHDVSV9UPBPswUOQWhjIADBk5IYaYASCY3M +4X5BPCWFu1oQhgVMEhodBoBjpHhHrfoDm1TwtT+dp53TmR10zpUiN+FcaVMsjqN4 +DWX4ma0uhu+zJew2XjCJkNfXwVqGFpe2Hx+lupOGs/kwBvQ4PYn5ydgcm5DTggBC +45JxCAVi3tQCYGsg2xkX9yPjaXYc8E4/aeQI9UZxUeR2siBn8ECX4gJTmPJbQ4Xy +kqn6YOHyxIVoqd+9wo9Z1weHxCWtPGESg7l7Jn/6WQ5V8z6RzrquGi67asrpYpv2 +lxNXMQA0f3S8sWYe4f8QVazyALtu8+0XE17UPjlbNBqEfCIrMsYmL5VyMVbL0dlX +XBxHjzfpXraNGoSD4v6LxRxPdWQgrhEZ6DmfiWfX8uhLdMwlvUxNXj33UDtM8dtN +6mHERA9wF2RQQzPddZ0MYmUFDI92i9mRC7Yzx6mcv/yUnFw213Jnzg297lW0Xp0i +fawyPi2V8f8CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4ICAQB7U21HoBp5Qfrwd8aA +KzBY2BfEp5ouyn32kpfkB3Ha6+XJ69Lt1WHMSKnmYamlwZCSOS2uQ6DzdTLDfZpC +8PH5Gs32O9zJwUeSuYcUQGfcAenauu9gwC5ZnIbhOs5YTnEFquVsBqrNUKS+hLKJ +sAPtucoqlLX5qSkv/BOK2X4os90LAmx+yB/yarAzZOO0ku8qXt+MHI+rOMPLTmm9 +kYhtyXejQaXLOVbvQ9b2gxHvMcyLhklc4KpJPRfPzOdNebHsf5o4Em6lxeglGw/A +z05sBSAla69sEygcItZryQ4WjMRUpsLePXJrlSL5DYWGK6BX1gCkWtpXLqE1HgR3 +4L/xvaJQ5ZWpLoyJoJauU37Zhd5dLNGpNiSSEA0BKOjj9Kjm8nvsJE9DgziTaG57 +qFLRkMkDdBdb5wOfVYI/MY9zc+igrFPQJkQ0Xkdza8yXegBldv1JRe+49zifysea +Y/B+qWx8IpeHke0iEMqR6iWrw6oGBG/obHJ/V09DwC6iU8vot+pLr/bSyoUCUP30 +OEATJf50ic9oZYXgdT9oNBcAlAriuzoQuGi9nAKZJss6YkhooWoqXlXNQgAEc2gl +WF4fNumXwVaPVeW2q36Xk1btHz7k+IeVUg1jaPMPUJ+1dgIOZA7FcoYotvF6StyX +xoHybhvC7lbeif8EK7tJ2p4hug== +-----END CERTIFICATE REQUEST----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.crt b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.crt new file mode 100644 index 0000000000..92a581495c --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE7jCCAtYCCQChJZEdSdrQkzANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDApH +byBTd2FnZ2VyMB4XDTE2MTIyMTA4MzM0N1oXDTE3MTIyMTA4MzM0N1owXTELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExETAPBgNVBAcMCE1pbGxicmFl +MRIwEAYDVQQKDAlMb2NhbCBEZXYxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBALGjhpJfej7btWCO4OCRJBliUAUyPMO8 +B649Qjn1Yiw9E1L5viByYJSihsfUQ7u2gHip7QdigKCA/s4+w8V2L0Dv8lCowCLk +exf10b7XGQaOqhk2mlr/jOapAg0pKDoUlVErBBZK2s6UbD/gLXAbxudwxCFKJ1Y7 +d/Dw5aTl1vlWZpHzf2o9/ZCeHXf8Xu3aMIEPJ79wG0vzNZK7bL1r1lQVzACdHAr3 +4HAQAvgWB4ZjKqN8z0vGC0N0MpaAuHD8fH8wQ5YiWBbDhDPFVzRYU8PcQjeZSMFq +Oulew9KVm+vXtcMvteEoXMXwWlqAGlvnv7sskc/VbrLJJQaoswyKgy1QCKxVO47E +f2iU4kP75iDYx6NpApdnpN3zxHMHyZDxuwmtoKealenxl5cZeHc6uUU1wXk+nmy7 +TrgW509mcopHzHj+Q0zyGUg/dRws3qXPAGZehJPoaYF1F54eiindF1yLMMH5osvy +1bNp2EQezOlY3P4gqW9VHq3CQvytmDbXqS0vPzVAsFu8YazM3Bs0mW2bBXrEsajW +DSjrvbhdZjlL9j2jqwZ2nzyan88M5t5T0vZhcu+wKisATI1yLdV3oWvLmdFz/XA9 +L6UyosTiwC1MWPmkOY4mcHn/Px70f40+wO815pZ6FbjecxRSyMfAm6vDPWtLAMUr +1UoD4vasyvQNAgMBAAEwDQYJKoZIhvcNAQELBQADggIBACI85R1LfDwKpmWFdCeN +M8O6TwSftxh113QzMvobYDMmBI+yVn0ZvpcfP7E+LWRjzNcDxMFbntbbFWt99Rcd +rJek6CVxLJug53mUEFmvktreHsJ1T7cMbk1ZVroAurE7hZOWYM2HwXlKzVyXX0qh +wR26HSuzQcGBfo5/8e6dzMuy0fUVkgDMu4oKt0+mGgS4kXsOyexfRRBkY9GPusVk +gSzu/WbSGNxNvp/ewWNi8waqrN3noM83iae+BXxI0Sq4eLTQ/vnV1ReM4gRR12Vw +anwZqHZ/WzBV27z9gW36t7wRxJS/uTXQ8J08KtBRBPv+19NXSqqjys5Jg0P1f+l9 +k+sWwpVqIF2rAQ3FyMfboaFKPC0jRn7iJMjp9KyvMbSI+25/rP5xvMicoJwRlk9I +GNGasxSfmRpVpV+WG04xMGp3cPrCXHBdAAjI3O68YIPOX3VqZ6MasN1iGuYWOmam +yeKzLUApYdtkR7yJ+X1FOKVfbzX27CLYmzwrHnDLJzu8NVgqLGU+qTSK0zm3sYE3 +w3ex6WX86Oz2QBJ5h/s2TLbsWis7ZkKjMyXqVWlbg4P3reyNrfpAoc0y1R9EjZlf +1c9HZBRBuRMgaPWmdSR4lxw1FhQBTstIfzC8lBYNbt8QRRtJIxVF9mxiL7H+6XH5 +FZXcQCHun6klGtCkypeAaviE +-----END CERTIFICATE----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.csr b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.csr new file mode 100644 index 0000000000..f65d21f0f4 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.csr @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEojCCAooCAQAwXTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +ETAPBgNVBAcMCE1pbGxicmFlMRIwEAYDVQQKDAlMb2NhbCBEZXYxEjAQBgNVBAMM +CWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALGjhpJf +ej7btWCO4OCRJBliUAUyPMO8B649Qjn1Yiw9E1L5viByYJSihsfUQ7u2gHip7Qdi +gKCA/s4+w8V2L0Dv8lCowCLkexf10b7XGQaOqhk2mlr/jOapAg0pKDoUlVErBBZK +2s6UbD/gLXAbxudwxCFKJ1Y7d/Dw5aTl1vlWZpHzf2o9/ZCeHXf8Xu3aMIEPJ79w +G0vzNZK7bL1r1lQVzACdHAr34HAQAvgWB4ZjKqN8z0vGC0N0MpaAuHD8fH8wQ5Yi +WBbDhDPFVzRYU8PcQjeZSMFqOulew9KVm+vXtcMvteEoXMXwWlqAGlvnv7sskc/V +brLJJQaoswyKgy1QCKxVO47Ef2iU4kP75iDYx6NpApdnpN3zxHMHyZDxuwmtoKea +lenxl5cZeHc6uUU1wXk+nmy7TrgW509mcopHzHj+Q0zyGUg/dRws3qXPAGZehJPo +aYF1F54eiindF1yLMMH5osvy1bNp2EQezOlY3P4gqW9VHq3CQvytmDbXqS0vPzVA +sFu8YazM3Bs0mW2bBXrEsajWDSjrvbhdZjlL9j2jqwZ2nzyan88M5t5T0vZhcu+w +KisATI1yLdV3oWvLmdFz/XA9L6UyosTiwC1MWPmkOY4mcHn/Px70f40+wO815pZ6 +FbjecxRSyMfAm6vDPWtLAMUr1UoD4vasyvQNAgMBAAGgADANBgkqhkiG9w0BAQsF +AAOCAgEAM9VLDurmvoYQyNEpRvFpOLPkgr8rgboo/HN+O/hN9jtmXranLxzTzd+u +OJCujyzS3sbqiZwPeT3APHH4c/mLdrEKZHjfy2sEeXMsVW6dCOcIEYsADSCM6chi +zU86aw4rAkd6YYB+lXFsEmBq78AIpw0vcdpoPoqGRG9ETQsjr4kD3ATGHTnaP551 +61JJed7Kn5FTbieTmzmMa46dn7GjTTmPEcoAnHNCx4CbJAHwWEzvQWF4lVlyb2di +jFD0NQ0WeaFHK/f6UQMqMq+7TpurN8sLWDlyPHA2X/FT+OsUMAX2mLcwZEsYhTjP +dC4ZCuZ/itDgEp3hyPeKiLo+mL/bhhy50nzah/qclI9PS8ufUXEjWoObqiJ5eyIZ +jTZ73qpLupS+Yrami98IYfuOotwGzKkVLwUPtCWQrKsun6YNtotuKKmqEEQX3Fm3 +ZXIYv0BckkXIGd0aKPeMGgMUO26pyxPBSRWB29F07LXzS6eEmfOHvZcT+QLZmys9 +FkH3yePeTilojCnxNINPyKT4Dk0NiZviCdKavUIJ5QtOyDJ1Nc9j5ss+QaAaNtZZ +VTTjupNp+cfCh/kdyGpGP+GgXQQcGgw4OaIbfXqmec7RsqTOppK5gDR4Ne3e5FVm +SpPDyHbv2GJolPG8/HCOsLCJED+wAEfhK/wUg8ZpC+7Ymct2TU8= +-----END CERTIFICATE REQUEST----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.key b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.key new file mode 100644 index 0000000000..dbcedf27e8 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJJwIBAAKCAgEAsaOGkl96Ptu1YI7g4JEkGWJQBTI8w7wHrj1COfViLD0TUvm+ +IHJglKKGx9RDu7aAeKntB2KAoID+zj7DxXYvQO/yUKjAIuR7F/XRvtcZBo6qGTaa +Wv+M5qkCDSkoOhSVUSsEFkrazpRsP+AtcBvG53DEIUonVjt38PDlpOXW+VZmkfN/ +aj39kJ4dd/xe7dowgQ8nv3AbS/M1krtsvWvWVBXMAJ0cCvfgcBAC+BYHhmMqo3zP +S8YLQ3QyloC4cPx8fzBDliJYFsOEM8VXNFhTw9xCN5lIwWo66V7D0pWb69e1wy+1 +4ShcxfBaWoAaW+e/uyyRz9VussklBqizDIqDLVAIrFU7jsR/aJTiQ/vmINjHo2kC +l2ek3fPEcwfJkPG7Ca2gp5qV6fGXlxl4dzq5RTXBeT6ebLtOuBbnT2ZyikfMeP5D +TPIZSD91HCzepc8AZl6Ek+hpgXUXnh6KKd0XXIswwfmiy/LVs2nYRB7M6Vjc/iCp +b1UercJC/K2YNtepLS8/NUCwW7xhrMzcGzSZbZsFesSxqNYNKOu9uF1mOUv2PaOr +BnafPJqfzwzm3lPS9mFy77AqKwBMjXIt1Xeha8uZ0XP9cD0vpTKixOLALUxY+aQ5 +jiZwef8/HvR/jT7A7zXmlnoVuN5zFFLIx8Cbq8M9a0sAxSvVSgPi9qzK9A0CAwEA +AQKCAgAb4VyHsLCRGQ64nvQwitctnL6OcjoTRnm2ISs5yYelBdj4lvX+RbVe3rtk +ta4D0jsLtS/cjts9VcGoQTWc0lXMTVysyC+Pymh/dDd9SmlFHDMaTfWf/qfws+n8 +gs8rfnuJB8VWcl0xOx5aUCcRh2qKfKprxyWxZRgIGucQIHrDG4pxsdP3qs8XWZmq +cVO85RfjyaslYsUGAKAR7ZS9jiVPgTRJjF8QYaM6M2kj4uE/eGUCz94BOI4gAibG +dGF+akJn+/0/nRhSSlF/hqOPNaXAAdvqugYvRSsF4be+X3jfZTXD8sMLGbil4Hlt +5tk8P31aNT6Vbhw3t1Y2W1fuyfaYbPZfprpR/6ZPV3Uf1oWoh1ystIxWnfU7Qdxu +vrkHkrtho6Qt/7d8nNg0mQ8y5glNcVh/iNu9gkyHIpQ2dZpM9tpHArBGweHVDMvZ +vrb/oJ5fRxnKkyouMtWvqO1TY4STPBwCDNSwJa0yxTn3fLvkOdHk1nGEKra7E7Nc +hgsIe4q1ZoEikg7cZe8pvcsHIFfju3Kv/zgDTvHjzHPTdNear7mpk/LihlWdbTiI +UKkgv17JHRsIhfE5G4pZXLRv2qjCGh+uS8yn2k5qPJqGoyIQ2A7BYbaQ/y2gVh6u +hnVdKeETT2uUqIS3xHrV0U9grAeldPJu7bHRwSoJ+HUbp+D8QQKCAQEA4/5K0+Qq +p4rpB+4FpPkMcM4yE1j0ASwHsKGMDPU70/t8yfzZBlpf5WNHTOWa8frnxOyazo8E +sjm2Xw1RlMb21bFF0wjb3uhN2ak++0zIKMf5vWnM0bb2z7yzbcOJVxLzO9DmRUh0 +OXvHvbeKbW9KXHT3YKA2zjaw0mO1zl7sd7r028wYpD6owGtfzooyXwWCnByIQ3nM +JFB7wFJGIg6Kbu2eJULrN1EaT1Ye0FUVmc4x55FLmZvkYziQ88e4UsjYdZ4R5EFi +2XULVI1RA+NPqDXkXmpIx3JnRRvaPc74QatGvDFwY8YeCAjfGFN5LiwFJ6Cz3/jf +WjDLOhqoSiYQ2QKCAQEAx3W7uPE7WNQRsyu2QnsEDdlikgP0FJf3fFZOYurfsxp7 +iqTpNkR9pSWXftP4FBM/KRruoY5TucmPTfGPRS6sQWTfUkVOhrUpOLnuWjf2DJxH +Qqb0wnT76WcAB4L5Gr//91a+w3dwAX5YhdTZLxEKgpm8ky290otCg3+AYOb/P3Ja +V8RR8RQCNV1+y7peBgjj/mbYeVpxjTiZ5cq4cx2OU4rnup/k3HIg1Gw+qr0N9AUN +2WYOL+X0qaKffDa2ekv88H6mVnfRSReFIpteuV0XITwvMc0DbHdj6zEj1TSZMExu +rDVe7eh2BeL1QxbuazRUgwZ+kfy2NUzPkB1SSwi8VQKCAQBs8K4qj0S+Z8avjlFO +Id6K7EvLKN72zGYkRRzZeDiNMwbOsS22NmrJ/eUs3i1qYJxsYS4bcwUocCEvS/rm +XyfEtf8KNppw6YmBbrh0dZzSt7MiibJfptBKNP17fkpau+hTdZ8CDfvTF806XsAb +SGk8wnsNxaBKaqGU9iYCJSNSlpe3is9fc71IrEXMOAaXltdw5sVJkKI12+s121o9 +nbsSBCJj5ZTlCrDKpfj1TSKUKo13+9om3PGFY5sHkTAHBoc/tDcSXRfxllbCoP/M +HsqKMq4bWyfJfWXRBN0EWagQINocxHbShfEFn8+SHRizMj+ITuaEJ7P5sYT6D5DI +VWYJAoIBAEqaxdFiIYGTKN+sbOqm2phXhB/7bJM7WC1glsc29N8n+6ebEUPkEF7y +FZ0xqavQmyJD2ZgCBV0LgBd2T9FfqLx4/3LlS37lSfrWyMlj/xsuZRUQH6KQYR0n +EoK8wXH4+MPJ5WZ1SSa13GSKfYW2SQkaecdPJ54VypYm3ZzhKf3QRuxnGQMkKcNO +KjwHhF2be7PPQg75/lkFH8MstRsRpgengA90+QRfh9oMdtAkEJECRvDW1F2kFIRS +uHacfFp4C67koFDdViGRs5GDLcYFhL5ApaJp/WrXqT7yTWXU26uOGyM8fzpbZbHD +91rVu+3LUAUGK9ds/7Yl+cj8vqgkJ1UCggEAc0a5kmBREz/8rAWKnlCZrhBsxUUM +tiIj32h6dVdFo5SsoyVTxdB394npw1DAsC8xdowrcm/zsYstB3IDMYlrBnCdRxTU +Xu6RD3Jci0Qg1cfLQg5snlRnrNz12wygXcvTvW8cHsda8vO+FL1RgFdehDtYoyZr +swcLLRAOOLTRXy1Xdbv+8vE6s5ryl3uAO+2Zwbmur3tRL+rhXE+Tb308jlt8g2NK +WrRbc3c092aImdGcKmkMGqo6H+xnL9Jj7sR161uO5JJQjxcYbZ5PBmm3J5Z71cSY +LR5snbYdxUy7WKE3yxAoWi+FMsoGf+O77+oHAcpXRaTDv0Enr/7rEku5Yw== +-----END RSA PRIVATE KEY----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.p12 b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient.p12 new file mode 100644 index 0000000000000000000000000000000000000000..14208f6bae5861bbe9e43d58ba6f14e9b35dc78e GIT binary patch literal 4021 zcmY+GbyO3KyT_@GX4HsDmo#J4UZqn~93dr)t_g^wlz=0p6r=_t1Zinx2uO=aP3dN+ zfFlG1>FayWz4v$TAJ2Kt`Fzjw{P{UwXbh-oc~HcF zT>fGtGzO6Up9okK14#Ibo{^D~{9O_MNl2kwK$`#lKt~FMGEh*R85AhMz;^CrWK<+i zV*sYs2Q|h6FM9&L;z`KD6tP;?M&IV#=daG6Qj_O30RxXNNeZ4UIT>!c z9@|i1aTVn|f!EJFYKs-ytZLywOV#AgI8WZ#>1osY*m20b`{R$+2cIO1&qpAB9v+j( zb}pnY!QC`@lIijjo*3(84gibAV))X+@w2_>k5v`_5fTY$-VgiMu%V&y?T-RInjP^m z|GkDF8*!MIK@d5o7h)9Mrlk3ts%DEwFl(hgc6z)`B^*_XP&Kgg{hczYLorUal}wgw z540oUu6~I=ah^v%3Fzi+sWA(R-Ec1F(;QCA{1b?>XF0HEt>WA8HW*$kCSxzg>3O|H zd~||}_iUatHgeVaY1FQd-t zwV2kXpiyF*v(y84Nh~brl==YJA?GDfDv`gFC)-ui-oSX^(zy3=Yuy1IA6HkxyMOCd zF78R&qZBb`kz9)M4Y0^(C)ONJO|={qX>zAQnl|%zvVBY_OgH=J%nANhTnHMgbds84 zlRO=lk#w}FDCeCU_=G87+VN$z5gQxWwrZ;)(NW4=sevd#llfE0ZjF9k7#|yk-EJmT zL13@a6j*l`hIzi^&|iHU18_|T?LOLz!N$*_NAhpp_A9`$j`0dS6-Pl%JO2nNNe|qk zm=6fdrl$jRVUHTTv}!J=Nfl1`u^}PM}$2%(AxWQ{i2X0?M?hPtwUcn z^Hgs?-$U|FlMnu*j3$Y5Gp%LT1q|`kCPf;c?}fB_VT04tdZj)}a^t=l?Aj2qP;hNx zos+a-Hb9A#Pe8Kwn_T#<>qPj-rudyt%suoST3-FoIfZM!G1GS(JR*WK_JyfKDPl|) zRPD5{9{lzpJtV9^tDmK5x!1t`&@U;>v^o4q{fGFkKH+_4D8Tm|Zh_h>`ZCCO%Hw*C^D7)jEzJV2CcLUz3SMFtFCe?eL>4^EB5S!;MMJEO2)pTq^ zH)C>P<$atq-}_4!vCp`RHs{v>_Jj>}eI0$=M0V_Ek1m{tzt}+NNNoD-G8rkI-zCuP zZcUdzo)w82SH`QJu8=ifGv75FJhM4|5L9Dig4?mBW||A^kYis2?~0m>Iv?Ud8)ngA z4mlOlOqE)?oyCgJ_`?q zO@hFM77*$7eu%|Rsi&bEN>L2|VU(TW!ot1yBS6CKA)SF=z1uGmdxJLF+ZDy-(2Q}* z19Vrax6X~u^8~=<-LA)VxUNS5Nu8?v%RF?0luXJA#Lv;YWee89vo&kf5X`TBhvw6G zP6!*r*6(8P{!yu>od;%WUSsAn46p8reNHtpRJ}@&gY1J>9_>9{-2#=+>eKmGyTwv=~_8;sA403*%J12Srll}_o6wM z6(~0WCm%>wQV%k{lK*vr!k)W3A)EN4D>*j!1*PHmCWGyBIdXzGqtk3jNZ);Gq?~K$ zfg9e2$A@i%Vh^6!Y#E->FyF;b6XLvn`U@z^g>i@?4>U{J>_5QjzQxWs@bWH-XgxIA z(`%ex@%ytb_B-mr>yT2`DnyYn-ob`~XQCJS^qN*k!$Q`3A!_}isDzm@3jX-hVOPh{ z952rVyF~LQyvnd?I9-9EDZ639enelv!{G8YyRc8Qy;(5p>u}6Co5-u1l!@&87Ycx; z2#1*^VW9TBkSEdKLs-NWcYl9PT|g+Oh9^g+B4Z2HHH%zTduyiByW4U@x9^lgf401T zeusKLf5i7(ZpscdAgAB4RE~9YbK&LA3OT5t)#F&ivB?(+t|%X*KWExUkHm^I-BZ5M zr|=D`_A1{yXT!nzWtiry)H8=4J<%y*Yo$YkfyXTD_hppt&igO0xrR$H`z_qQFX1F} z#IGA|q2c;;Fk1oAQQKRiJ(Tu!$H!D1Y;Uw^nkuYhO9`)K02%OJxm5kKOoFHsto59@w};q}ZLh=#8Rh3r+r zX8%zOCpQb?SErHl(#k8C;yKNG(c4@Or^VDGPjy=wQ7*L_zriQ?Igm2nSMB1W+j@Mm zdcB=OxdPlMUVa#z@@F$bGkXcDQu#|~noz{zN!_8n;qQ06h3JmCSJu6KZDLPI)kOom z?!BS~g-?x@d*0vPv#m+ey zbh#@YEw-IBx|*Y9(C*XAH0GKItg@HPM?^JG(LJ66lHe*QV}9^ZB*2uDgNX#5kviPWi+g3 zTaR(02Dc^5;;z!^o?p$6INnC6BW&k9VO;lF!|PRnT?2q5c`MJv*w72t+!yERi&M!B zS%J}=ze|Sz$?$oHkeXss&HO!@`SE%`xMh7-${`n&d#uO9lB6Cv!F zTPzsq>r>c^d-hqF00Emy*%bKRE9Uw-%y$%4!6x)|u_~QFWdk zKo5gFbq!+8?FR16icHz-9OX3~;qF;A37OUo4#C`lvd~BdgMFQ5R3_|OJMU>C)ixlV zn0{5w3piF8T@(|h#pU+v?<&!ZPs-r9e4?m-u-$6&YowqK0rvEe<(m%>54faW#k9<0yWYIhjc+SaH)N z@AHR(3J_X~^6JK8g15>05W)@Va8!z~&4B5vGt!;X)$tUdOTNbJc#zKXqZ(LL|qdiv*| zMo9XimWt#+(Mh0#|o^?&he)w95p;L7;*GXWRZ zno>G{$@CHmpzVx(O9{*9UxuO`cME0*4BvC{CQ!EJ;yy$1OM^aqe~s5LR%m9aE0Nlv0mGHo*1B(~!j3Tsk@$j){F5>4Cu~BL65Ws$4Ora{yxlBo z+sNZH|1(LO>KId9EVHScD#jmKoL99nH(i1A2?xZ!X?9lO%OJNn>9(+3jq@Hw47Ef? zBr486iJG+(ynsYEWhm)OwV)(j@ymA?( zH&7-8-Cj{8|G{AM28&mipnXtj9fB=I%Tak_4faY= zP885N>-gv8{hO#F)hrk%oo1ITWs$Nh=UMbn1z9yab2rF*2O&9pb0>@(2UYC5_6VY6 zz7YgPPtXPXHm{q^C7l#*pUu^WC3_kBYDp$^7CJJA)&*CZSqIHa>_cRQp@RS0&Zxn% zY!s~HnG6G% coverage.txt + +# Standard go tooling behavior is to ignore dirs with leading underscores +# skip generator for race detection and coverage +for dir in $(go list ./...) +do + pth="$GOPATH/src/$dir" + go test -race -timeout 20m -covermode=${GOCOVMODE-atomic} -coverprofile=${pth}/profile.out $dir + if [ -f $pth/profile.out ] + then + cat $pth/profile.out | tail -n +2 >> coverage.txt + rm $pth/profile.out + fi +done + +go tool cover -func coverage.txt diff --git a/vendor/github.com/go-openapi/runtime/hack/gen-self-signed-certs.sh b/vendor/github.com/go-openapi/runtime/hack/gen-self-signed-certs.sh new file mode 100755 index 0000000000..10b020e760 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/hack/gen-self-signed-certs.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# generate CA +openssl genrsa -out myCA.key 4096 +openssl req -x509 -new -key myCA.key -out myCA.crt -days 730 -subj /CN="Go Swagger" + +# generate server cert and key +openssl genrsa -out mycert1.key 4096 +openssl req -new -out mycert1.req -key mycert1.key -subj /CN="goswagger.local" +openssl x509 -req -in mycert1.req -out mycert1.crt -CAkey myCA.key -CA myCA.crt -days 365 -CAcreateserial -CAserial serial + +# generate client cert, key and bundle +openssl genrsa -out myclient.key 4096 +openssl req -new -key myclient.key -out myclient.csr +openssl x509 -req -days 730 -in myclient.csr -out myclient.crt -CAkey myCA.key -CA myCA.crt -days 365 -CAcreateserial -CAserial serial +openssl pkcs12 -export -clcerts -in myclient.crt -inkey myclient.key -out myclient.p12 diff --git a/vendor/github.com/go-openapi/runtime/headers.go b/vendor/github.com/go-openapi/runtime/headers.go new file mode 100644 index 0000000000..4d111db4fe --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/headers.go @@ -0,0 +1,45 @@ +// 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 runtime + +import ( + "mime" + "net/http" + + "github.com/go-openapi/errors" +) + +// ContentType parses a content type header +func ContentType(headers http.Header) (string, string, error) { + ct := headers.Get(HeaderContentType) + orig := ct + if ct == "" { + ct = DefaultMime + } + if ct == "" { + return "", "", nil + } + + mt, opts, err := mime.ParseMediaType(ct) + if err != nil { + return "", "", errors.NewParseError(HeaderContentType, "header", orig, err) + } + + if cs, ok := opts[charsetKey]; ok { + return mt, cs, nil + } + + return mt, "", nil +} diff --git a/vendor/github.com/go-openapi/runtime/headers_test.go b/vendor/github.com/go-openapi/runtime/headers_test.go new file mode 100644 index 0000000000..c9e3343895 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/headers_test.go @@ -0,0 +1,61 @@ +// 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 runtime + +import ( + "mime" + "net/http" + "testing" + + "github.com/go-openapi/errors" + "github.com/stretchr/testify/assert" +) + +func TestParseContentType(t *testing.T) { + _, _, reason1 := mime.ParseMediaType("application(") + _, _, reason2 := mime.ParseMediaType("application/json;char*") + data := []struct { + hdr, mt, cs string + err *errors.ParseError + }{ + {"application/json", "application/json", "", nil}, + {"text/html; charset=utf-8", "text/html", "utf-8", nil}, + {"text/html;charset=utf-8", "text/html", "utf-8", nil}, + {"", "application/octet-stream", "", nil}, + {"text/html; charset=utf-8", "text/html", "utf-8", nil}, + {"application(", "", "", errors.NewParseError("Content-Type", "header", "application(", reason1)}, + {"application/json;char*", "", "", errors.NewParseError("Content-Type", "header", "application/json;char*", reason2)}, + } + + headers := http.Header(map[string][]string{}) + for _, v := range data { + if v.hdr != "" { + headers.Set("Content-Type", v.hdr) + } else { + headers.Del("Content-Type") + } + ct, cs, err := ContentType(headers) + if v.err == nil { + assert.NoError(t, err, "input: %q, err: %v", v.hdr, err) + } else { + assert.Error(t, err, "input: %q", v.hdr) + assert.IsType(t, &errors.ParseError{}, err, "input: %q", v.hdr) + assert.Equal(t, v.err.Error(), err.Error(), "input: %q", v.hdr) + } + assert.Equal(t, v.mt, ct, "input: %q", v.hdr) + assert.Equal(t, v.cs, cs, "input: %q", v.hdr) + } + +} diff --git a/vendor/github.com/go-openapi/runtime/interfaces.go b/vendor/github.com/go-openapi/runtime/interfaces.go new file mode 100644 index 0000000000..5f2a472a83 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/interfaces.go @@ -0,0 +1,103 @@ +// 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 runtime + +import ( + "io" + "net/http" + + "github.com/go-openapi/strfmt" +) + +// OperationHandlerFunc an adapter for a function to the OperationHandler interface +type OperationHandlerFunc func(interface{}) (interface{}, error) + +// Handle implements the operation handler interface +func (s OperationHandlerFunc) Handle(data interface{}) (interface{}, error) { + return s(data) +} + +// OperationHandler a handler for a swagger operation +type OperationHandler interface { + Handle(interface{}) (interface{}, error) +} + +// ConsumerFunc represents a function that can be used as a consumer +type ConsumerFunc func(io.Reader, interface{}) error + +// Consume consumes the reader into the data parameter +func (fn ConsumerFunc) Consume(reader io.Reader, data interface{}) error { + return fn(reader, data) +} + +// Consumer implementations know how to bind the values on the provided interface to +// data provided by the request body +type Consumer interface { + // Consume performs the binding of request values + Consume(io.Reader, interface{}) error +} + +// ProducerFunc represents a function that can be used as a producer +type ProducerFunc func(io.Writer, interface{}) error + +// Produce produces the response for the provided data +func (f ProducerFunc) Produce(writer io.Writer, data interface{}) error { + return f(writer, data) +} + +// Producer implementations know how to turn the provided interface into a valid +// HTTP response +type Producer interface { + // Produce writes to the http response + Produce(io.Writer, interface{}) error +} + +// AuthenticatorFunc turns a function into an authenticator +type AuthenticatorFunc func(interface{}) (bool, interface{}, error) + +// Authenticate authenticates the request with the provided data +func (f AuthenticatorFunc) Authenticate(params interface{}) (bool, interface{}, error) { + return f(params) +} + +// Authenticator represents an authentication strategy +// implementations of Authenticator know how to authenticate the +// request data and translate that into a valid principal object or an error +type Authenticator interface { + Authenticate(interface{}) (bool, interface{}, error) +} + +// AuthorizerFunc turns a function into an authorizer +type AuthorizerFunc func(*http.Request, interface{}) error + +// Authorize authorizes the processing of the request for the principal +func (f AuthorizerFunc) Authorize(r *http.Request, principal interface{}) error { + return f(r, principal) +} + +// Authorizer represents an authorization strategy +// implementations of Authorizer know how to authorize the principal object +// using the request data and returns error if unauthorized +type Authorizer interface { + Authorize(*http.Request, interface{}) error +} + +// Validatable types implementing this interface allow customizing their validation +// this will be used instead of the reflective valditation based on the spec document. +// the implementations are assumed to have been generated by the swagger tool so they should +// contain all the validations obtained from the spec +type Validatable interface { + Validate(strfmt.Registry) error +} diff --git a/vendor/github.com/go-openapi/runtime/internal/testing/data.go b/vendor/github.com/go-openapi/runtime/internal/testing/data.go new file mode 100644 index 0000000000..b1102809f0 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/internal/testing/data.go @@ -0,0 +1,811 @@ +// 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 testing + +import ( + "encoding/json" +) + +// PetStore20YAML yaml doc for swagger 2.0 pet store +const PetStore20YAML = `swagger: '2.0' +info: + version: '1.0.0' + title: Swagger Petstore + description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification + termsOfService: http://helloreverb.com/terms/ + contact: + name: Swagger API team + email: foo@example.com + url: http://swagger.io + license: + name: MIT + url: http://opensource.org/licenses/MIT +host: petstore.swagger.wordnik.com +basePath: /api +schemes: + - http +consumes: + - application/json +produces: + - application/json +paths: + /pets: + get: + description: Returns all pets from the system that the user has access to + operationId: findPets + produces: + - application/json + - application/xml + - text/xml + - text/html + parameters: + - name: tags + in: query + description: tags to filter by + required: false + type: array + items: + type: string + collectionFormat: csv + - name: limit + in: query + description: maximum number of results to return + required: false + type: integer + format: int32 + responses: + '200': + description: pet response + schema: + type: array + items: + $ref: '#/definitions/pet' + default: + description: unexpected error + schema: + $ref: '#/definitions/errorModel' + post: + description: Creates a new pet in the store. Duplicates are allowed + operationId: addPet + produces: + - application/json + parameters: + - name: pet + in: body + description: Pet to add to the store + required: true + schema: + $ref: '#/definitions/newPet' + responses: + '200': + description: pet response + schema: + $ref: '#/definitions/pet' + default: + description: unexpected error + schema: + $ref: '#/definitions/errorModel' + /pets/{id}: + get: + description: Returns a user based on a single ID, if the user does not have access to the pet + operationId: findPetById + produces: + - application/json + - application/xml + - text/xml + - text/html + parameters: + - name: id + in: path + description: ID of pet to fetch + required: true + type: integer + format: int64 + responses: + '200': + description: pet response + schema: + $ref: '#/definitions/pet' + default: + description: unexpected error + schema: + $ref: '#/definitions/errorModel' + delete: + description: deletes a single pet based on the ID supplied + operationId: deletePet + parameters: + - name: id + in: path + description: ID of pet to delete + required: true + type: integer + format: int64 + responses: + '204': + description: pet deleted + default: + description: unexpected error + schema: + $ref: '#/definitions/errorModel' +definitions: + pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + newPet: + allOf: + - $ref: '#/definitions/pet' + - required: + - name + properties: + id: + type: integer + format: int64 + name: + type: string + errorModel: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string +` + +// PetStore20 json doc for swagger 2.0 pet store +const PetStore20 = `{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "contact": { + "name": "Wordnik API Team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "petstore.swagger.wordnik.com", + "basePath": "/api", + "schemes": [ + "http" + ], + "paths": { + "/pets": { + "get": { + "security": [ + { + "basic": [] + } + ], + "tags": [ "Pet Operations" ], + "operationId": "getAllPets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "The status to filter by", + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "The maximum number of results to return", + "type": "integer", + "format": "int64" + } + ], + "summary": "Finds all pets in the system", + "responses": { + "200": { + "description": "Pet response", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "post": { + "security": [ + { + "basic": [] + } + ], + "tags": [ "Pet Operations" ], + "operationId": "createPet", + "summary": "Creates a new pet", + "consumes": ["application/x-yaml"], + "produces": ["application/x-yaml"], + "parameters": [ + { + "name": "pet", + "in": "body", + "description": "The Pet to create", + "required": true, + "schema": { + "$ref": "#/definitions/newPet" + } + } + ], + "responses": { + "200": { + "description": "Created Pet response", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/pets/{id}": { + "delete": { + "security": [ + { + "apiKey": [] + } + ], + "description": "Deletes the Pet by id", + "operationId": "deletePet", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "204": { + "description": "pet deleted" + }, + "default": { + "description": "unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "tags": [ "Pet Operations" ], + "operationId": "getPetById", + "summary": "Finds the pet by id", + "responses": { + "200": { + "description": "Pet response", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet", + "required": true, + "type": "integer", + "format": "int64" + } + ] + } + }, + "definitions": { + "Category": { + "id": "Category", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "Pet": { + "id": "Pet", + "properties": { + "category": { + "$ref": "#/definitions/Category" + }, + "id": { + "description": "unique identifier for the pet", + "format": "int64", + "maximum": 100.0, + "minimum": 0.0, + "type": "integer" + }, + "name": { + "type": "string" + }, + "photoUrls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ], + "type": "string" + }, + "tags": { + "items": { + "$ref": "#/definitions/Tag" + }, + "type": "array" + } + }, + "required": [ + "id", + "name" + ] + }, + "newPet": { + "anyOf": [ + { + "$ref": "#/definitions/Pet" + }, + { + "required": [ + "name" + ] + } + ] + }, + "Tag": { + "id": "Tag", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "Error": { + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + }, + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/json", + "application/xml", + "text/plain", + "text/html" + ], + "securityDefinitions": { + "basic": { + "type": "basic" + }, + "apiKey": { + "type": "apiKey", + "in": "header", + "name": "X-API-KEY" + } + } +} +` + +// RootPetStore20 json doc for swagger 2.0 pet store at / +const RootPetStore20 = `{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "contact": { + "name": "Wordnik API Team", + "url": "http://developer.wordnik.com" + }, + "license": { + "name": "Creative Commons 4.0 International", + "url": "http://creativecommons.org/licenses/by/4.0/" + } + }, + "host": "petstore.swagger.wordnik.com", + "basePath": "/", + "schemes": [ + "http" + ], + "paths": { + "/pets": { + "get": { + "security": [ + { + "basic": [] + } + ], + "tags": [ "Pet Operations" ], + "operationId": "getAllPets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "The status to filter by", + "type": "string" + } + ], + "summary": "Finds all pets in the system", + "responses": { + "200": { + "description": "Pet response", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "post": { + "security": [ + { + "basic": [] + } + ], + "tags": [ "Pet Operations" ], + "operationId": "createPet", + "summary": "Creates a new pet", + "consumes": ["application/x-yaml"], + "produces": ["application/x-yaml"], + "parameters": [ + { + "name": "pet", + "in": "body", + "description": "The Pet to create", + "required": true, + "schema": { + "$ref": "#/definitions/newPet" + } + } + ], + "responses": { + "200": { + "description": "Created Pet response", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/pets/{id}": { + "delete": { + "security": [ + { + "apiKey": [] + } + ], + "description": "Deletes the Pet by id", + "operationId": "deletePet", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "204": { + "description": "pet deleted" + }, + "default": { + "description": "unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "get": { + "tags": [ "Pet Operations" ], + "operationId": "getPetById", + "summary": "Finds the pet by id", + "responses": { + "200": { + "description": "Pet response", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet", + "required": true, + "type": "integer", + "format": "int64" + } + ] + } + }, + "definitions": { + "Category": { + "id": "Category", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "Pet": { + "id": "Pet", + "properties": { + "category": { + "$ref": "#/definitions/Category" + }, + "id": { + "description": "unique identifier for the pet", + "format": "int64", + "maximum": 100.0, + "minimum": 0.0, + "type": "integer" + }, + "name": { + "type": "string" + }, + "photoUrls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ], + "type": "string" + }, + "tags": { + "items": { + "$ref": "#/definitions/Tag" + }, + "type": "array" + } + }, + "required": [ + "id", + "name" + ] + }, + "newPet": { + "anyOf": [ + { + "$ref": "#/definitions/Pet" + }, + { + "required": [ + "name" + ] + } + ] + }, + "Tag": { + "id": "Tag", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "Error": { + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + }, + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/json", + "application/xml", + "text/plain", + "text/html" + ], + "securityDefinitions": { + "basic": { + "type": "basic" + }, + "apiKey": { + "type": "apiKey", + "in": "header", + "name": "X-API-KEY" + } + } +} +` + +// PetStoreJSONMessage json raw message for Petstore20 +var PetStoreJSONMessage = json.RawMessage([]byte(PetStore20)) + +// RootPetStoreJSONMessage json raw message for Petstore20 +var RootPetStoreJSONMessage = json.RawMessage([]byte(RootPetStore20)) + +// InvalidJSON invalid swagger 2.0 spec in JSON +const InvalidJSON = `{ + "apiVersion": "1.0.0", + "apis": [ + { + "description": "Operations about pets", + "path": "/pet" + }, + { + "description": "Operations about user", + "path": "/user" + }, + { + "description": "Operations about store", + "path": "/store" + } + ], + "authorizations": { + "oauth2": { + "grantTypes": { + "authorization_code": { + "tokenEndpoint": { + "tokenName": "auth_code", + "url": "http://petstore.swagger.wordnik.com/oauth/token" + }, + "tokenRequestEndpoint": { + "clientIdName": "client_id", + "clientSecretName": "client_secret", + "url": "http://petstore.swagger.wordnik.com/oauth/requestToken" + } + }, + "implicit": { + "loginEndpoint": { + "url": "http://petstore.swagger.wordnik.com/oauth/dialog" + }, + "tokenName": "access_token" + } + }, + "scopes": [ + { + "description": "Modify pets in your account", + "scope": "write:pets" + }, + { + "description": "Read your pets", + "scope": "read:pets" + }, + { + "description": "Anything (testing)", + "scope": "test:anything" + } + ], + "type": "oauth2" + } + }, + "info": { + "contact": "apiteam@wordnik.com", + "description": "This is a sample server Petstore server. You can find out more about Swagger \n at http://swagger.wordnik.com or on irc.freenode.net, #swagger. For this sample,\n you can use the api key \"special-key\" to test the authorization filters", + "license": "Apache 2.0", + "licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.html", + "termsOfServiceUrl": "http://helloreverb.com/terms/", + "title": "Swagger Sample App" + }, + "swaggerVersion": "1.2" +} +` + +// InvalidJSONMessage json raw message for invalid json +var InvalidJSONMessage = json.RawMessage([]byte(InvalidJSON)) diff --git a/vendor/github.com/go-openapi/runtime/internal/testing/petstore/api.go b/vendor/github.com/go-openapi/runtime/internal/testing/petstore/api.go new file mode 100644 index 0000000000..2a066cee1b --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/internal/testing/petstore/api.go @@ -0,0 +1,159 @@ +// 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 petstore + +import ( + goerrors "errors" + "io" + "net/http" + "strings" + gotest "testing" + + "github.com/go-openapi/errors" + "github.com/go-openapi/loads" + "github.com/go-openapi/runtime" + testingutil "github.com/go-openapi/runtime/internal/testing" + "github.com/go-openapi/runtime/middleware/untyped" + "github.com/go-openapi/runtime/security" + "github.com/go-openapi/runtime/yamlpc" + "github.com/stretchr/testify/assert" +) + +// NewAPI registers a stub api for the pet store +func NewAPI(t gotest.TB) (*loads.Document, *untyped.API) { + spec, err := loads.Analyzed(testingutil.PetStoreJSONMessage, "") + assert.NoError(t, err) + api := untyped.NewAPI(spec) + + api.RegisterConsumer("application/json", runtime.JSONConsumer()) + api.RegisterProducer("application/json", runtime.JSONProducer()) + api.RegisterConsumer("application/xml", new(stubConsumer)) + api.RegisterProducer("application/xml", new(stubProducer)) + api.RegisterProducer("text/plain", new(stubProducer)) + api.RegisterProducer("text/html", new(stubProducer)) + api.RegisterConsumer("application/x-yaml", yamlpc.YAMLConsumer()) + api.RegisterProducer("application/x-yaml", yamlpc.YAMLProducer()) + + api.RegisterAuth("basic", security.BasicAuth(func(username, password string) (interface{}, error) { + if username == "admin" && password == "admin" { + return "admin", nil + } else if username == "topuser" && password == "topuser" { + return "topuser", nil + } + return nil, errors.Unauthenticated("basic") + })) + api.RegisterAuth("apiKey", security.APIKeyAuth("X-API-KEY", "header", func(token string) (interface{}, error) { + if token == "token123" { + return "admin", nil + } + return nil, errors.Unauthenticated("token") + })) + api.RegisterAuthorizer(runtime.AuthorizerFunc(func(r *http.Request, user interface{}) error { + if r.Method == http.MethodPost && strings.HasPrefix(r.URL.Path, "/api/pets") && user.(string) != "admin" { + return goerrors.New("unauthorized") + } + return nil + })) + api.RegisterOperation("get", "/pets", new(stubOperationHandler)) + api.RegisterOperation("post", "/pets", new(stubOperationHandler)) + api.RegisterOperation("delete", "/pets/{id}", new(stubOperationHandler)) + api.RegisterOperation("get", "/pets/{id}", new(stubOperationHandler)) + + api.Models["pet"] = func() interface{} { return new(Pet) } + api.Models["newPet"] = func() interface{} { return new(Pet) } + api.Models["tag"] = func() interface{} { return new(Tag) } + + return spec, api +} + +// NewRootAPI registers a stub api for the pet store +func NewRootAPI(t gotest.TB) (*loads.Document, *untyped.API) { + spec, err := loads.Analyzed(testingutil.RootPetStoreJSONMessage, "") + assert.NoError(t, err) + api := untyped.NewAPI(spec) + + api.RegisterConsumer("application/json", runtime.JSONConsumer()) + api.RegisterProducer("application/json", runtime.JSONProducer()) + api.RegisterConsumer("application/xml", new(stubConsumer)) + api.RegisterProducer("application/xml", new(stubProducer)) + api.RegisterProducer("text/plain", new(stubProducer)) + api.RegisterProducer("text/html", new(stubProducer)) + api.RegisterConsumer("application/x-yaml", yamlpc.YAMLConsumer()) + api.RegisterProducer("application/x-yaml", yamlpc.YAMLProducer()) + + api.RegisterAuth("basic", security.BasicAuth(func(username, password string) (interface{}, error) { + if username == "admin" && password == "admin" { + return "admin", nil + } + return nil, errors.Unauthenticated("basic") + })) + api.RegisterAuth("apiKey", security.APIKeyAuth("X-API-KEY", "header", func(token string) (interface{}, error) { + if token == "token123" { + return "admin", nil + } + return nil, errors.Unauthenticated("token") + })) + api.RegisterAuthorizer(security.Authorized()) + api.RegisterOperation("get", "/pets", new(stubOperationHandler)) + api.RegisterOperation("post", "/pets", new(stubOperationHandler)) + api.RegisterOperation("delete", "/pets/{id}", new(stubOperationHandler)) + api.RegisterOperation("get", "/pets/{id}", new(stubOperationHandler)) + + api.Models["pet"] = func() interface{} { return new(Pet) } + api.Models["newPet"] = func() interface{} { return new(Pet) } + api.Models["tag"] = func() interface{} { return new(Tag) } + + return spec, api +} + +// Tag the tag model +type Tag struct { + ID int64 + Name string +} + +// Pet the pet model +type Pet struct { + ID int64 + Name string + PhotoURLs []string + Status string + Tags []Tag +} + +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(params interface{}) (interface{}, error) { + return nil, nil +} diff --git a/vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api.go b/vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api.go new file mode 100644 index 0000000000..1505420057 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api.go @@ -0,0 +1,351 @@ +// 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 simplepetstore + +import ( + "encoding/json" + "net/http" + "sync" + "sync/atomic" + + "github.com/go-openapi/errors" + "github.com/go-openapi/loads" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/middleware/untyped" +) + +// NewPetstore creates a new petstore api handler +func NewPetstore() (http.Handler, error) { + spec, err := loads.Analyzed(json.RawMessage([]byte(swaggerJSON)), "") + if err != nil { + return nil, err + } + api := untyped.NewAPI(spec) + + api.RegisterOperation("get", "/pets", getAllPets) + api.RegisterOperation("post", "/pets", createPet) + api.RegisterOperation("delete", "/pets/{id}", deletePet) + api.RegisterOperation("get", "/pets/{id}", getPetByID) + + return middleware.Serve(spec, api), nil +} + +var getAllPets = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) { + return pets, nil +}) + +var createPet = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) { + body := data.(map[string]interface{})["pet"].(map[string]interface{}) + return addPet(Pet{ + Name: body["name"].(string), + Status: body["status"].(string), + }), nil +}) + +var deletePet = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) { + id := data.(map[string]interface{})["id"].(int64) + removePet(id) + return nil, nil +}) + +var getPetByID = runtime.OperationHandlerFunc(func(data interface{}) (interface{}, error) { + id := data.(map[string]interface{})["id"].(int64) + return petByID(id) +}) + +// Tag the tag model +type Tag struct { + ID int64 + Name string +} + +// Pet the pet model +type Pet struct { + ID int64 `json:"id"` + Name string `json:"name"` + PhotoURLs []string `json:"photoUrls,omitempty"` + Status string `json:"status,omitempty"` + Tags []Tag `json:"tags,omitempty"` +} + +var pets = []Pet{ + {1, "Dog", []string{}, "available", nil}, + {2, "Cat", []string{}, "pending", nil}, +} + +var petsLock = &sync.Mutex{} +var lastPetID int64 = 2 + +func newPetID() int64 { + return atomic.AddInt64(&lastPetID, 1) +} + +func addPet(pet Pet) Pet { + petsLock.Lock() + defer petsLock.Unlock() + pet.ID = newPetID() + pets = append(pets, pet) + return pet +} + +func removePet(id int64) { + petsLock.Lock() + defer petsLock.Unlock() + var newPets []Pet + for _, pet := range pets { + if pet.ID != id { + newPets = append(newPets, pet) + } + } + pets = newPets +} + +func petByID(id int64) (*Pet, error) { + for _, pet := range pets { + if pet.ID == id { + return &pet, nil + } + } + return nil, errors.NotFound("not found: pet %d", id) +} + +var swaggerJSON = `{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "Wordnik API Team" + }, + "license": { + "name": "MIT" + } + }, + "host": "localhost:8344", + "basePath": "/api", + "schemes": [ + "http" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/pets": { + "get": { + "description": "Returns all pets from the system that the user has access to", + "operationId": "findPets", + "produces": [ + "application/json", + "application/xml", + "text/xml", + "text/html" + ], + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "tags to filter by", + "required": false, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv" + }, + { + "name": "limit", + "in": "query", + "description": "maximum number of results to return", + "required": false, + "type": "integer", + "format": "int32" + } + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/pet" + } + } + }, + "default": { + "description": "unexpected error", + "schema": { + "$ref": "#/definitions/errorModel" + } + } + } + }, + "post": { + "description": "Creates a new pet in the store. Duplicates are allowed", + "operationId": "addPet", + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "pet", + "in": "body", + "description": "Pet to add to the store", + "required": true, + "schema": { + "$ref": "#/definitions/petInput" + } + } + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "$ref": "#/definitions/pet" + } + }, + "default": { + "description": "unexpected error", + "schema": { + "$ref": "#/definitions/errorModel" + } + } + } + } + }, + "/pets/{id}": { + "get": { + "description": "Returns a user based on a single ID, if the user does not have access to the pet", + "operationId": "findPetById", + "produces": [ + "application/json", + "application/xml", + "text/xml", + "text/html" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to fetch", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "200": { + "description": "pet response", + "schema": { + "$ref": "#/definitions/pet" + } + }, + "default": { + "description": "unexpected error", + "schema": { + "$ref": "#/definitions/errorModel" + } + } + } + }, + "delete": { + "description": "deletes a single pet based on the ID supplied", + "operationId": "deletePet", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of pet to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "204": { + "description": "pet deleted" + }, + "default": { + "description": "unexpected error", + "schema": { + "$ref": "#/definitions/errorModel" + } + } + } + } + } + }, + "definitions": { + "pet": { + "required": [ + "name", + "status" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "petInput": { + "allOf": [ + { + "$ref": "#/definitions/pet" + }, + { + "properties": { + "id": { + "type": "integer", + "format": "int64" + } + } + } + ] + }, + "errorModel": { + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } +}` diff --git a/vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api_test.go b/vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api_test.go new file mode 100644 index 0000000000..6681863d85 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/internal/testing/simplepetstore/api_test.go @@ -0,0 +1,81 @@ +// 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 simplepetstore + +import ( + "bytes" + "net/http/httptest" + "testing" + + "github.com/go-openapi/runtime" + "github.com/stretchr/testify/assert" +) + +func TestSimplePetstoreSpec(t *testing.T) { + handler, _ := NewPetstore() + // Serves swagger spec document + r, _ := runtime.JSONRequest("GET", "/swagger.json", nil) + rw := httptest.NewRecorder() + handler.ServeHTTP(rw, r) + assert.Equal(t, 200, rw.Code) + assert.Equal(t, swaggerJSON, rw.Body.String()) +} + +func TestSimplePetstoreAllPets(t *testing.T) { + handler, _ := NewPetstore() + // Serves swagger spec document + r, _ := runtime.JSONRequest("GET", "/api/pets", nil) + rw := httptest.NewRecorder() + handler.ServeHTTP(rw, r) + assert.Equal(t, 200, rw.Code) + assert.Equal(t, "[{\"id\":1,\"name\":\"Dog\",\"status\":\"available\"},{\"id\":2,\"name\":\"Cat\",\"status\":\"pending\"}]\n", rw.Body.String()) +} + +func TestSimplePetstorePetByID(t *testing.T) { + handler, _ := NewPetstore() + + // Serves swagger spec document + r, _ := runtime.JSONRequest("GET", "/api/pets/1", nil) + rw := httptest.NewRecorder() + handler.ServeHTTP(rw, r) + assert.Equal(t, 200, rw.Code) + assert.Equal(t, "{\"id\":1,\"name\":\"Dog\",\"status\":\"available\"}\n", rw.Body.String()) +} + +func TestSimplePetstoreAddPet(t *testing.T) { + handler, _ := NewPetstore() + // Serves swagger spec document + r, _ := runtime.JSONRequest("POST", "/api/pets", bytes.NewBuffer([]byte(`{"name": "Fish","status": "available"}`))) + rw := httptest.NewRecorder() + handler.ServeHTTP(rw, r) + assert.Equal(t, 200, rw.Code) + assert.Equal(t, "{\"id\":3,\"name\":\"Fish\",\"status\":\"available\"}\n", rw.Body.String()) +} + +func TestSimplePetstoreDeletePet(t *testing.T) { + handler, _ := NewPetstore() + // Serves swagger spec document + r, _ := runtime.JSONRequest("DELETE", "/api/pets/1", nil) + rw := httptest.NewRecorder() + handler.ServeHTTP(rw, r) + assert.Equal(t, 204, rw.Code) + assert.Equal(t, "", rw.Body.String()) + + r, _ = runtime.JSONRequest("GET", "/api/pets/1", nil) + rw = httptest.NewRecorder() + handler.ServeHTTP(rw, r) + assert.Equal(t, 404, rw.Code) + assert.Equal(t, "{\"code\":404,\"message\":\"not found: pet 1\"}", rw.Body.String()) +} diff --git a/vendor/github.com/go-openapi/runtime/json.go b/vendor/github.com/go-openapi/runtime/json.go new file mode 100644 index 0000000000..81ee360b59 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/json.go @@ -0,0 +1,37 @@ +// 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 runtime + +import ( + "encoding/json" + "io" +) + +// JSONConsumer creates a new JSON consumer +func JSONConsumer() Consumer { + return ConsumerFunc(func(reader io.Reader, data interface{}) error { + dec := json.NewDecoder(reader) + dec.UseNumber() // preserve number formats + return dec.Decode(data) + }) +} + +// JSONProducer creates a new JSON producer +func JSONProducer() Producer { + return ProducerFunc(func(writer io.Writer, data interface{}) error { + enc := json.NewEncoder(writer) + return enc.Encode(data) + }) +} diff --git a/vendor/github.com/go-openapi/runtime/json_test.go b/vendor/github.com/go-openapi/runtime/json_test.go new file mode 100644 index 0000000000..5e11d03ca2 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/json_test.go @@ -0,0 +1,62 @@ +// 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 runtime + +import ( + "bytes" + "io" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +var consProdJSON = `{"name":"Somebody","id":1}` + +type eofRdr struct { +} + +func (r *eofRdr) Read(d []byte) (int, error) { + return 0, io.EOF +} + +func TestJSONConsumer(t *testing.T) { + cons := JSONConsumer() + var data struct { + Name string + ID int + } + err := cons.Consume(bytes.NewBuffer([]byte(consProdJSON)), &data) + if assert.NoError(t, err) { + assert.Equal(t, "Somebody", data.Name) + assert.Equal(t, 1, data.ID) + + err = cons.Consume(new(eofRdr), &data) + assert.Error(t, err) + } +} + +func TestJSONProducer(t *testing.T) { + prod := JSONProducer() + data := struct { + Name string `json:"name"` + ID int `json:"id"` + }{Name: "Somebody", ID: 1} + + rw := httptest.NewRecorder() + err := prod.Produce(rw, data) + assert.NoError(t, err) + assert.Equal(t, consProdJSON+"\n", rw.Body.String()) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/body_test.go b/vendor/github.com/go-openapi/runtime/middleware/body_test.go new file mode 100644 index 0000000000..7e8ad0f932 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/body_test.go @@ -0,0 +1,101 @@ +package middleware + +import ( + "io" + "net/http" + "path" + "testing" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/internal/testing/petstore" + "github.com/stretchr/testify/assert" +) + +type eofReader struct { +} + +func (r *eofReader) Read(b []byte) (int, error) { + return 0, io.EOF +} + +func (r *eofReader) Close() error { + return nil +} + +type rbn func(*http.Request, *MatchedRoute) error + +func (b rbn) BindRequest(r *http.Request, rr *MatchedRoute) error { + return b(r, rr) +} + +func TestBindRequest_BodyValidation(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + api.DefaultConsumes = runtime.JSONMime + ctx.router = DefaultRouter(spec, ctx.api) + + req, err := http.NewRequest("GET", path.Join(spec.BasePath(), "/pets"), new(eofReader)) + if assert.NoError(t, err) { + req.Header.Set("Content-Type", runtime.JSONMime) + + ri, rCtx, ok := ctx.RouteInfo(req) + if assert.True(t, ok) { + req = rCtx + err := ctx.BindValidRequest(req, ri, rbn(func(r *http.Request, rr *MatchedRoute) error { + defer r.Body.Close() + var data interface{} + err := runtime.JSONConsumer().Consume(r.Body, &data) + _ = data + return err + })) + + assert.Error(t, err) + assert.Equal(t, io.EOF, err) + } + } +} + +func TestBindRequest_DeleteNoBody(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + api.DefaultConsumes = runtime.JSONMime + ctx.router = DefaultRouter(spec, ctx.api) + + req, err := http.NewRequest("DELETE", path.Join(spec.BasePath(), "/pets/123"), new(eofReader)) + if assert.NoError(t, err) { + req.Header.Set("Accept", "*/*") + + ri, rCtx, ok := ctx.RouteInfo(req) + if assert.True(t, ok) { + req = rCtx + bverr := ctx.BindValidRequest(req, ri, rbn(func(r *http.Request, rr *MatchedRoute) error { + return nil + })) + + assert.NoError(t, bverr) + //assert.Equal(t, io.EOF, bverr) + } + } + + req, err = http.NewRequest("DELETE", path.Join(spec.BasePath(), "/pets/123"), new(eofReader)) + if assert.NoError(t, err) { + req.Header.Set("Accept", "*/*") + req.Header.Set("Content-Type", runtime.JSONMime) + req.ContentLength = 1 + + ri, rCtx, ok := ctx.RouteInfo(req) + if assert.True(t, ok) { + req = rCtx + err := ctx.BindValidRequest(req, ri, rbn(func(r *http.Request, rr *MatchedRoute) error { + defer r.Body.Close() + var data interface{} + err := runtime.JSONConsumer().Consume(r.Body, &data) + _ = data + return err + })) + + assert.Error(t, err) + assert.Equal(t, io.EOF, err) + } + } +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/context.go b/vendor/github.com/go-openapi/runtime/middleware/context.go new file mode 100644 index 0000000000..c5c6c6efc8 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/context.go @@ -0,0 +1,559 @@ +// 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 middleware + +import ( + stdContext "context" + "log" + "net/http" + "os" + "strings" + "sync" + + "github.com/go-openapi/analysis" + "github.com/go-openapi/errors" + "github.com/go-openapi/loads" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware/untyped" + "github.com/go-openapi/runtime/security" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" +) + +// Debug when true turns on verbose logging +var Debug = os.Getenv("SWAGGER_DEBUG") != "" || os.Getenv("DEBUG") != "" + +func debugLog(format string, args ...interface{}) { + if Debug { + log.Printf(format, args...) + } +} + +// A Builder can create middlewares +type Builder func(http.Handler) http.Handler + +// PassthroughBuilder returns the handler, aka the builder identity function +func PassthroughBuilder(handler http.Handler) http.Handler { return handler } + +// RequestBinder is an interface for types to implement +// when they want to be able to bind from a request +type RequestBinder interface { + BindRequest(*http.Request, *MatchedRoute) error +} + +// Responder is an interface for types to implement +// when they want to be considered for writing HTTP responses +type Responder interface { + WriteResponse(http.ResponseWriter, runtime.Producer) +} + +// ResponderFunc wraps a func as a Responder interface +type ResponderFunc func(http.ResponseWriter, runtime.Producer) + +// WriteResponse writes to the response +func (fn ResponderFunc) WriteResponse(rw http.ResponseWriter, pr runtime.Producer) { + fn(rw, pr) +} + +// Context is a type safe wrapper around an untyped request context +// used throughout to store request context with the standard context attached +// to the http.Request +type Context struct { + spec *loads.Document + analyzer *analysis.Spec + api RoutableAPI + router Router +} + +type routableUntypedAPI struct { + api *untyped.API + hlock *sync.Mutex + handlers map[string]map[string]http.Handler + defaultConsumes string + defaultProduces string +} + +func newRoutableUntypedAPI(spec *loads.Document, api *untyped.API, context *Context) *routableUntypedAPI { + var handlers map[string]map[string]http.Handler + if spec == nil || api == nil { + return nil + } + analyzer := analysis.New(spec.Spec()) + for method, hls := range analyzer.Operations() { + um := strings.ToUpper(method) + for path, op := range hls { + schemes := analyzer.SecurityDefinitionsFor(op) + + if oh, ok := api.OperationHandlerFor(method, path); ok { + if handlers == nil { + handlers = make(map[string]map[string]http.Handler) + } + if b, ok := handlers[um]; !ok || b == nil { + handlers[um] = make(map[string]http.Handler) + } + + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // lookup route info in the context + route, rCtx, _ := context.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + + // bind and validate the request using reflection + var bound interface{} + var validation error + bound, r, validation = context.BindAndValidate(r, route) + if validation != nil { + context.Respond(w, r, route.Produces, route, validation) + return + } + + // actually handle the request + result, err := oh.Handle(bound) + if err != nil { + // respond with failure + context.Respond(w, r, route.Produces, route, err) + return + } + + // respond with success + context.Respond(w, r, route.Produces, route, result) + }) + + if len(schemes) > 0 { + handler = newSecureAPI(context, handler) + } + handlers[um][path] = handler + } + } + } + + return &routableUntypedAPI{ + api: api, + hlock: new(sync.Mutex), + handlers: handlers, + defaultProduces: api.DefaultProduces, + defaultConsumes: api.DefaultConsumes, + } +} + +func (r *routableUntypedAPI) HandlerFor(method, path string) (http.Handler, bool) { + r.hlock.Lock() + paths, ok := r.handlers[strings.ToUpper(method)] + if !ok { + r.hlock.Unlock() + return nil, false + } + handler, ok := paths[path] + r.hlock.Unlock() + return handler, ok +} +func (r *routableUntypedAPI) ServeErrorFor(operationID string) func(http.ResponseWriter, *http.Request, error) { + return r.api.ServeError +} +func (r *routableUntypedAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer { + return r.api.ConsumersFor(mediaTypes) +} +func (r *routableUntypedAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer { + return r.api.ProducersFor(mediaTypes) +} +func (r *routableUntypedAPI) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator { + return r.api.AuthenticatorsFor(schemes) +} +func (r *routableUntypedAPI) Authorizer() runtime.Authorizer { + return r.api.Authorizer() +} +func (r *routableUntypedAPI) Formats() strfmt.Registry { + return r.api.Formats() +} + +func (r *routableUntypedAPI) DefaultProduces() string { + return r.defaultProduces +} + +func (r *routableUntypedAPI) DefaultConsumes() string { + return r.defaultConsumes +} + +// NewRoutableContext creates a new context for a routable API +func NewRoutableContext(spec *loads.Document, routableAPI RoutableAPI, routes Router) *Context { + var an *analysis.Spec + if spec != nil { + an = analysis.New(spec.Spec()) + } + ctx := &Context{spec: spec, api: routableAPI, analyzer: an} + return ctx +} + +// NewContext creates a new context wrapper +func NewContext(spec *loads.Document, api *untyped.API, routes Router) *Context { + var an *analysis.Spec + if spec != nil { + an = analysis.New(spec.Spec()) + } + ctx := &Context{spec: spec, analyzer: an} + ctx.api = newRoutableUntypedAPI(spec, api, ctx) + return ctx +} + +// Serve serves the specified spec with the specified api registrations as a http.Handler +func Serve(spec *loads.Document, api *untyped.API) http.Handler { + return ServeWithBuilder(spec, api, PassthroughBuilder) +} + +// ServeWithBuilder serves the specified spec with the specified api registrations as a http.Handler that is decorated +// by the Builder +func ServeWithBuilder(spec *loads.Document, api *untyped.API, builder Builder) http.Handler { + context := NewContext(spec, api, nil) + return context.APIHandler(builder) +} + +type contextKey int8 + +const ( + _ contextKey = iota + ctxContentType + ctxResponseFormat + ctxMatchedRoute + ctxBoundParams + ctxSecurityPrincipal + ctxSecurityScopes +) + +type contentTypeValue struct { + MediaType string + Charset string +} + +// BasePath returns the base path for this API +func (c *Context) BasePath() string { + return c.spec.BasePath() +} + +// RequiredProduces returns the accepted content types for responses +func (c *Context) RequiredProduces() []string { + return c.analyzer.RequiredProduces() +} + +// BindValidRequest binds a params object to a request but only when the request is valid +// if the request is not valid an error will be returned +func (c *Context) BindValidRequest(request *http.Request, route *MatchedRoute, binder RequestBinder) error { + var res []error + + requestContentType := "*/*" + // check and validate content type, select consumer + if runtime.HasBody(request) { + ct, _, err := runtime.ContentType(request.Header) + if err != nil { + res = append(res, err) + } else { + if err := validateContentType(route.Consumes, ct); err != nil { + res = append(res, err) + } + if len(res) == 0 { + cons, ok := route.Consumers[ct] + if !ok { + res = append(res, errors.New(500, "no consumer registered for %s", ct)) + } else { + route.Consumer = cons + requestContentType = ct + } + } + } + } + + // check and validate the response format + if len(res) == 0 && runtime.HasBody(request) { + if str := NegotiateContentType(request, route.Produces, requestContentType); str == "" { + res = append(res, errors.InvalidResponseFormat(request.Header.Get(runtime.HeaderAccept), route.Produces)) + } + } + + // now bind the request with the provided binder + // it's assumed the binder will also validate the request and return an error if the + // request is invalid + if binder != nil && len(res) == 0 { + if err := binder.BindRequest(request, route); err != nil { + return err + } + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// ContentType gets the parsed value of a content type +// Returns the media type, its charset and a shallow copy of the request +// when its context doesn't contain the content type value, otherwise it returns +// the same request +// Returns the error that runtime.ContentType may retunrs. +func (c *Context) ContentType(request *http.Request) (string, string, *http.Request, error) { + var rCtx = request.Context() + + if v, ok := rCtx.Value(ctxContentType).(*contentTypeValue); ok { + return v.MediaType, v.Charset, request, nil + } + + mt, cs, err := runtime.ContentType(request.Header) + if err != nil { + return "", "", nil, err + } + rCtx = stdContext.WithValue(rCtx, ctxContentType, &contentTypeValue{mt, cs}) + return mt, cs, request.WithContext(rCtx), nil +} + +// LookupRoute looks a route up and returns true when it is found +func (c *Context) LookupRoute(request *http.Request) (*MatchedRoute, bool) { + if route, ok := c.router.Lookup(request.Method, request.URL.EscapedPath()); ok { + return route, ok + } + return nil, false +} + +// RouteInfo tries to match a route for this request +// Returns the matched route, a shallow copy of the request if its context +// contains the matched router, otherwise the same request, and a bool to +// indicate if it the request matches one of the routes, if it doesn't +// then it returns false and nil for the other two return values +func (c *Context) RouteInfo(request *http.Request) (*MatchedRoute, *http.Request, bool) { + var rCtx = request.Context() + + if v, ok := rCtx.Value(ctxMatchedRoute).(*MatchedRoute); ok { + return v, request, ok + } + + if route, ok := c.LookupRoute(request); ok { + rCtx = stdContext.WithValue(rCtx, ctxMatchedRoute, route) + return route, request.WithContext(rCtx), ok + } + + return nil, nil, false +} + +// ResponseFormat negotiates the response content type +// Returns the response format and a shallow copy of the request if its context +// doesn't contain the response format, otherwise the same request +func (c *Context) ResponseFormat(r *http.Request, offers []string) (string, *http.Request) { + var rCtx = r.Context() + + if v, ok := rCtx.Value(ctxResponseFormat).(string); ok { + debugLog("[%s %s] found response format %q in context", r.Method, r.URL.Path, v) + return v, r + } + + format := NegotiateContentType(r, offers, "") + if format != "" { + debugLog("[%s %s] set response format %q in context", r.Method, r.URL.Path, format) + r = r.WithContext(stdContext.WithValue(rCtx, ctxResponseFormat, format)) + } + debugLog("[%s %s] negotiated response format %q", r.Method, r.URL.Path, format) + return format, r +} + +// AllowedMethods gets the allowed methods for the path of this request +func (c *Context) AllowedMethods(request *http.Request) []string { + return c.router.OtherMethods(request.Method, request.URL.EscapedPath()) +} + +// Authorize authorizes the request +// Returns the principal object and a shallow copy of the request when its +// context doesn't contain the principal, otherwise the same request or an error +// (the last) if one of the authenticators returns one or an Unauthenticated error +func (c *Context) Authorize(request *http.Request, route *MatchedRoute) (interface{}, *http.Request, error) { + if route == nil || len(route.Authenticators) == 0 { + return nil, nil, nil + } + + var rCtx = request.Context() + if v := rCtx.Value(ctxSecurityPrincipal); v != nil { + return v, request, nil + } + + var lastError error + for scheme, authenticator := range route.Authenticators { + applies, usr, err := authenticator.Authenticate(&security.ScopedAuthRequest{ + Request: request, + RequiredScopes: route.Scopes[scheme], + }) + if !applies || err != nil || usr == nil { + if err != nil { + lastError = err + } + continue + } + if route.Authorizer != nil { + if err := route.Authorizer.Authorize(request, usr); err != nil { + return nil, nil, errors.New(http.StatusForbidden, err.Error()) + } + } + rCtx = stdContext.WithValue(rCtx, ctxSecurityPrincipal, usr) + rCtx = stdContext.WithValue(rCtx, ctxSecurityScopes, route.Scopes[scheme]) + return usr, request.WithContext(rCtx), nil + } + + if lastError != nil { + return nil, nil, lastError + } + + return nil, nil, errors.Unauthenticated("invalid credentials") +} + +// BindAndValidate binds and validates the request +// Returns the validation map and a shallow copy of the request when its context +// doesn't contain the validation, otherwise it returns the same request or an +// CompositeValidationError error +func (c *Context) BindAndValidate(request *http.Request, matched *MatchedRoute) (interface{}, *http.Request, error) { + var rCtx = request.Context() + + if v, ok := rCtx.Value(ctxBoundParams).(*validation); ok { + debugLog("got cached validation (valid: %t)", len(v.result) == 0) + if len(v.result) > 0 { + return v.bound, request, errors.CompositeValidationError(v.result...) + } + return v.bound, request, nil + } + result := validateRequest(c, request, matched) + rCtx = stdContext.WithValue(rCtx, ctxBoundParams, result) + request = request.WithContext(rCtx) + if len(result.result) > 0 { + return result.bound, request, errors.CompositeValidationError(result.result...) + } + debugLog("no validation errors found") + return result.bound, request, nil +} + +// NotFound the default not found responder for when no route has been matched yet +func (c *Context) NotFound(rw http.ResponseWriter, r *http.Request) { + c.Respond(rw, r, []string{c.api.DefaultProduces()}, nil, errors.NotFound("not found")) +} + +// Respond renders the response after doing some content negotiation +func (c *Context) Respond(rw http.ResponseWriter, r *http.Request, produces []string, route *MatchedRoute, data interface{}) { + debugLog("responding to %s %s with produces: %v", r.Method, r.URL.Path, produces) + offers := []string{} + for _, mt := range produces { + if mt != c.api.DefaultProduces() { + offers = append(offers, mt) + } + } + // the default producer is last so more specific producers take precedence + offers = append(offers, c.api.DefaultProduces()) + debugLog("offers: %v", offers) + + var format string + format, r = c.ResponseFormat(r, offers) + rw.Header().Set(runtime.HeaderContentType, format) + + if resp, ok := data.(Responder); ok { + producers := route.Producers + prod, ok := producers[format] + if !ok { + 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)) + } + prod = pr + } + resp.WriteResponse(rw, prod) + return + } + + if err, ok := data.(error); ok { + if format == "" { + rw.Header().Set(runtime.HeaderContentType, runtime.JSONMime) + } + if route == nil || route.Operation == nil { + c.api.ServeErrorFor("")(rw, r, err) + return + } + c.api.ServeErrorFor(route.Operation.ID)(rw, r, err) + return + } + + if route == nil || route.Operation == nil { + rw.WriteHeader(200) + if r.Method == "HEAD" { + return + } + producers := c.api.ProducersFor(normalizeOffers(offers)) + prod, ok := producers[format] + if !ok { + panic(errors.New(http.StatusInternalServerError, "can't find a producer for "+format)) + } + if err := prod.Produce(rw, data); err != nil { + panic(err) // let the recovery middleware deal with this + } + return + } + + if _, code, ok := route.Operation.SuccessResponse(); ok { + rw.WriteHeader(code) + if code == 204 || r.Method == "HEAD" { + return + } + + producers := route.Producers + prod, ok := producers[format] + if !ok { + if !ok { + 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)) + } + prod = pr + } + } + if err := prod.Produce(rw, data); err != nil { + panic(err) // let the recovery middleware deal with this + } + return + } + + c.api.ServeErrorFor(route.Operation.ID)(rw, r, errors.New(http.StatusInternalServerError, "can't produce response")) +} + +// APIHandler returns a handler to serve the API, this includes a swagger spec, router and the contract defined in the swagger spec +func (c *Context) APIHandler(builder Builder) http.Handler { + b := builder + if b == nil { + b = PassthroughBuilder + } + + var title string + sp := c.spec.Spec() + if sp != nil && sp.Info != nil && sp.Info.Title != "" { + title = sp.Info.Title + } + + redocOpts := RedocOpts{ + BasePath: c.BasePath(), + Title: title, + } + + return Spec("", c.spec.Raw(), Redoc(redocOpts, c.RoutesHandler(b))) +} + +// RoutesHandler returns a handler to serve the API, just the routes and the contract defined in the swagger spec +func (c *Context) RoutesHandler(builder Builder) http.Handler { + b := builder + if b == nil { + b = PassthroughBuilder + } + return NewRouter(c, b(NewOperationExecutor(c))) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/context_test.go b/vendor/github.com/go-openapi/runtime/middleware/context_test.go new file mode 100644 index 0000000000..e236ece893 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/context_test.go @@ -0,0 +1,434 @@ +// 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 middleware + +import ( + "errors" + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-openapi/loads" + "github.com/go-openapi/loads/fmts" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/internal/testing/petstore" + "github.com/go-openapi/runtime/middleware/untyped" + "github.com/stretchr/testify/assert" +) + +type stubOperationHandler struct { +} + +func (s *stubOperationHandler) ParameterModel() interface{} { + return nil +} + +func (s *stubOperationHandler) Handle(params interface{}) (interface{}, error) { + return nil, nil +} + +func init() { + loads.AddLoader(fmts.YAMLMatcher, fmts.YAMLDoc) +} + +func TestContentType_Issue264(t *testing.T) { + swspec, err := loads.Spec("../fixtures/bugs/264/swagger.yml") + if assert.NoError(t, err) { + api := untyped.NewAPI(swspec) + api.RegisterConsumer("application/json", runtime.JSONConsumer()) + api.RegisterProducer("application/json", runtime.JSONProducer()) + api.RegisterOperation("delete", "/key/{id}", new(stubOperationHandler)) + + handler := Serve(swspec, api) + request, _ := http.NewRequest("DELETE", "/key/1", nil) + recorder := httptest.NewRecorder() + handler.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + } +} + +func TestServe(t *testing.T) { + spec, api := petstore.NewAPI(t) + handler := Serve(spec, api) + + // serve spec document + request, _ := http.NewRequest("GET", "http://localhost:8080/swagger.json", nil) + request.Header.Add("Content-Type", runtime.JSONMime) + request.Header.Add("Accept", runtime.JSONMime) + recorder := httptest.NewRecorder() + + handler.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + + request, _ = http.NewRequest("GET", "http://localhost:8080/swagger-ui", nil) + recorder = httptest.NewRecorder() + + handler.ServeHTTP(recorder, request) + assert.Equal(t, 404, recorder.Code) +} + +func TestContextAuthorize(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := runtime.JSONRequest("GET", "/api/pets", nil) + + ri, reqWithCtx, ok := ctx.RouteInfo(request) + assert.True(t, ok) + assert.NotNil(t, reqWithCtx) + + request = reqWithCtx + + p, reqWithCtx, err := ctx.Authorize(request, ri) + assert.Error(t, err) + assert.Nil(t, p) + assert.Nil(t, reqWithCtx) + + v := request.Context().Value(ctxSecurityPrincipal) + assert.Nil(t, v) + + request.SetBasicAuth("wrong", "wrong") + p, reqWithCtx, err = ctx.Authorize(request, ri) + assert.Error(t, err) + assert.Nil(t, p) + assert.Nil(t, reqWithCtx) + + v = request.Context().Value(ctxSecurityPrincipal) + assert.Nil(t, v) + + request.SetBasicAuth("admin", "admin") + p, reqWithCtx, err = ctx.Authorize(request, ri) + assert.NoError(t, err) + assert.Equal(t, "admin", p) + assert.NotNil(t, reqWithCtx) + + // Assign the new returned request to follow with the test + request = reqWithCtx + + v, ok = request.Context().Value(ctxSecurityPrincipal).(string) + assert.True(t, ok) + assert.Equal(t, "admin", v) + + // Once the request context contains the principal the authentication + // isn't rechecked + request.SetBasicAuth("doesn't matter", "doesn't") + pp, reqCtx, rr := ctx.Authorize(request, ri) + assert.Equal(t, p, pp) + assert.Equal(t, err, rr) + assert.Equal(t, request, reqCtx) +} + +func TestContextAuthorize_WithAuthorizer(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := runtime.JSONRequest("POST", "/api/pets", nil) + + ri, reqWithCtx, ok := ctx.RouteInfo(request) + assert.True(t, ok) + assert.NotNil(t, reqWithCtx) + + request = reqWithCtx + + request.SetBasicAuth("topuser", "topuser") + p, reqWithCtx, err := ctx.Authorize(request, ri) + assert.Error(t, err) + assert.Nil(t, p) + assert.Nil(t, reqWithCtx) + + request.SetBasicAuth("admin", "admin") + p, reqWithCtx, err = ctx.Authorize(request, ri) + assert.NoError(t, err) + assert.Equal(t, "admin", p) + assert.NotNil(t, reqWithCtx) +} + +func TestContextNegotiateContentType(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := http.NewRequest("POST", "/api/pets", nil) + // request.Header.Add("Accept", "*/*") + request.Header.Add("content-type", "text/html") + + v := request.Context().Value(ctxBoundParams) + assert.Nil(t, v) + + ri, request, _ := ctx.RouteInfo(request) + + res := NegotiateContentType(request, ri.Produces, "text/plain") + assert.Equal(t, ri.Produces[0], res) +} + +func TestContextBindAndValidate(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := http.NewRequest("POST", "/api/pets", nil) + request.Header.Add("Accept", "*/*") + request.Header.Add("content-type", "text/html") + request.ContentLength = 1 + + v := request.Context().Value(ctxBoundParams) + assert.Nil(t, v) + + ri, request, _ := ctx.RouteInfo(request) + data, request, result := ctx.BindAndValidate(request, ri) // this requires a much more thorough test + assert.NotNil(t, data) + assert.NotNil(t, result) + + v, ok := request.Context().Value(ctxBoundParams).(*validation) + assert.True(t, ok) + assert.NotNil(t, v) + + dd, rCtx, rr := ctx.BindAndValidate(request, ri) + assert.Equal(t, data, dd) + assert.Equal(t, result, rr) + assert.Equal(t, rCtx, request) +} + +func TestContextRender(t *testing.T) { + ct := runtime.JSONMime + spec, api := petstore.NewAPI(t) + + assert.NotNil(t, spec) + assert.NotNil(t, api) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := http.NewRequest("GET", "/api/pets", nil) + request.Header.Set(runtime.HeaderAccept, ct) + ri, request, _ := ctx.RouteInfo(request) + + recorder := httptest.NewRecorder() + ctx.Respond(recorder, request, []string{ct}, ri, map[string]interface{}{"name": "hello"}) + assert.Equal(t, 200, recorder.Code) + assert.Equal(t, "{\"name\":\"hello\"}\n", recorder.Body.String()) + + recorder = httptest.NewRecorder() + ctx.Respond(recorder, request, []string{ct}, ri, errors.New("this went wrong")) + assert.Equal(t, 500, recorder.Code) + + // recorder = httptest.NewRecorder() + // assert.Panics(t, func() { ctx.Respond(recorder, request, []string{ct}, ri, map[int]interface{}{1: "hello"}) }) + + // Panic when route is nil and there is not a producer for the requested response format + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "/api/pets", nil) + request.Header.Set(runtime.HeaderAccept, "text/xml") + assert.Panics(t, func() { ctx.Respond(recorder, request, []string{}, nil, map[string]interface{}{"name": "hello"}) }) + + request, _ = http.NewRequest("GET", "/api/pets", nil) + request.Header.Set(runtime.HeaderAccept, ct) + ri, request, _ = ctx.RouteInfo(request) + + recorder = httptest.NewRecorder() + ctx.Respond(recorder, request, []string{ct}, ri, map[string]interface{}{"name": "hello"}) + assert.Equal(t, 200, recorder.Code) + assert.Equal(t, "{\"name\":\"hello\"}\n", recorder.Body.String()) + + recorder = httptest.NewRecorder() + ctx.Respond(recorder, request, []string{ct}, ri, errors.New("this went wrong")) + assert.Equal(t, 500, recorder.Code) + + // recorder = httptest.NewRecorder() + // assert.Panics(t, func() { ctx.Respond(recorder, request, []string{ct}, ri, map[int]interface{}{1: "hello"}) }) + + // recorder = httptest.NewRecorder() + // request, _ = http.NewRequest("GET", "/pets", nil) + // assert.Panics(t, func() { ctx.Respond(recorder, request, []string{}, ri, map[string]interface{}{"name": "hello"}) }) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("DELETE", "/api/pets/1", nil) + ri, request, _ = ctx.RouteInfo(request) + ctx.Respond(recorder, request, ri.Produces, ri, nil) + assert.Equal(t, 204, recorder.Code) + +} + +func TestContextValidResponseFormat(t *testing.T) { + ct := "application/json" + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := http.NewRequest("GET", "http://localhost:8080", nil) + request.Header.Set(runtime.HeaderAccept, ct) + + // check there's nothing there + cached, ok := request.Context().Value(ctxResponseFormat).(string) + assert.False(t, ok) + assert.Empty(t, cached) + + // trigger the parse + mt, request := ctx.ResponseFormat(request, []string{ct}) + assert.Equal(t, ct, mt) + + // check it was cached + cached, ok = request.Context().Value(ctxResponseFormat).(string) + assert.True(t, ok) + assert.Equal(t, ct, cached) + + // check if the cast works and fetch from cache too + mt, _ = ctx.ResponseFormat(request, []string{ct}) + assert.Equal(t, ct, mt) +} + +func TestContextInvalidResponseFormat(t *testing.T) { + ct := "application/x-yaml" + other := "application/sgml" + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := http.NewRequest("GET", "http://localhost:8080", nil) + request.Header.Set(runtime.HeaderAccept, ct) + + // check there's nothing there + cached, ok := request.Context().Value(ctxResponseFormat).(string) + assert.False(t, ok) + assert.Empty(t, cached) + + // trigger the parse + mt, request := ctx.ResponseFormat(request, []string{other}) + assert.Empty(t, mt) + + // check it was cached + cached, ok = request.Context().Value(ctxResponseFormat).(string) + assert.False(t, ok) + assert.Empty(t, cached) + + // check if the cast works and fetch from cache too + mt, rCtx := ctx.ResponseFormat(request, []string{other}) + assert.Empty(t, mt) + assert.Equal(t, request, rCtx) +} + +func TestContextValidRoute(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := http.NewRequest("GET", "/api/pets", nil) + + // check there's nothing there + cached := request.Context().Value(ctxMatchedRoute) + assert.Nil(t, cached) + + matched, rCtx, ok := ctx.RouteInfo(request) + assert.True(t, ok) + assert.NotNil(t, matched) + assert.NotNil(t, rCtx) + assert.NotEqual(t, request, rCtx) + + request = rCtx + + // check it was cached + _, ok = request.Context().Value(ctxMatchedRoute).(*MatchedRoute) + assert.True(t, ok) + + matched, rCtx, ok = ctx.RouteInfo(request) + assert.True(t, ok) + assert.NotNil(t, matched) + assert.Equal(t, request, rCtx) +} + +func TestContextInvalidRoute(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + ctx.router = DefaultRouter(spec, ctx.api) + + request, _ := http.NewRequest("DELETE", "pets", nil) + + // check there's nothing there + cached := request.Context().Value(ctxMatchedRoute) + assert.Nil(t, cached) + + matched, rCtx, ok := ctx.RouteInfo(request) + assert.False(t, ok) + assert.Nil(t, matched) + assert.Nil(t, rCtx) + + // check it was not cached + cached = request.Context().Value(ctxMatchedRoute) + assert.Nil(t, cached) + + matched, rCtx, ok = ctx.RouteInfo(request) + assert.False(t, ok) + assert.Nil(t, matched) + assert.Nil(t, rCtx) +} + +func TestContextValidContentType(t *testing.T) { + ct := "application/json" + ctx := NewContext(nil, nil, nil) + + request, _ := http.NewRequest("GET", "http://localhost:8080", nil) + request.Header.Set(runtime.HeaderContentType, ct) + + // check there's nothing there + cached := request.Context().Value(ctxContentType) + assert.Nil(t, cached) + + // trigger the parse + mt, _, rCtx, err := ctx.ContentType(request) + assert.NoError(t, err) + assert.Equal(t, ct, mt) + assert.NotNil(t, rCtx) + assert.NotEqual(t, request, rCtx) + + request = rCtx + + // check it was cached + cached = request.Context().Value(ctxContentType) + assert.NotNil(t, cached) + + // check if the cast works and fetch from cache too + mt, _, rCtx, err = ctx.ContentType(request) + assert.NoError(t, err) + assert.Equal(t, ct, mt) + assert.Equal(t, request, rCtx) +} + +func TestContextInvalidContentType(t *testing.T) { + ct := "application(" + ctx := NewContext(nil, nil, nil) + + request, _ := http.NewRequest("GET", "http://localhost:8080", nil) + request.Header.Set(runtime.HeaderContentType, ct) + + // check there's nothing there + cached := request.Context().Value(ctxContentType) + assert.Nil(t, cached) + + // trigger the parse + mt, _, rCtx, err := ctx.ContentType(request) + assert.Error(t, err) + assert.Empty(t, mt) + assert.Nil(t, rCtx) + + // check it was not cached + cached = request.Context().Value(ctxContentType) + assert.Nil(t, cached) + + // check if the failure continues + _, _, rCtx, err = ctx.ContentType(request) + assert.Error(t, err) + assert.Nil(t, rCtx) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE b/vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE new file mode 100755 index 0000000000..e65039ad84 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Naoya Inada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/README.md b/vendor/github.com/go-openapi/runtime/middleware/denco/README.md new file mode 100755 index 0000000000..30109e17d5 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/README.md @@ -0,0 +1,180 @@ +# Denco [![Build Status](https://travis-ci.org/naoina/denco.png?branch=master)](https://travis-ci.org/naoina/denco) + +The fast and flexible HTTP request router for [Go](http://golang.org). + +Denco is based on Double-Array implementation of [Kocha-urlrouter](https://github.com/naoina/kocha-urlrouter). +However, Denco is optimized and some features added. + +## Features + +* Fast (See [go-http-routing-benchmark](https://github.com/naoina/go-http-routing-benchmark)) +* [URL patterns](#url-patterns) (`/foo/:bar` and `/foo/*wildcard`) +* Small (but enough) URL router API +* HTTP request multiplexer like `http.ServeMux` + +## Installation + + go get -u github.com/go-openapi/runtime/middleware/denco + +## Using as HTTP request multiplexer + +```go +package main + +import ( + "fmt" + "log" + "net/http" + + "github.com/go-openapi/runtime/middleware/denco" +) + +func Index(w http.ResponseWriter, r *http.Request, params denco.Params) { + fmt.Fprintf(w, "Welcome to Denco!\n") +} + +func User(w http.ResponseWriter, r *http.Request, params denco.Params) { + fmt.Fprintf(w, "Hello %s!\n", params.Get("name")) +} + +func main() { + mux := denco.NewMux() + handler, err := mux.Build([]denco.Handler{ + mux.GET("/", Index), + mux.GET("/user/:name", User), + mux.POST("/user/:name", User), + }) + if err != nil { + panic(err) + } + log.Fatal(http.ListenAndServe(":8080", handler)) +} +``` + +## Using as URL router + +```go +package main + +import ( + "fmt" + + "github.com/go-openapi/runtime/middleware/denco" +) + +type route struct { + name string +} + +func main() { + router := denco.New() + router.Build([]denco.Record{ + {"/", &route{"root"}}, + {"/user/:id", &route{"user"}}, + {"/user/:name/:id", &route{"username"}}, + {"/static/*filepath", &route{"static"}}, + }) + + data, params, found := router.Lookup("/") + // print `&main.route{name:"root"}, denco.Params(nil), true`. + fmt.Printf("%#v, %#v, %#v\n", data, params, found) + + data, params, found = router.Lookup("/user/hoge") + // print `&main.route{name:"user"}, denco.Params{denco.Param{Name:"id", Value:"hoge"}}, true`. + fmt.Printf("%#v, %#v, %#v\n", data, params, found) + + data, params, found = router.Lookup("/user/hoge/7") + // print `&main.route{name:"username"}, denco.Params{denco.Param{Name:"name", Value:"hoge"}, denco.Param{Name:"id", Value:"7"}}, true`. + fmt.Printf("%#v, %#v, %#v\n", data, params, found) + + data, params, found = router.Lookup("/static/path/to/file") + // print `&main.route{name:"static"}, denco.Params{denco.Param{Name:"filepath", Value:"path/to/file"}}, true`. + fmt.Printf("%#v, %#v, %#v\n", data, params, found) +} +``` + +See [Godoc](http://godoc.org/github.com/go-openapi/runtime/middleware/denco) for more details. + +## Getting the value of path parameter + +You can get the value of path parameter by 2 ways. + +1. Using [`denco.Params.Get`](http://godoc.org/github.com/go-openapi/runtime/middleware/denco#Params.Get) method +2. Find by loop + +```go +package main + +import ( + "fmt" + + "github.com/go-openapi/runtime/middleware/denco" +) + +func main() { + router := denco.New() + if err := router.Build([]denco.Record{ + {"/user/:name/:id", "route1"}, + }); err != nil { + panic(err) + } + + // 1. Using denco.Params.Get method. + _, params, _ := router.Lookup("/user/alice/1") + name := params.Get("name") + if name != "" { + fmt.Printf("Hello %s.\n", name) // prints "Hello alice.". + } + + // 2. Find by loop. + for _, param := range params { + if param.Name == "name" { + fmt.Printf("Hello %s.\n", name) // prints "Hello alice.". + } + } +} +``` + +## URL patterns + +Denco's route matching strategy is "most nearly matching". + +When routes `/:name` and `/alice` have been built, URI `/alice` matches the route `/alice`, not `/:name`. +Because URI `/alice` is more match with the route `/alice` than `/:name`. + +For more example, when routes below have been built: + +``` +/user/alice +/user/:name +/user/:name/:id +/user/alice/:id +/user/:id/bob +``` + +Routes matching are: + +``` +/user/alice => "/user/alice" (no match with "/user/:name") +/user/bob => "/user/:name" +/user/naoina/1 => "/user/:name/1" +/user/alice/1 => "/user/alice/:id" (no match with "/user/:name/:id") +/user/1/bob => "/user/:id/bob" (no match with "/user/:name/:id") +/user/alice/bob => "/user/alice/:id" (no match with "/user/:name/:id" and "/user/:id/bob") +``` + +## Limitation + +Denco has some limitations below. + +* Number of param records (such as `/:name`) must be less than 2^22 +* Number of elements of internal slice must be less than 2^22 + +## Benchmarks + + cd $GOPATH/github.com/go-openapi/runtime/middleware/denco + go test -bench . -benchmem + +## License + +Denco is licensed under the MIT License. diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/router.go b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go new file mode 100755 index 0000000000..73703fddec --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/router.go @@ -0,0 +1,452 @@ +// Package denco provides fast URL router. +package denco + +import ( + "fmt" + "sort" + "strings" +) + +const ( + // ParamCharacter is a special character for path parameter. + ParamCharacter = ':' + + // WildcardCharacter is a special character for wildcard path parameter. + WildcardCharacter = '*' + + // TerminationCharacter is a special character for end of path. + TerminationCharacter = '#' + + // MaxSize is max size of records and internal slice. + MaxSize = (1 << 22) - 1 +) + +// Router represents a URL router. +type Router struct { + // SizeHint expects the maximum number of path parameters in records to Build. + // SizeHint will be used to determine the capacity of the memory to allocate. + // By default, SizeHint will be determined from given records to Build. + SizeHint int + + static map[string]interface{} + param *doubleArray +} + +// New returns a new Router. +func New() *Router { + return &Router{ + SizeHint: -1, + static: make(map[string]interface{}), + param: newDoubleArray(), + } +} + +// Lookup returns data and path parameters that associated with path. +// 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 { + return data, nil, true + } + if len(rt.param.node) == 1 { + return nil, nil, false + } + nd, params, found := rt.param.lookup(path, make([]Param, 0, rt.SizeHint), 1) + if !found { + return nil, nil, false + } + for i := 0; i < len(params); i++ { + params[i].Name = nd.paramNames[i] + } + return nd.data, params, true +} + +// Build builds URL router from records. +func (rt *Router) Build(records []Record) error { + statics, params := makeRecords(records) + if len(params) > MaxSize { + return fmt.Errorf("denco: too many records") + } + if rt.SizeHint < 0 { + rt.SizeHint = 0 + for _, p := range params { + size := 0 + for _, k := range p.Key { + if k == ParamCharacter || k == WildcardCharacter { + size++ + } + } + if size > rt.SizeHint { + rt.SizeHint = size + } + } + } + for _, r := range statics { + rt.static[r.Key] = r.Value + } + if err := rt.param.build(params, 1, 0, make(map[int]struct{})); err != nil { + return err + } + return nil +} + +// Param represents name and value of path parameter. +type Param struct { + Name string + Value string +} + +// Params represents the name and value of path parameters. +type Params []Param + +// Get gets the first value associated with the given name. +// If there are no values associated with the key, Get returns "". +func (ps Params) Get(name string) string { + for _, p := range ps { + if p.Name == name { + return p.Value + } + } + return "" +} + +type doubleArray struct { + bc []baseCheck + node []*node +} + +func newDoubleArray() *doubleArray { + return &doubleArray{ + bc: []baseCheck{0}, + node: []*node{nil}, // A start index is adjusting to 1 because 0 will be used as a mark of non-existent node. + } +} + +// baseCheck contains BASE, CHECK and Extra flags. +// From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK. +// +// BASE (22bit) | Extra flags (2bit) | CHECK (8bit) +// |----------------------|--|--------| +// 32 10 8 0 +type baseCheck uint32 + +func (bc baseCheck) Base() int { + return int(bc >> 10) +} + +func (bc *baseCheck) SetBase(base int) { + *bc |= baseCheck(base) << 10 +} + +func (bc baseCheck) Check() byte { + return byte(bc) +} + +func (bc *baseCheck) SetCheck(check byte) { + *bc |= baseCheck(check) +} + +func (bc baseCheck) IsEmpty() bool { + return bc&0xfffffcff == 0 +} + +func (bc baseCheck) IsSingleParam() bool { + return bc¶mTypeSingle == paramTypeSingle +} + +func (bc baseCheck) IsWildcardParam() bool { + return bc¶mTypeWildcard == paramTypeWildcard +} + +func (bc baseCheck) IsAnyParam() bool { + return bc¶mTypeAny != 0 +} + +func (bc *baseCheck) SetSingleParam() { + *bc |= (1 << 8) +} + +func (bc *baseCheck) SetWildcardParam() { + *bc |= (1 << 9) +} + +const ( + paramTypeSingle = 0x0100 + paramTypeWildcard = 0x0200 + paramTypeAny = 0x0300 +) + +func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Param, bool) { + indices := make([]uint64, 0, 1) + for i := 0; i < len(path); i++ { + if da.bc[idx].IsAnyParam() { + indices = append(indices, (uint64(i)<<32)|(uint64(idx)&0xffffffff)) + } + c := path[i] + if idx = nextIndex(da.bc[idx].Base(), c); idx >= len(da.bc) || da.bc[idx].Check() != c { + goto BACKTRACKING + } + } + if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter { + return da.node[da.bc[next].Base()], params, true + } +BACKTRACKING: + for j := len(indices) - 1; j >= 0; j-- { + i, idx := int(indices[j]>>32), int(indices[j]&0xffffffff) + if da.bc[idx].IsSingleParam() { + idx := nextIndex(da.bc[idx].Base(), ParamCharacter) + if idx >= len(da.bc) { + break + } + next := NextSeparator(path, i) + params := append(params, Param{Value: path[i:next]}) + if nd, params, found := da.lookup(path[next:], params, idx); found { + return nd, params, true + } + } + if da.bc[idx].IsWildcardParam() { + idx := nextIndex(da.bc[idx].Base(), WildcardCharacter) + params := append(params, Param{Value: path[i:]}) + return da.node[da.bc[idx].Base()], params, true + } + } + return nil, nil, false +} + +// build builds double-array from records. +func (da *doubleArray) build(srcs []*record, idx, depth int, usedBase map[int]struct{}) error { + sort.Stable(recordSlice(srcs)) + base, siblings, leaf, err := da.arrange(srcs, idx, depth, usedBase) + if err != nil { + return err + } + if leaf != nil { + nd, err := makeNode(leaf) + if err != nil { + return err + } + da.bc[idx].SetBase(len(da.node)) + da.node = append(da.node, nd) + } + for _, sib := range siblings { + da.setCheck(nextIndex(base, sib.c), sib.c) + } + for _, sib := range siblings { + records := srcs[sib.start:sib.end] + switch sib.c { + case ParamCharacter: + for _, r := range records { + next := NextSeparator(r.Key, depth+1) + name := r.Key[depth+1 : next] + r.paramNames = append(r.paramNames, name) + r.Key = r.Key[next:] + } + da.bc[idx].SetSingleParam() + if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil { + return err + } + case WildcardCharacter: + r := records[0] + name := r.Key[depth+1 : len(r.Key)-1] + r.paramNames = append(r.paramNames, name) + r.Key = "" + da.bc[idx].SetWildcardParam() + if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil { + return err + } + default: + if err := da.build(records, nextIndex(base, sib.c), depth+1, usedBase); err != nil { + return err + } + } + } + return nil +} + +// setBase sets BASE. +func (da *doubleArray) setBase(i, base int) { + da.bc[i].SetBase(base) +} + +// setCheck sets CHECK. +func (da *doubleArray) setCheck(i int, check byte) { + da.bc[i].SetCheck(check) +} + +// findEmptyIndex returns an index of unused BASE/CHECK node. +func (da *doubleArray) findEmptyIndex(start int) int { + i := start + for ; i < len(da.bc); i++ { + if da.bc[i].IsEmpty() { + break + } + } + return i +} + +// findBase returns good BASE. +func (da *doubleArray) findBase(siblings []sibling, start int, usedBase map[int]struct{}) (base int) { + for idx, firstChar := start+1, siblings[0].c; ; idx = da.findEmptyIndex(idx + 1) { + base = nextIndex(idx, firstChar) + if _, used := usedBase[base]; used { + continue + } + i := 0 + for ; i < len(siblings); i++ { + next := nextIndex(base, siblings[i].c) + if len(da.bc) <= next { + da.bc = append(da.bc, make([]baseCheck, next-len(da.bc)+1)...) + } + if !da.bc[next].IsEmpty() { + break + } + } + if i == len(siblings) { + break + } + } + usedBase[base] = struct{}{} + return base +} + +func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[int]struct{}) (base int, siblings []sibling, leaf *record, err error) { + siblings, leaf, err = makeSiblings(records, depth) + if err != nil { + return -1, nil, nil, err + } + if len(siblings) < 1 { + return -1, nil, leaf, nil + } + base = da.findBase(siblings, idx, usedBase) + if base > MaxSize { + return -1, nil, nil, fmt.Errorf("denco: too many elements of internal slice") + } + da.setBase(idx, base) + return base, siblings, leaf, err +} + +// node represents a node of Double-Array. +type node struct { + data interface{} + + // Names of path parameters. + paramNames []string +} + +// makeNode returns a new node from record. +func makeNode(r *record) (*node, error) { + dups := make(map[string]bool) + for _, name := range r.paramNames { + if dups[name] { + return nil, fmt.Errorf("denco: path parameter `%v' is duplicated in the key `%v'", name, r.Key) + } + dups[name] = true + } + return &node{data: r.Value, paramNames: r.paramNames}, nil +} + +// sibling represents an intermediate data of build for Double-Array. +type sibling struct { + // An index of start of duplicated characters. + start int + + // An index of end of duplicated characters. + end int + + // A character of sibling. + c byte +} + +// nextIndex returns a next index of array of BASE/CHECK. +func nextIndex(base int, c byte) int { + return base ^ int(c) +} + +// makeSiblings returns slice of sibling. +func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, err error) { + var ( + pc byte + n int + ) + for i, r := range records { + if len(r.Key) <= depth { + leaf = r + continue + } + c := r.Key[depth] + switch { + case pc < c: + sib = append(sib, sibling{start: i, c: c}) + case pc == c: + continue + default: + return nil, nil, fmt.Errorf("denco: BUG: routing table hasn't been sorted") + } + if n > 0 { + sib[n-1].end = i + } + pc = c + n++ + } + if n == 0 { + return nil, leaf, nil + } + sib[n-1].end = len(records) + return sib, leaf, nil +} + +// Record represents a record data for router construction. +type Record struct { + // Key for router construction. + Key string + + // Result value for Key. + Value interface{} +} + +// NewRecord returns a new Record. +func NewRecord(key string, value interface{}) Record { + return Record{ + Key: key, + Value: value, + } +} + +// record represents a record that use to build the Double-Array. +type record struct { + Record + paramNames []string +} + +// makeRecords returns the records that use to build Double-Arrays. +func makeRecords(srcs []Record) (statics, params []*record) { + spChars := string([]byte{ParamCharacter, WildcardCharacter}) + termChar := string(TerminationCharacter) + for _, r := range srcs { + if strings.ContainsAny(r.Key, spChars) { + r.Key += termChar + params = append(params, &record{Record: r}) + } else { + statics = append(statics, &record{Record: r}) + } + } + return statics, params +} + +// recordSlice represents a slice of Record for sort and implements the sort.Interface. +type recordSlice []*record + +// Len implements the sort.Interface.Len. +func (rs recordSlice) Len() int { + return len(rs) +} + +// Less implements the sort.Interface.Less. +func (rs recordSlice) Less(i, j int) bool { + return rs[i].Key < rs[j].Key +} + +// Swap implements the sort.Interface.Swap. +func (rs recordSlice) Swap(i, j int) { + rs[i], rs[j] = rs[j], rs[i] +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/router_bench_test.go b/vendor/github.com/go-openapi/runtime/middleware/denco/router_bench_test.go new file mode 100755 index 0000000000..312402cc2b --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/router_bench_test.go @@ -0,0 +1,178 @@ +package denco_test + +import ( + "bytes" + "crypto/rand" + "fmt" + "math/big" + "testing" + + "github.com/go-openapi/runtime/middleware/denco" +) + +func BenchmarkRouterLookupStatic100(b *testing.B) { + benchmarkRouterLookupStatic(b, 100) +} + +func BenchmarkRouterLookupStatic300(b *testing.B) { + benchmarkRouterLookupStatic(b, 300) +} + +func BenchmarkRouterLookupStatic700(b *testing.B) { + benchmarkRouterLookupStatic(b, 700) +} + +func BenchmarkRouterLookupSingleParam100(b *testing.B) { + records := makeTestSingleParamRecords(100) + benchmarkRouterLookupSingleParam(b, records) +} + +func BenchmarkRouterLookupSingleParam300(b *testing.B) { + records := makeTestSingleParamRecords(300) + benchmarkRouterLookupSingleParam(b, records) +} + +func BenchmarkRouterLookupSingleParam700(b *testing.B) { + records := makeTestSingleParamRecords(700) + benchmarkRouterLookupSingleParam(b, records) +} + +func BenchmarkRouterLookupSingle2Param100(b *testing.B) { + records := makeTestSingle2ParamRecords(100) + benchmarkRouterLookupSingleParam(b, records) +} + +func BenchmarkRouterLookupSingle2Param300(b *testing.B) { + records := makeTestSingle2ParamRecords(300) + benchmarkRouterLookupSingleParam(b, records) +} + +func BenchmarkRouterLookupSingle2Param700(b *testing.B) { + records := makeTestSingle2ParamRecords(700) + benchmarkRouterLookupSingleParam(b, records) +} + +func BenchmarkRouterBuildStatic100(b *testing.B) { + records := makeTestStaticRecords(100) + benchmarkRouterBuild(b, records) +} + +func BenchmarkRouterBuildStatic300(b *testing.B) { + records := makeTestStaticRecords(300) + benchmarkRouterBuild(b, records) +} + +func BenchmarkRouterBuildStatic700(b *testing.B) { + records := makeTestStaticRecords(700) + benchmarkRouterBuild(b, records) +} + +func BenchmarkRouterBuildSingleParam100(b *testing.B) { + records := makeTestSingleParamRecords(100) + benchmarkRouterBuild(b, records) +} + +func BenchmarkRouterBuildSingleParam300(b *testing.B) { + records := makeTestSingleParamRecords(300) + benchmarkRouterBuild(b, records) +} + +func BenchmarkRouterBuildSingleParam700(b *testing.B) { + records := makeTestSingleParamRecords(700) + benchmarkRouterBuild(b, records) +} + +func BenchmarkRouterBuildSingle2Param100(b *testing.B) { + records := makeTestSingle2ParamRecords(100) + benchmarkRouterBuild(b, records) +} + +func BenchmarkRouterBuildSingle2Param300(b *testing.B) { + records := makeTestSingle2ParamRecords(300) + benchmarkRouterBuild(b, records) +} + +func BenchmarkRouterBuildSingle2Param700(b *testing.B) { + records := makeTestSingle2ParamRecords(700) + benchmarkRouterBuild(b, records) +} + +func benchmarkRouterLookupStatic(b *testing.B, n int) { + b.StopTimer() + router := denco.New() + records := makeTestStaticRecords(n) + if err := router.Build(records); err != nil { + b.Fatal(err) + } + record := pickTestRecord(records) + b.StartTimer() + for i := 0; i < b.N; i++ { + if r, _, _ := router.Lookup(record.Key); r != record.Value { + b.Fail() + } + } +} + +func benchmarkRouterLookupSingleParam(b *testing.B, records []denco.Record) { + router := denco.New() + if err := router.Build(records); err != nil { + b.Fatal(err) + } + record := pickTestRecord(records) + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, _, found := router.Lookup(record.Key); !found { + b.Fail() + } + } +} + +func benchmarkRouterBuild(b *testing.B, records []denco.Record) { + for i := 0; i < b.N; i++ { + router := denco.New() + if err := router.Build(records); err != nil { + b.Fatal(err) + } + } +} + +func makeTestStaticRecords(n int) []denco.Record { + records := make([]denco.Record, n) + for i := 0; i < n; i++ { + records[i] = denco.NewRecord("/"+randomString(50), fmt.Sprintf("testroute%d", i)) + } + return records +} + +func makeTestSingleParamRecords(n int) []denco.Record { + records := make([]denco.Record, n) + for i := 0; i < len(records); i++ { + records[i] = denco.NewRecord(fmt.Sprintf("/user%d/:name", i), fmt.Sprintf("testroute%d", i)) + } + return records +} + +func makeTestSingle2ParamRecords(n int) []denco.Record { + records := make([]denco.Record, n) + for i := 0; i < len(records); i++ { + records[i] = denco.NewRecord(fmt.Sprintf("/user%d/:name/comment/:id", i), fmt.Sprintf("testroute%d", i)) + } + return records +} + +func pickTestRecord(records []denco.Record) denco.Record { + return records[len(records)/2] +} + +func randomString(n int) string { + const srcStrings = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/" + var buf bytes.Buffer + for i := 0; i < n; i++ { + num, err := rand.Int(rand.Reader, big.NewInt(int64(len(srcStrings)-1))) + if err != nil { + panic(err) + } + buf.WriteByte(srcStrings[num.Int64()]) + } + return buf.String() +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/router_test.go b/vendor/github.com/go-openapi/runtime/middleware/denco/router_test.go new file mode 100755 index 0000000000..c0bd1cb40d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/router_test.go @@ -0,0 +1,526 @@ +package denco_test + +import ( + "fmt" + "math/rand" + "reflect" + "testing" + "time" + + "github.com/go-openapi/runtime/middleware/denco" +) + +func routes() []denco.Record { + return []denco.Record{ + {"/", "testroute0"}, + {"/path/to/route", "testroute1"}, + {"/path/to/other", "testroute2"}, + {"/path/to/route/a", "testroute3"}, + {"/path/to/:param", "testroute4"}, + {"/gists/:param1/foo/:param2", "testroute12"}, + {"/gists/:param1/foo/bar", "testroute11"}, + {"/:param1/:param2/foo/:param3", "testroute13"}, + {"/path/to/wildcard/*routepath", "testroute5"}, + {"/path/to/:param1/:param2", "testroute6"}, + {"/path/to/:param1/sep/:param2", "testroute7"}, + {"/:year/:month/:day", "testroute8"}, + {"/user/:id", "testroute9"}, + {"/a/to/b/:param/*routepath", "testroute10"}, + } +} + +var realURIs = []denco.Record{ + {"/authorizations", "/authorizations"}, + {"/authorizations/:id", "/authorizations/:id"}, + {"/applications/:client_id/tokens/:access_token", "/applications/:client_id/tokens/:access_token"}, + {"/events", "/events"}, + {"/repos/:owner/:repo/events", "/repos/:owner/:repo/events"}, + {"/networks/:owner/:repo/events", "/networks/:owner/:repo/events"}, + {"/orgs/:org/events", "/orgs/:org/events"}, + {"/users/:user/received_events", "/users/:user/received_events"}, + {"/users/:user/received_events/public", "/users/:user/received_events/public"}, + {"/users/:user/events", "/users/:user/events"}, + {"/users/:user/events/public", "/users/:user/events/public"}, + {"/users/:user/events/orgs/:org", "/users/:user/events/orgs/:org"}, + {"/feeds", "/feeds"}, + {"/notifications", "/notifications"}, + {"/repos/:owner/:repo/notifications", "/repos/:owner/:repo/notifications"}, + {"/notifications/threads/:id", "/notifications/threads/:id"}, + {"/notifications/threads/:id/subscription", "/notifications/threads/:id/subscription"}, + {"/repos/:owner/:repo/stargazers", "/repos/:owner/:repo/stargazers"}, + {"/users/:user/starred", "/users/:user/starred"}, + {"/user/starred", "/user/starred"}, + {"/user/starred/:owner/:repo", "/user/starred/:owner/:repo"}, + {"/repos/:owner/:repo/subscribers", "/repos/:owner/:repo/subscribers"}, + {"/users/:user/subscriptions", "/users/:user/subscriptions"}, + {"/user/subscriptions", "/user/subscriptions"}, + {"/repos/:owner/:repo/subscription", "/repos/:owner/:repo/subscription"}, + {"/user/subscriptions/:owner/:repo", "/user/subscriptions/:owner/:repo"}, + {"/users/:user/gists", "/users/:user/gists"}, + {"/gists", "/gists"}, + {"/gists/:id", "/gists/:id"}, + {"/gists/:id/star", "/gists/:id/star"}, + {"/repos/:owner/:repo/git/blobs/:sha", "/repos/:owner/:repo/git/blobs/:sha"}, + {"/repos/:owner/:repo/git/commits/:sha", "/repos/:owner/:repo/git/commits/:sha"}, + {"/repos/:owner/:repo/git/refs", "/repos/:owner/:repo/git/refs"}, + {"/repos/:owner/:repo/git/tags/:sha", "/repos/:owner/:repo/git/tags/:sha"}, + {"/repos/:owner/:repo/git/trees/:sha", "/repos/:owner/:repo/git/trees/:sha"}, + {"/issues", "/issues"}, + {"/user/issues", "/user/issues"}, + {"/orgs/:org/issues", "/orgs/:org/issues"}, + {"/repos/:owner/:repo/issues", "/repos/:owner/:repo/issues"}, + {"/repos/:owner/:repo/issues/:number", "/repos/:owner/:repo/issues/:number"}, + {"/repos/:owner/:repo/assignees", "/repos/:owner/:repo/assignees"}, + {"/repos/:owner/:repo/assignees/:assignee", "/repos/:owner/:repo/assignees/:assignee"}, + {"/repos/:owner/:repo/issues/:number/comments", "/repos/:owner/:repo/issues/:number/comments"}, + {"/repos/:owner/:repo/issues/:number/events", "/repos/:owner/:repo/issues/:number/events"}, + {"/repos/:owner/:repo/labels", "/repos/:owner/:repo/labels"}, + {"/repos/:owner/:repo/labels/:name", "/repos/:owner/:repo/labels/:name"}, + {"/repos/:owner/:repo/issues/:number/labels", "/repos/:owner/:repo/issues/:number/labels"}, + {"/repos/:owner/:repo/milestones/:number/labels", "/repos/:owner/:repo/milestones/:number/labels"}, + {"/repos/:owner/:repo/milestones", "/repos/:owner/:repo/milestones"}, + {"/repos/:owner/:repo/milestones/:number", "/repos/:owner/:repo/milestones/:number"}, + {"/emojis", "/emojis"}, + {"/gitignore/templates", "/gitignore/templates"}, + {"/gitignore/templates/:name", "/gitignore/templates/:name"}, + {"/meta", "/meta"}, + {"/rate_limit", "/rate_limit"}, + {"/users/:user/orgs", "/users/:user/orgs"}, + {"/user/orgs", "/user/orgs"}, + {"/orgs/:org", "/orgs/:org"}, + {"/orgs/:org/members", "/orgs/:org/members"}, + {"/orgs/:org/members/:user", "/orgs/:org/members/:user"}, + {"/orgs/:org/public_members", "/orgs/:org/public_members"}, + {"/orgs/:org/public_members/:user", "/orgs/:org/public_members/:user"}, + {"/orgs/:org/teams", "/orgs/:org/teams"}, + {"/teams/:id", "/teams/:id"}, + {"/teams/:id/members", "/teams/:id/members"}, + {"/teams/:id/members/:user", "/teams/:id/members/:user"}, + {"/teams/:id/repos", "/teams/:id/repos"}, + {"/teams/:id/repos/:owner/:repo", "/teams/:id/repos/:owner/:repo"}, + {"/user/teams", "/user/teams"}, + {"/repos/:owner/:repo/pulls", "/repos/:owner/:repo/pulls"}, + {"/repos/:owner/:repo/pulls/:number", "/repos/:owner/:repo/pulls/:number"}, + {"/repos/:owner/:repo/pulls/:number/commits", "/repos/:owner/:repo/pulls/:number/commits"}, + {"/repos/:owner/:repo/pulls/:number/files", "/repos/:owner/:repo/pulls/:number/files"}, + {"/repos/:owner/:repo/pulls/:number/merge", "/repos/:owner/:repo/pulls/:number/merge"}, + {"/repos/:owner/:repo/pulls/:number/comments", "/repos/:owner/:repo/pulls/:number/comments"}, + {"/user/repos", "/user/repos"}, + {"/users/:user/repos", "/users/:user/repos"}, + {"/orgs/:org/repos", "/orgs/:org/repos"}, + {"/repositories", "/repositories"}, + {"/repos/:owner/:repo", "/repos/:owner/:repo"}, + {"/repos/:owner/:repo/contributors", "/repos/:owner/:repo/contributors"}, + {"/repos/:owner/:repo/languages", "/repos/:owner/:repo/languages"}, + {"/repos/:owner/:repo/teams", "/repos/:owner/:repo/teams"}, + {"/repos/:owner/:repo/tags", "/repos/:owner/:repo/tags"}, + {"/repos/:owner/:repo/branches", "/repos/:owner/:repo/branches"}, + {"/repos/:owner/:repo/branches/:branch", "/repos/:owner/:repo/branches/:branch"}, + {"/repos/:owner/:repo/collaborators", "/repos/:owner/:repo/collaborators"}, + {"/repos/:owner/:repo/collaborators/:user", "/repos/:owner/:repo/collaborators/:user"}, + {"/repos/:owner/:repo/comments", "/repos/:owner/:repo/comments"}, + {"/repos/:owner/:repo/commits/:sha/comments", "/repos/:owner/:repo/commits/:sha/comments"}, + {"/repos/:owner/:repo/comments/:id", "/repos/:owner/:repo/comments/:id"}, + {"/repos/:owner/:repo/commits", "/repos/:owner/:repo/commits"}, + {"/repos/:owner/:repo/commits/:sha", "/repos/:owner/:repo/commits/:sha"}, + {"/repos/:owner/:repo/readme", "/repos/:owner/:repo/readme"}, + {"/repos/:owner/:repo/keys", "/repos/:owner/:repo/keys"}, + {"/repos/:owner/:repo/keys/:id", "/repos/:owner/:repo/keys/:id"}, + {"/repos/:owner/:repo/downloads", "/repos/:owner/:repo/downloads"}, + {"/repos/:owner/:repo/downloads/:id", "/repos/:owner/:repo/downloads/:id"}, + {"/repos/:owner/:repo/forks", "/repos/:owner/:repo/forks"}, + {"/repos/:owner/:repo/hooks", "/repos/:owner/:repo/hooks"}, + {"/repos/:owner/:repo/hooks/:id", "/repos/:owner/:repo/hooks/:id"}, + {"/repos/:owner/:repo/releases", "/repos/:owner/:repo/releases"}, + {"/repos/:owner/:repo/releases/:id", "/repos/:owner/:repo/releases/:id"}, + {"/repos/:owner/:repo/releases/:id/assets", "/repos/:owner/:repo/releases/:id/assets"}, + {"/repos/:owner/:repo/stats/contributors", "/repos/:owner/:repo/stats/contributors"}, + {"/repos/:owner/:repo/stats/commit_activity", "/repos/:owner/:repo/stats/commit_activity"}, + {"/repos/:owner/:repo/stats/code_frequency", "/repos/:owner/:repo/stats/code_frequency"}, + {"/repos/:owner/:repo/stats/participation", "/repos/:owner/:repo/stats/participation"}, + {"/repos/:owner/:repo/stats/punch_card", "/repos/:owner/:repo/stats/punch_card"}, + {"/repos/:owner/:repo/statuses/:ref", "/repos/:owner/:repo/statuses/:ref"}, + {"/search/repositories", "/search/repositories"}, + {"/search/code", "/search/code"}, + {"/search/issues", "/search/issues"}, + {"/search/users", "/search/users"}, + {"/legacy/issues/search/:owner/:repository/:state/:keyword", "/legacy/issues/search/:owner/:repository/:state/:keyword"}, + {"/legacy/repos/search/:keyword", "/legacy/repos/search/:keyword"}, + {"/legacy/user/search/:keyword", "/legacy/user/search/:keyword"}, + {"/legacy/user/email/:email", "/legacy/user/email/:email"}, + {"/users/:user", "/users/:user"}, + {"/user", "/user"}, + {"/users", "/users"}, + {"/user/emails", "/user/emails"}, + {"/users/:user/followers", "/users/:user/followers"}, + {"/user/followers", "/user/followers"}, + {"/users/:user/following", "/users/:user/following"}, + {"/user/following", "/user/following"}, + {"/user/following/:user", "/user/following/:user"}, + {"/users/:user/following/:target_user", "/users/:user/following/:target_user"}, + {"/users/:user/keys", "/users/:user/keys"}, + {"/user/keys", "/user/keys"}, + {"/user/keys/:id", "/user/keys/:id"}, + {"/people/:userId", "/people/:userId"}, + {"/people", "/people"}, + {"/activities/:activityId/people/:collection", "/activities/:activityId/people/:collection"}, + {"/people/:userId/people/:collection", "/people/:userId/people/:collection"}, + {"/people/:userId/openIdConnect", "/people/:userId/openIdConnect"}, + {"/people/:userId/activities/:collection", "/people/:userId/activities/:collection"}, + {"/activities/:activityId", "/activities/:activityId"}, + {"/activities", "/activities"}, + {"/activities/:activityId/comments", "/activities/:activityId/comments"}, + {"/comments/:commentId", "/comments/:commentId"}, + {"/people/:userId/moments/:collection", "/people/:userId/moments/:collection"}, +} + +type testcase struct { + path string + value interface{} + params []denco.Param + found bool +} + +func runLookupTest(t *testing.T, records []denco.Record, testcases []testcase) { + r := denco.New() + if err := r.Build(records); err != nil { + t.Fatal(err) + } + for _, testcase := range testcases { + data, params, found := r.Lookup(testcase.path) + if !reflect.DeepEqual(data, testcase.value) || !reflect.DeepEqual(params, denco.Params(testcase.params)) || !reflect.DeepEqual(found, testcase.found) { + t.Errorf("Router.Lookup(%q) => (%#v, %#v, %#v), want (%#v, %#v, %#v)", testcase.path, data, params, found, testcase.value, denco.Params(testcase.params), testcase.found) + } + } +} + +func TestRouter_Lookup(t *testing.T) { + testcases := []testcase{ + {"/", "testroute0", nil, true}, + {"/gists/1323/foo/bar", "testroute11", []denco.Param{{"param1", "1323"}}, true}, + {"/gists/1323/foo/133", "testroute12", []denco.Param{{"param1", "1323"}, {"param2", "133"}}, true}, + {"/234/1323/foo/133", "testroute13", []denco.Param{{"param1", "234"}, {"param2", "1323"}, {"param3", "133"}}, true}, + {"/path/to/route", "testroute1", nil, true}, + {"/path/to/other", "testroute2", nil, true}, + {"/path/to/route/a", "testroute3", nil, true}, + {"/path/to/hoge", "testroute4", []denco.Param{{"param", "hoge"}}, true}, + {"/path/to/wildcard/some/params", "testroute5", []denco.Param{{"routepath", "some/params"}}, true}, + {"/path/to/o1/o2", "testroute6", []denco.Param{{"param1", "o1"}, {"param2", "o2"}}, true}, + {"/path/to/p1/sep/p2", "testroute7", []denco.Param{{"param1", "p1"}, {"param2", "p2"}}, true}, + {"/2014/01/06", "testroute8", []denco.Param{{"year", "2014"}, {"month", "01"}, {"day", "06"}}, true}, + {"/user/777", "testroute9", []denco.Param{{"id", "777"}}, true}, + {"/a/to/b/p1/some/wildcard/params", "testroute10", []denco.Param{{"param", "p1"}, {"routepath", "some/wildcard/params"}}, true}, + {"/missing", nil, nil, false}, + } + runLookupTest(t, routes(), testcases) + + records := []denco.Record{ + {"/", "testroute0"}, + {"/:b", "testroute1"}, + {"/*wildcard", "testroute2"}, + } + testcases = []testcase{ + {"/", "testroute0", nil, true}, + {"/true", "testroute1", []denco.Param{{"b", "true"}}, true}, + {"/foo/bar", "testroute2", []denco.Param{{"wildcard", "foo/bar"}}, true}, + } + runLookupTest(t, records, testcases) + + records = []denco.Record{ + {"/networks/:owner/:repo/events", "testroute0"}, + {"/orgs/:org/events", "testroute1"}, + {"/notifications/threads/:id", "testroute2"}, + {"/mypathisgreat/:thing-id", "testroute3"}, + } + testcases = []testcase{ + {"/networks/:owner/:repo/events", "testroute0", []denco.Param{{"owner", ":owner"}, {"repo", ":repo"}}, true}, + {"/orgs/:org/events", "testroute1", []denco.Param{{"org", ":org"}}, true}, + {"/notifications/threads/:id", "testroute2", []denco.Param{{"id", ":id"}}, true}, + {"/mypathisgreat/:thing-id", "testroute3", []denco.Param{{"thing-id", ":thing-id"}}, true}, + } + runLookupTest(t, records, testcases) + + runLookupTest(t, []denco.Record{ + {"/", "route2"}, + }, []testcase{ + {"/user/alice", nil, nil, false}, + }) + + runLookupTest(t, []denco.Record{ + {"/user/:name", "route1"}, + }, []testcase{ + {"/", nil, nil, false}, + }) + + runLookupTest(t, []denco.Record{ + {"/*wildcard", "testroute0"}, + {"/a/:b", "testroute1"}, + }, []testcase{ + {"/a", "testroute0", []denco.Param{{"wildcard", "a"}}, true}, + }) +} + +func TestRouter_Lookup_withManyRoutes(t *testing.T) { + n := 1000 + rand.Seed(time.Now().UnixNano()) + records := make([]denco.Record, n) + for i := 0; i < n; i++ { + records[i] = denco.Record{Key: "/" + randomString(rand.Intn(50)+10), Value: fmt.Sprintf("route%d", i)} + } + router := denco.New() + if err := router.Build(records); err != nil { + t.Fatal(err) + } + for _, r := range records { + data, params, found := router.Lookup(r.Key) + if !reflect.DeepEqual(data, r.Value) || len(params) != 0 || !reflect.DeepEqual(found, true) { + t.Errorf("Router.Lookup(%q) => (%#v, %#v, %#v), want (%#v, %#v, %#v)", r.Key, data, len(params), found, r.Value, 0, true) + } + } +} + +func TestRouter_Lookup_realURIs(t *testing.T) { + testcases := []testcase{ + {"/authorizations", "/authorizations", nil, true}, + {"/authorizations/1", "/authorizations/:id", []denco.Param{{"id", "1"}}, true}, + {"/applications/1/tokens/zohRoo7e", "/applications/:client_id/tokens/:access_token", []denco.Param{{"client_id", "1"}, {"access_token", "zohRoo7e"}}, true}, + {"/events", "/events", nil, true}, + {"/repos/naoina/denco/events", "/repos/:owner/:repo/events", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/networks/naoina/denco/events", "/networks/:owner/:repo/events", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/orgs/something/events", "/orgs/:org/events", []denco.Param{{"org", "something"}}, true}, + {"/users/naoina/received_events", "/users/:user/received_events", []denco.Param{{"user", "naoina"}}, true}, + {"/users/naoina/received_events/public", "/users/:user/received_events/public", []denco.Param{{"user", "naoina"}}, true}, + {"/users/naoina/events", "/users/:user/events", []denco.Param{{"user", "naoina"}}, true}, + {"/users/naoina/events/public", "/users/:user/events/public", []denco.Param{{"user", "naoina"}}, true}, + {"/users/naoina/events/orgs/something", "/users/:user/events/orgs/:org", []denco.Param{{"user", "naoina"}, {"org", "something"}}, true}, + {"/feeds", "/feeds", nil, true}, + {"/notifications", "/notifications", nil, true}, + {"/repos/naoina/denco/notifications", "/repos/:owner/:repo/notifications", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/notifications/threads/1", "/notifications/threads/:id", []denco.Param{{"id", "1"}}, true}, + {"/notifications/threads/2/subscription", "/notifications/threads/:id/subscription", []denco.Param{{"id", "2"}}, true}, + {"/repos/naoina/denco/stargazers", "/repos/:owner/:repo/stargazers", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/users/naoina/starred", "/users/:user/starred", []denco.Param{{"user", "naoina"}}, true}, + {"/user/starred", "/user/starred", nil, true}, + {"/user/starred/naoina/denco", "/user/starred/:owner/:repo", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/subscribers", "/repos/:owner/:repo/subscribers", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/users/naoina/subscriptions", "/users/:user/subscriptions", []denco.Param{{"user", "naoina"}}, true}, + {"/user/subscriptions", "/user/subscriptions", nil, true}, + {"/repos/naoina/denco/subscription", "/repos/:owner/:repo/subscription", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/user/subscriptions/naoina/denco", "/user/subscriptions/:owner/:repo", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/users/naoina/gists", "/users/:user/gists", []denco.Param{{"user", "naoina"}}, true}, + {"/gists", "/gists", nil, true}, + {"/gists/1", "/gists/:id", []denco.Param{{"id", "1"}}, true}, + {"/gists/2/star", "/gists/:id/star", []denco.Param{{"id", "2"}}, true}, + {"/repos/naoina/denco/git/blobs/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/git/blobs/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true}, + {"/repos/naoina/denco/git/commits/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/git/commits/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true}, + {"/repos/naoina/denco/git/refs", "/repos/:owner/:repo/git/refs", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/git/tags/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/git/tags/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true}, + {"/repos/naoina/denco/git/trees/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/git/trees/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true}, + {"/issues", "/issues", nil, true}, + {"/user/issues", "/user/issues", nil, true}, + {"/orgs/something/issues", "/orgs/:org/issues", []denco.Param{{"org", "something"}}, true}, + {"/repos/naoina/denco/issues", "/repos/:owner/:repo/issues", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/issues/1", "/repos/:owner/:repo/issues/:number", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/repos/naoina/denco/assignees", "/repos/:owner/:repo/assignees", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/assignees/foo", "/repos/:owner/:repo/assignees/:assignee", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"assignee", "foo"}}, true}, + {"/repos/naoina/denco/issues/1/comments", "/repos/:owner/:repo/issues/:number/comments", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/repos/naoina/denco/issues/1/events", "/repos/:owner/:repo/issues/:number/events", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/repos/naoina/denco/labels", "/repos/:owner/:repo/labels", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/labels/bug", "/repos/:owner/:repo/labels/:name", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"name", "bug"}}, true}, + {"/repos/naoina/denco/issues/1/labels", "/repos/:owner/:repo/issues/:number/labels", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/repos/naoina/denco/milestones/1/labels", "/repos/:owner/:repo/milestones/:number/labels", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/repos/naoina/denco/milestones", "/repos/:owner/:repo/milestones", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/milestones/1", "/repos/:owner/:repo/milestones/:number", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/emojis", "/emojis", nil, true}, + {"/gitignore/templates", "/gitignore/templates", nil, true}, + {"/gitignore/templates/Go", "/gitignore/templates/:name", []denco.Param{{"name", "Go"}}, true}, + {"/meta", "/meta", nil, true}, + {"/rate_limit", "/rate_limit", nil, true}, + {"/users/naoina/orgs", "/users/:user/orgs", []denco.Param{{"user", "naoina"}}, true}, + {"/user/orgs", "/user/orgs", nil, true}, + {"/orgs/something", "/orgs/:org", []denco.Param{{"org", "something"}}, true}, + {"/orgs/something/members", "/orgs/:org/members", []denco.Param{{"org", "something"}}, true}, + {"/orgs/something/members/naoina", "/orgs/:org/members/:user", []denco.Param{{"org", "something"}, {"user", "naoina"}}, true}, + {"/orgs/something/public_members", "/orgs/:org/public_members", []denco.Param{{"org", "something"}}, true}, + {"/orgs/something/public_members/naoina", "/orgs/:org/public_members/:user", []denco.Param{{"org", "something"}, {"user", "naoina"}}, true}, + {"/orgs/something/teams", "/orgs/:org/teams", []denco.Param{{"org", "something"}}, true}, + {"/teams/1", "/teams/:id", []denco.Param{{"id", "1"}}, true}, + {"/teams/2/members", "/teams/:id/members", []denco.Param{{"id", "2"}}, true}, + {"/teams/3/members/naoina", "/teams/:id/members/:user", []denco.Param{{"id", "3"}, {"user", "naoina"}}, true}, + {"/teams/4/repos", "/teams/:id/repos", []denco.Param{{"id", "4"}}, true}, + {"/teams/5/repos/naoina/denco", "/teams/:id/repos/:owner/:repo", []denco.Param{{"id", "5"}, {"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/user/teams", "/user/teams", nil, true}, + {"/repos/naoina/denco/pulls", "/repos/:owner/:repo/pulls", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/pulls/1", "/repos/:owner/:repo/pulls/:number", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/repos/naoina/denco/pulls/1/commits", "/repos/:owner/:repo/pulls/:number/commits", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/repos/naoina/denco/pulls/1/files", "/repos/:owner/:repo/pulls/:number/files", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/repos/naoina/denco/pulls/1/merge", "/repos/:owner/:repo/pulls/:number/merge", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/repos/naoina/denco/pulls/1/comments", "/repos/:owner/:repo/pulls/:number/comments", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"number", "1"}}, true}, + {"/user/repos", "/user/repos", nil, true}, + {"/users/naoina/repos", "/users/:user/repos", []denco.Param{{"user", "naoina"}}, true}, + {"/orgs/something/repos", "/orgs/:org/repos", []denco.Param{{"org", "something"}}, true}, + {"/repositories", "/repositories", nil, true}, + {"/repos/naoina/denco", "/repos/:owner/:repo", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/contributors", "/repos/:owner/:repo/contributors", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/languages", "/repos/:owner/:repo/languages", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/teams", "/repos/:owner/:repo/teams", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/tags", "/repos/:owner/:repo/tags", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/branches", "/repos/:owner/:repo/branches", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/branches/master", "/repos/:owner/:repo/branches/:branch", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"branch", "master"}}, true}, + {"/repos/naoina/denco/collaborators", "/repos/:owner/:repo/collaborators", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/collaborators/something", "/repos/:owner/:repo/collaborators/:user", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"user", "something"}}, true}, + {"/repos/naoina/denco/comments", "/repos/:owner/:repo/comments", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/commits/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9/comments", "/repos/:owner/:repo/commits/:sha/comments", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true}, + {"/repos/naoina/denco/comments/1", "/repos/:owner/:repo/comments/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "1"}}, true}, + {"/repos/naoina/denco/commits", "/repos/:owner/:repo/commits", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/commits/03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9", "/repos/:owner/:repo/commits/:sha", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"sha", "03c3bbc7f0d12268b9ca53d4fbfd8dc5ae5697b9"}}, true}, + {"/repos/naoina/denco/readme", "/repos/:owner/:repo/readme", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/keys", "/repos/:owner/:repo/keys", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/keys/1", "/repos/:owner/:repo/keys/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "1"}}, true}, + {"/repos/naoina/denco/downloads", "/repos/:owner/:repo/downloads", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/downloads/2", "/repos/:owner/:repo/downloads/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "2"}}, true}, + {"/repos/naoina/denco/forks", "/repos/:owner/:repo/forks", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/hooks", "/repos/:owner/:repo/hooks", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/hooks/2", "/repos/:owner/:repo/hooks/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "2"}}, true}, + {"/repos/naoina/denco/releases", "/repos/:owner/:repo/releases", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/releases/1", "/repos/:owner/:repo/releases/:id", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "1"}}, true}, + {"/repos/naoina/denco/releases/1/assets", "/repos/:owner/:repo/releases/:id/assets", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"id", "1"}}, true}, + {"/repos/naoina/denco/stats/contributors", "/repos/:owner/:repo/stats/contributors", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/stats/commit_activity", "/repos/:owner/:repo/stats/commit_activity", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/stats/code_frequency", "/repos/:owner/:repo/stats/code_frequency", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/stats/participation", "/repos/:owner/:repo/stats/participation", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/stats/punch_card", "/repos/:owner/:repo/stats/punch_card", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}}, true}, + {"/repos/naoina/denco/statuses/master", "/repos/:owner/:repo/statuses/:ref", []denco.Param{{"owner", "naoina"}, {"repo", "denco"}, {"ref", "master"}}, true}, + {"/search/repositories", "/search/repositories", nil, true}, + {"/search/code", "/search/code", nil, true}, + {"/search/issues", "/search/issues", nil, true}, + {"/search/users", "/search/users", nil, true}, + {"/legacy/issues/search/naoina/denco/closed/test", "/legacy/issues/search/:owner/:repository/:state/:keyword", []denco.Param{{"owner", "naoina"}, {"repository", "denco"}, {"state", "closed"}, {"keyword", "test"}}, true}, + {"/legacy/repos/search/test", "/legacy/repos/search/:keyword", []denco.Param{{"keyword", "test"}}, true}, + {"/legacy/user/search/test", "/legacy/user/search/:keyword", []denco.Param{{"keyword", "test"}}, true}, + {"/legacy/user/email/naoina@kuune.org", "/legacy/user/email/:email", []denco.Param{{"email", "naoina@kuune.org"}}, true}, + {"/users/naoina", "/users/:user", []denco.Param{{"user", "naoina"}}, true}, + {"/user", "/user", nil, true}, + {"/users", "/users", nil, true}, + {"/user/emails", "/user/emails", nil, true}, + {"/users/naoina/followers", "/users/:user/followers", []denco.Param{{"user", "naoina"}}, true}, + {"/user/followers", "/user/followers", nil, true}, + {"/users/naoina/following", "/users/:user/following", []denco.Param{{"user", "naoina"}}, true}, + {"/user/following", "/user/following", nil, true}, + {"/user/following/naoina", "/user/following/:user", []denco.Param{{"user", "naoina"}}, true}, + {"/users/naoina/following/target", "/users/:user/following/:target_user", []denco.Param{{"user", "naoina"}, {"target_user", "target"}}, true}, + {"/users/naoina/keys", "/users/:user/keys", []denco.Param{{"user", "naoina"}}, true}, + {"/user/keys", "/user/keys", nil, true}, + {"/user/keys/1", "/user/keys/:id", []denco.Param{{"id", "1"}}, true}, + {"/people/me", "/people/:userId", []denco.Param{{"userId", "me"}}, true}, + {"/people", "/people", nil, true}, + {"/activities/foo/people/vault", "/activities/:activityId/people/:collection", []denco.Param{{"activityId", "foo"}, {"collection", "vault"}}, true}, + {"/people/me/people/vault", "/people/:userId/people/:collection", []denco.Param{{"userId", "me"}, {"collection", "vault"}}, true}, + {"/people/me/openIdConnect", "/people/:userId/openIdConnect", []denco.Param{{"userId", "me"}}, true}, + {"/people/me/activities/vault", "/people/:userId/activities/:collection", []denco.Param{{"userId", "me"}, {"collection", "vault"}}, true}, + {"/activities/foo", "/activities/:activityId", []denco.Param{{"activityId", "foo"}}, true}, + {"/activities", "/activities", nil, true}, + {"/activities/foo/comments", "/activities/:activityId/comments", []denco.Param{{"activityId", "foo"}}, true}, + {"/comments/hoge", "/comments/:commentId", []denco.Param{{"commentId", "hoge"}}, true}, + {"/people/me/moments/vault", "/people/:userId/moments/:collection", []denco.Param{{"userId", "me"}, {"collection", "vault"}}, true}, + } + runLookupTest(t, realURIs, testcases) +} + +func TestRouter_Build(t *testing.T) { + // test for duplicate name of path parameters. + func() { + r := denco.New() + if err := r.Build([]denco.Record{ + {"/:user/:id/:id", "testroute0"}, + {"/:user/:user/:id", "testroute0"}, + }); err == nil { + t.Errorf("no error returned by duplicate name of path parameters") + } + }() +} + +func TestRouter_Build_withoutSizeHint(t *testing.T) { + for _, v := range []struct { + keys []string + sizeHint int + }{ + {[]string{"/user"}, 0}, + {[]string{"/user/:id"}, 1}, + {[]string{"/user/:id/post"}, 1}, + {[]string{"/user/:id/:group"}, 2}, + {[]string{"/user/:id/post/:cid"}, 2}, + {[]string{"/user/:id/post/:cid", "/admin/:id/post/:cid"}, 2}, + {[]string{"/user/:id", "/admin/:id/post/:cid"}, 2}, + {[]string{"/user/:id/post/:cid", "/admin/:id/post/:cid/:type"}, 3}, + } { + r := denco.New() + actual := r.SizeHint + expect := -1 + if !reflect.DeepEqual(actual, expect) { + t.Errorf(`before Build; Router.SizeHint => (%[1]T=%#[1]v); want (%[2]T=%#[2]v)`, actual, expect) + } + records := make([]denco.Record, len(v.keys)) + for i, k := range v.keys { + records[i] = denco.Record{Key: k, Value: "value"} + } + if err := r.Build(records); err != nil { + t.Fatal(err) + } + actual = r.SizeHint + expect = v.sizeHint + if !reflect.DeepEqual(actual, expect) { + t.Errorf(`Router.Build(%#v); Router.SizeHint => (%[2]T=%#[2]v); want (%[3]T=%#[3]v)`, records, actual, expect) + } + } +} + +func TestRouter_Build_withSizeHint(t *testing.T) { + for _, v := range []struct { + key string + sizeHint int + expect int + }{ + {"/user", 0, 0}, + {"/user", 1, 1}, + {"/user", 2, 2}, + {"/user/:id", 3, 3}, + {"/user/:id/:group", 0, 0}, + {"/user/:id/:group", 1, 1}, + } { + r := denco.New() + r.SizeHint = v.sizeHint + records := []denco.Record{ + {v.key, "value"}, + } + if err := r.Build(records); err != nil { + t.Fatal(err) + } + actual := r.SizeHint + expect := v.expect + if !reflect.DeepEqual(actual, expect) { + t.Errorf(`Router.Build(%#v); Router.SizeHint => (%[2]T=%#[2]v); want (%[3]T=%#[3]v)`, records, actual, expect) + } + } +} + +func TestParams_Get(t *testing.T) { + params := denco.Params([]denco.Param{ + {"name1", "value1"}, + {"name2", "value2"}, + {"name3", "value3"}, + {"name1", "value4"}, + }) + for _, v := range []struct{ value, expected string }{ + {"name1", "value1"}, + {"name2", "value2"}, + {"name3", "value3"}, + {"name4", ""}, + } { + actual := params.Get(v.value) + expected := v.expected + if !reflect.DeepEqual(actual, expected) { + t.Errorf("Params.Get(%q) => %#v, want %#v", v.value, actual, expected) + } + } +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/server.go b/vendor/github.com/go-openapi/runtime/middleware/denco/server.go new file mode 100755 index 0000000000..0886713c18 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/server.go @@ -0,0 +1,106 @@ +package denco + +import ( + "net/http" +) + +// Mux represents a multiplexer for HTTP request. +type Mux struct{} + +// NewMux returns a new Mux. +func NewMux() *Mux { + return &Mux{} +} + +// GET is shorthand of Mux.Handler("GET", path, handler). +func (m *Mux) GET(path string, handler HandlerFunc) Handler { + return m.Handler("GET", path, handler) +} + +// POST is shorthand of Mux.Handler("POST", path, handler). +func (m *Mux) POST(path string, handler HandlerFunc) Handler { + return m.Handler("POST", path, handler) +} + +// PUT is shorthand of Mux.Handler("PUT", path, handler). +func (m *Mux) PUT(path string, handler HandlerFunc) Handler { + return m.Handler("PUT", path, handler) +} + +// HEAD is shorthand of Mux.Handler("HEAD", path, handler). +func (m *Mux) HEAD(path string, handler HandlerFunc) Handler { + return m.Handler("HEAD", path, handler) +} + +// Handler returns a handler for HTTP method. +func (m *Mux) Handler(method, path string, handler HandlerFunc) Handler { + return Handler{ + Method: method, + Path: path, + Func: handler, + } +} + +// Build builds a http.Handler. +func (m *Mux) Build(handlers []Handler) (http.Handler, error) { + recordMap := make(map[string][]Record) + for _, h := range handlers { + recordMap[h.Method] = append(recordMap[h.Method], NewRecord(h.Path, h.Func)) + } + mux := newServeMux() + for m, records := range recordMap { + router := New() + if err := router.Build(records); err != nil { + return nil, err + } + mux.routers[m] = router + } + return mux, nil +} + +// Handler represents a handler of HTTP request. +type Handler struct { + // Method is an HTTP method. + Method string + + // Path is a routing path for handler. + Path string + + // Func is a function of handler of HTTP request. + Func HandlerFunc +} + +// The HandlerFunc type is aliased to type of handler function. +type HandlerFunc func(w http.ResponseWriter, r *http.Request, params Params) + +type serveMux struct { + routers map[string]*Router +} + +func newServeMux() *serveMux { + return &serveMux{ + routers: make(map[string]*Router), + } +} + +// ServeHTTP implements http.Handler interface. +func (mux *serveMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { + handler, params := mux.handler(r.Method, r.URL.Path) + handler(w, r, params) +} + +func (mux *serveMux) handler(method, path string) (HandlerFunc, []Param) { + if router, found := mux.routers[method]; found { + if handler, params, found := router.Lookup(path); found { + return handler.(HandlerFunc), params + } + } + return NotFound, nil +} + +// NotFound replies to the request with an HTTP 404 not found error. +// NotFound is called when unknown HTTP method or a handler not found. +// If you want to use the your own NotFound handler, please overwrite this variable. +var NotFound = func(w http.ResponseWriter, r *http.Request, _ Params) { + http.NotFound(w, r) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/server_test.go b/vendor/github.com/go-openapi/runtime/middleware/denco/server_test.go new file mode 100755 index 0000000000..27c4f0033f --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/server_test.go @@ -0,0 +1,106 @@ +package denco_test + +import ( + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-openapi/runtime/middleware/denco" +) + +func testHandlerFunc(w http.ResponseWriter, r *http.Request, params denco.Params) { + fmt.Fprintf(w, "method: %s, path: %s, params: %v", r.Method, r.URL.Path, params) +} + +func TestMux(t *testing.T) { + mux := denco.NewMux() + handler, err := mux.Build([]denco.Handler{ + mux.GET("/", testHandlerFunc), + mux.GET("/user/:name", testHandlerFunc), + mux.POST("/user/:name", testHandlerFunc), + mux.HEAD("/user/:name", testHandlerFunc), + mux.PUT("/user/:name", testHandlerFunc), + mux.Handler("GET", "/user/handler", testHandlerFunc), + mux.Handler("POST", "/user/handler", testHandlerFunc), + {"PUT", "/user/inference", testHandlerFunc}, + }) + if err != nil { + t.Fatal(err) + } + server := httptest.NewServer(handler) + defer server.Close() + + for _, v := range []struct { + status int + method, path, expected string + }{ + {200, "GET", "/", "method: GET, path: /, params: []"}, + {200, "GET", "/user/alice", "method: GET, path: /user/alice, params: [{name alice}]"}, + {200, "POST", "/user/bob", "method: POST, path: /user/bob, params: [{name bob}]"}, + {200, "HEAD", "/user/alice", ""}, + {200, "PUT", "/user/bob", "method: PUT, path: /user/bob, params: [{name bob}]"}, + {404, "POST", "/", "404 page not found\n"}, + {404, "GET", "/unknown", "404 page not found\n"}, + {404, "POST", "/user/alice/1", "404 page not found\n"}, + {200, "GET", "/user/handler", "method: GET, path: /user/handler, params: []"}, + {200, "POST", "/user/handler", "method: POST, path: /user/handler, params: []"}, + {200, "PUT", "/user/inference", "method: PUT, path: /user/inference, params: []"}, + } { + req, err := http.NewRequest(v.method, server.URL+v.path, nil) + if err != nil { + t.Error(err) + continue + } + res, err := http.DefaultClient.Do(req) + if err != nil { + t.Error(err) + continue + } + defer res.Body.Close() + body, err := ioutil.ReadAll(res.Body) + if err != nil { + t.Error(err) + continue + } + actual := string(body) + expected := v.expected + if res.StatusCode != v.status || actual != expected { + t.Errorf(`%s "%s" => %#v %#v, want %#v %#v`, v.method, v.path, res.StatusCode, actual, v.status, expected) + } + } +} + +func TestNotFound(t *testing.T) { + mux := denco.NewMux() + handler, err := mux.Build([]denco.Handler{}) + if err != nil { + t.Fatal(err) + } + server := httptest.NewServer(handler) + defer server.Close() + + origNotFound := denco.NotFound + defer func() { + denco.NotFound = origNotFound + }() + denco.NotFound = func(w http.ResponseWriter, r *http.Request, params denco.Params) { + 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) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + body, err := ioutil.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + actual := string(body) + expected := "method: GET, path: /, params: []" + if res.StatusCode != http.StatusServiceUnavailable || actual != expected { + t.Errorf(`GET "/" => %#v %#v, want %#v %#v`, res.StatusCode, actual, http.StatusServiceUnavailable, expected) + } +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/util.go b/vendor/github.com/go-openapi/runtime/middleware/denco/util.go new file mode 100755 index 0000000000..edc1f6ab80 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/util.go @@ -0,0 +1,12 @@ +package denco + +// NextSeparator returns an index of next separator in path. +func NextSeparator(path string, start int) int { + for start < len(path) { + if c := path[start]; c == '/' || c == TerminationCharacter { + break + } + start++ + } + return start +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/denco/util_test.go b/vendor/github.com/go-openapi/runtime/middleware/denco/util_test.go new file mode 100755 index 0000000000..c7241bec82 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/denco/util_test.go @@ -0,0 +1,31 @@ +package denco_test + +import ( + "reflect" + "testing" + + "github.com/go-openapi/runtime/middleware/denco" +) + +func TestNextSeparator(t *testing.T) { + for _, testcase := range []struct { + path string + start int + expected interface{} + }{ + {"/path/to/route", 0, 0}, + {"/path/to/route", 1, 5}, + {"/path/to/route", 9, 14}, + {"/path.html", 1, 10}, + {"/foo/bar.html", 1, 4}, + {"/foo/bar.html/baz.png", 5, 13}, + {"/foo/bar.html/baz.png", 14, 21}, + {"path#", 0, 4}, + } { + actual := denco.NextSeparator(testcase.path, testcase.start) + expected := testcase.expected + if !reflect.DeepEqual(actual, expected) { + t.Errorf("path = %q, start = %v expect %v, but %v", testcase.path, testcase.start, expected, actual) + } + } +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/doc.go b/vendor/github.com/go-openapi/runtime/middleware/doc.go new file mode 100644 index 0000000000..c0f963a7e6 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/doc.go @@ -0,0 +1,62 @@ +// 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 middleware provides the library with helper functions for serving swagger APIs. + +Pseudo middleware handler + + import ( + "net/http" + + "github.com/go-openapi/errors" + ) + + func newCompleteMiddleware(ctx *Context) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + // use context to lookup routes + if matched, ok := ctx.RouteInfo(r); ok { + + if len(matched.Authenticators) > 0 { + if _, err := ctx.Authorize(r, matched); err != nil { + ctx.Respond(rw, r, matched.Produces, matched, err) + return + } + } + + bound, validation := ctx.BindAndValidate(r, matched) + if validation != nil { + ctx.Respond(rw, r, matched.Produces, matched, validation) + return + } + + result, err := matched.Handler.Handle(bound) + if err != nil { + ctx.Respond(rw, r, matched.Produces, matched, err) + return + } + + ctx.Respond(rw, r, matched.Produces, matched, result) + return + } + + // Not found, check if it exists in the other methods first + if others := ctx.AllowedMethods(r); len(others) > 0 { + ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others)) + return + } + ctx.Respond(rw, r, ctx.spec.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.Path)) + }) + } +*/ +package middleware diff --git a/vendor/github.com/go-openapi/runtime/middleware/go18.go b/vendor/github.com/go-openapi/runtime/middleware/go18.go new file mode 100644 index 0000000000..75c762c094 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/go18.go @@ -0,0 +1,9 @@ +// +build go1.8 + +package middleware + +import "net/url" + +func pathUnescape(path string) (string, error) { + return url.PathUnescape(path) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/header/header.go b/vendor/github.com/go-openapi/runtime/middleware/header/header.go new file mode 100644 index 0000000000..3e342258bc --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/header/header.go @@ -0,0 +1,326 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd. + +// this file was taken from the github.com/golang/gddo repository + +// Package header provides functions for parsing HTTP headers. +package header + +import ( + "net/http" + "strings" + "time" +) + +// Octet types from RFC 2616. +var octetTypes [256]octetType + +type octetType byte + +const ( + isToken octetType = 1 << iota + isSpace +) + +func init() { + // OCTET = + // CHAR = + // CTL = + // CR = + // LF = + // SP = + // HT = + // <"> = + // CRLF = CR LF + // LWS = [CRLF] 1*( SP | HT ) + // TEXT = + // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> + // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT + // token = 1* + // qdtext = > + + for c := 0; c < 256; c++ { + var t octetType + isCtl := c <= 31 || c == 127 + isChar := 0 <= c && c <= 127 + isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) + if strings.ContainsRune(" \t\r\n", rune(c)) { + t |= isSpace + } + if isChar && !isCtl && !isSeparator { + t |= isToken + } + octetTypes[c] = t + } +} + +// Copy returns a shallow copy of the header. +func Copy(header http.Header) http.Header { + h := make(http.Header) + for k, vs := range header { + h[k] = vs + } + return h +} + +var timeLayouts = []string{"Mon, 02 Jan 2006 15:04:05 GMT", time.RFC850, time.ANSIC} + +// ParseTime parses the header as time. The zero value is returned if the +// header is not present or there is an error parsing the +// header. +func ParseTime(header http.Header, key string) time.Time { + if s := header.Get(key); s != "" { + for _, layout := range timeLayouts { + if t, err := time.Parse(layout, s); err == nil { + return t.UTC() + } + } + } + return time.Time{} +} + +// ParseList parses a comma separated list of values. Commas are ignored in +// quoted strings. Quoted values are not unescaped or unquoted. Whitespace is +// trimmed. +func ParseList(header http.Header, key string) []string { + var result []string + for _, s := range header[http.CanonicalHeaderKey(key)] { + begin := 0 + end := 0 + escape := false + quote := false + for i := 0; i < len(s); i++ { + b := s[i] + switch { + case escape: + escape = false + end = i + 1 + case quote: + switch b { + case '\\': + escape = true + case '"': + quote = false + } + end = i + 1 + case b == '"': + quote = true + end = i + 1 + case octetTypes[b]&isSpace != 0: + if begin == end { + begin = i + 1 + end = begin + } + case b == ',': + if begin < end { + result = append(result, s[begin:end]) + } + begin = i + 1 + end = begin + default: + end = i + 1 + } + } + if begin < end { + result = append(result, s[begin:end]) + } + } + return result +} + +// ParseValueAndParams parses a comma separated list of values with optional +// semicolon separated name-value pairs. Content-Type and Content-Disposition +// headers are in this format. +func ParseValueAndParams(header http.Header, key string) (string, map[string]string) { + return parseValueAndParams(header.Get(key)) +} + +func parseValueAndParams(s string) (value string, params map[string]string) { + params = make(map[string]string) + value, s = expectTokenSlash(s) + if value == "" { + return + } + value = strings.ToLower(value) + s = skipSpace(s) + for strings.HasPrefix(s, ";") { + var pkey string + pkey, s = expectToken(skipSpace(s[1:])) + if pkey == "" { + return + } + if !strings.HasPrefix(s, "=") { + return + } + var pvalue string + pvalue, s = expectTokenOrQuoted(s[1:]) + if pvalue == "" { + return + } + pkey = strings.ToLower(pkey) + params[pkey] = pvalue + s = skipSpace(s) + } + return +} + +// AcceptSpec ... +type AcceptSpec struct { + Value string + Q float64 +} + +// ParseAccept2 ... +func ParseAccept2(header http.Header, key string) (specs []AcceptSpec) { + for _, en := range ParseList(header, key) { + v, p := parseValueAndParams(en) + var spec AcceptSpec + spec.Value = v + spec.Q = 1.0 + if p != nil { + if q, ok := p["q"]; ok { + spec.Q, _ = expectQuality(q) + } + } + if spec.Q < 0.0 { + continue + } + specs = append(specs, spec) + } + + return +} + +// ParseAccept parses Accept* headers. +func ParseAccept(header http.Header, key string) (specs []AcceptSpec) { +loop: + for _, s := range header[key] { + for { + var spec AcceptSpec + spec.Value, s = expectTokenSlash(s) + if spec.Value == "" { + continue loop + } + spec.Q = 1.0 + s = skipSpace(s) + if strings.HasPrefix(s, ";") { + s = skipSpace(s[1:]) + for !strings.HasPrefix(s, "q=") && s != "" && !strings.HasPrefix(s, ",") { + s = skipSpace(s[1:]) + } + if strings.HasPrefix(s, "q=") { + spec.Q, s = expectQuality(s[2:]) + if spec.Q < 0.0 { + continue loop + } + } + } + specs = append(specs, spec) + s = skipSpace(s) + if !strings.HasPrefix(s, ",") { + continue loop + } + s = skipSpace(s[1:]) + } + } + return +} + +func skipSpace(s string) (rest string) { + i := 0 + for ; i < len(s); i++ { + if octetTypes[s[i]]&isSpace == 0 { + break + } + } + return s[i:] +} + +func expectToken(s string) (token, rest string) { + i := 0 + for ; i < len(s); i++ { + if octetTypes[s[i]]&isToken == 0 { + break + } + } + return s[:i], s[i:] +} + +func expectTokenSlash(s string) (token, rest string) { + i := 0 + for ; i < len(s); i++ { + b := s[i] + if (octetTypes[b]&isToken == 0) && b != '/' { + break + } + } + return s[:i], s[i:] +} + +func expectQuality(s string) (q float64, rest string) { + switch { + case len(s) == 0: + return -1, "" + case s[0] == '0': + q = 0 + case s[0] == '1': + q = 1 + default: + return -1, "" + } + s = s[1:] + if !strings.HasPrefix(s, ".") { + return q, s + } + s = s[1:] + i := 0 + n := 0 + d := 1 + for ; i < len(s); i++ { + b := s[i] + if b < '0' || b > '9' { + break + } + n = n*10 + int(b) - '0' + d *= 10 + } + return q + float64(n)/float64(d), s[i:] +} + +func expectTokenOrQuoted(s string) (value string, rest string) { + if !strings.HasPrefix(s, "\"") { + return expectToken(s) + } + s = s[1:] + for i := 0; i < len(s); i++ { + switch s[i] { + case '"': + return s[:i], s[i+1:] + case '\\': + p := make([]byte, len(s)-1) + j := copy(p, s[:i]) + escape := true + for i = i + 1; i < len(s); i++ { + b := s[i] + switch { + case escape: + escape = false + p[j] = b + j++ + case b == '\\': + escape = true + case b == '"': + return string(p[:j]), s[i+1:] + default: + p[j] = b + j++ + } + } + return "", "" + } + } + return "", "" +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/negotiate.go b/vendor/github.com/go-openapi/runtime/middleware/negotiate.go new file mode 100644 index 0000000000..a9b6f27d3d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/negotiate.go @@ -0,0 +1,98 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd. + +// this file was taken from the github.com/golang/gddo repository + +package middleware + +import ( + "net/http" + "strings" + + "github.com/go-openapi/runtime/middleware/header" +) + +// NegotiateContentEncoding returns the best offered content encoding for the +// request's Accept-Encoding header. If two offers match with equal weight and +// then the offer earlier in the list is preferred. If no offers are +// acceptable, then "" is returned. +func NegotiateContentEncoding(r *http.Request, offers []string) string { + bestOffer := "identity" + bestQ := -1.0 + specs := header.ParseAccept(r.Header, "Accept-Encoding") + for _, offer := range offers { + for _, spec := range specs { + if spec.Q > bestQ && + (spec.Value == "*" || spec.Value == offer) { + bestQ = spec.Q + bestOffer = offer + } + } + } + if bestQ == 0 { + bestOffer = "" + } + return bestOffer +} + +// NegotiateContentType returns the best offered content type for the request's +// Accept header. If two offers match with equal weight, then the more specific +// offer is preferred. For example, text/* trumps */*. If two offers match +// with equal weight and specificity, then the offer earlier in the list is +// preferred. If no offers match, then defaultOffer is returned. +func NegotiateContentType(r *http.Request, offers []string, defaultOffer string) string { + bestOffer := defaultOffer + bestQ := -1.0 + bestWild := 3 + specs := header.ParseAccept(r.Header, "Accept") + for _, rawOffer := range offers { + offer := normalizeOffer(rawOffer) + // No Accept header: just return the first offer. + if len(specs) == 0 { + return rawOffer + } + for _, spec := range specs { + switch { + case spec.Q == 0.0: + // ignore + case spec.Q < bestQ: + // better match found + case spec.Value == "*/*": + if spec.Q > bestQ || bestWild > 2 { + bestQ = spec.Q + bestWild = 2 + bestOffer = rawOffer + } + case strings.HasSuffix(spec.Value, "/*"): + if strings.HasPrefix(offer, spec.Value[:len(spec.Value)-1]) && + (spec.Q > bestQ || bestWild > 1) { + bestQ = spec.Q + bestWild = 1 + bestOffer = rawOffer + } + default: + if spec.Value == offer && + (spec.Q > bestQ || bestWild > 0) { + bestQ = spec.Q + bestWild = 0 + bestOffer = rawOffer + } + } + } + } + return bestOffer +} + +func normalizeOffers(orig []string) (norm []string) { + for _, o := range orig { + norm = append(norm, normalizeOffer(o)) + } + return +} + +func normalizeOffer(orig string) string { + return strings.SplitN(orig, ";", 2)[0] +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/negotiate_test.go b/vendor/github.com/go-openapi/runtime/middleware/negotiate_test.go new file mode 100644 index 0000000000..ca8d70a8ef --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/negotiate_test.go @@ -0,0 +1,83 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd. + +package middleware + +import ( + "net/http" + "testing" +) + +var negotiateContentEncodingTests = []struct { + s string + offers []string + expect string +}{ + {"", []string{"identity", "gzip"}, "identity"}, + {"*;q=0", []string{"identity", "gzip"}, ""}, + {"gzip", []string{"identity", "gzip"}, "gzip"}, +} + +func TestNegotiateContentEnoding(t *testing.T) { + for _, tt := range negotiateContentEncodingTests { + r := &http.Request{Header: http.Header{"Accept-Encoding": {tt.s}}} + actual := NegotiateContentEncoding(r, tt.offers) + if actual != tt.expect { + t.Errorf("NegotiateContentEncoding(%q, %#v)=%q, want %q", tt.s, tt.offers, actual, tt.expect) + } + } +} + +var negotiateContentTypeTests = []struct { + s string + offers []string + defaultOffer string + expect string +}{ + {"text/html, */*;q=0", []string{"x/y"}, "", ""}, + {"text/html, */*", []string{"x/y"}, "", "x/y"}, + {"text/html, image/png", []string{"text/html", "image/png"}, "", "text/html"}, + {"text/html, image/png", []string{"image/png", "text/html"}, "", "image/png"}, + {"text/html, image/png; q=0.5", []string{"image/png"}, "", "image/png"}, + {"text/html, image/png; q=0.5", []string{"text/html"}, "", "text/html"}, + {"text/html, image/png; q=0.5", []string{"foo/bar"}, "", ""}, + {"text/html, image/png; q=0.5", []string{"image/png", "text/html"}, "", "text/html"}, + {"text/html, image/png; q=0.5", []string{"text/html", "image/png"}, "", "text/html"}, + {"text/html;q=0.5, image/png", []string{"image/png"}, "", "image/png"}, + {"text/html;q=0.5, image/png", []string{"text/html"}, "", "text/html"}, + {"text/html;q=0.5, image/png", []string{"image/png", "text/html"}, "", "image/png"}, + {"text/html;q=0.5, image/png", []string{"text/html", "image/png"}, "", "image/png"}, + {"text/html;q=0.5, image/png", []string{"text/html", "image/png"}, "", "image/png"}, + {"image/png, image/*;q=0.5", []string{"image/jpg", "image/png"}, "", "image/png"}, + {"image/png, image/*;q=0.5", []string{"image/jpg"}, "", "image/jpg"}, + {"image/png, image/*;q=0.5", []string{"image/jpg", "image/gif"}, "", "image/jpg"}, + {"image/png, image/*", []string{"image/jpg", "image/gif"}, "", "image/jpg"}, + {"image/png, image/*", []string{"image/gif", "image/jpg"}, "", "image/gif"}, + {"image/png, image/*", []string{"image/gif", "image/png"}, "", "image/png"}, + {"image/png, image/*", []string{"image/png", "image/gif"}, "", "image/png"}, + {"application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.7,text/plain;version=0.0.4;q=0.3", []string{"text/plain"}, "", "text/plain"}, + {"application/json", []string{"application/json; charset=utf-8", "image/png"}, "", "application/json; charset=utf-8"}, + {"application/json; charset=utf-8", []string{"application/json; charset=utf-8", "image/png"}, "", "application/json; charset=utf-8"}, +} + +func TestNegotiateContentType(t *testing.T) { + for _, tt := range negotiateContentTypeTests { + r := &http.Request{Header: http.Header{"Accept": {tt.s}}} + actual := NegotiateContentType(r, tt.offers, tt.defaultOffer) + if actual != tt.expect { + t.Errorf("NegotiateContentType(%q, %#v, %q)=%q, want %q", tt.s, tt.offers, tt.defaultOffer, actual, tt.expect) + } + } +} + +func TestNegotiateContentTypeNoAcceptHeader(t *testing.T) { + r := &http.Request{Header: http.Header{}} + offers := []string{"application/json", "text/xml"} + actual := NegotiateContentType(r, offers, "") + if actual != "application/json" { + t.Errorf("NegotiateContentType(empty, %#v, empty)=%q, want %q", offers, actual, "application/json") + } +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go b/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go new file mode 100644 index 0000000000..466f553db4 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/not_implemented.go @@ -0,0 +1,48 @@ +// 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 middleware + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +type errorResp struct { + code int + response interface{} + headers http.Header +} + +func (e *errorResp) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + for k, v := range e.headers { + for _, val := range v { + rw.Header().Add(k, val) + } + } + if e.code > 0 { + rw.WriteHeader(e.code) + } else { + rw.WriteHeader(http.StatusInternalServerError) + } + if err := producer.Produce(rw, e.response); err != nil { + panic(err) + } +} + +// NotImplemented the error response when the response is not implemented +func NotImplemented(message string) Responder { + return &errorResp{http.StatusNotImplemented, message, make(http.Header)} +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/operation.go b/vendor/github.com/go-openapi/runtime/middleware/operation.go new file mode 100644 index 0000000000..1175a63cf2 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/operation.go @@ -0,0 +1,30 @@ +// 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 middleware + +import "net/http" + +// NewOperationExecutor creates a context aware middleware that handles the operations after routing +func NewOperationExecutor(ctx *Context) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + // use context to lookup routes + route, rCtx, _ := ctx.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + + route.Handler.ServeHTTP(rw, r) + }) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/operation_test.go b/vendor/github.com/go-openapi/runtime/middleware/operation_test.go new file mode 100644 index 0000000000..90ea0618d2 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/operation_test.go @@ -0,0 +1,64 @@ +// 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 middleware + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/internal/testing/petstore" + "github.com/stretchr/testify/assert" +) + +func TestOperationExecutor(t *testing.T) { + spec, api := petstore.NewAPI(t) + api.RegisterOperation("get", "/pets", runtime.OperationHandlerFunc(func(params interface{}) (interface{}, error) { + return []interface{}{ + map[string]interface{}{"id": 1, "name": "a dog"}, + }, nil + })) + + context := NewContext(spec, api, nil) + context.router = DefaultRouter(spec, context.api) + mw := NewOperationExecutor(context) + + recorder := httptest.NewRecorder() + request, _ := http.NewRequest("GET", "/api/pets", nil) + request.Header.Add("Accept", "application/json") + request.SetBasicAuth("admin", "admin") + mw.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + assert.Equal(t, `[{"id":1,"name":"a dog"}]`+"\n", recorder.Body.String()) + + spec, api = petstore.NewAPI(t) + api.RegisterOperation("get", "/pets", runtime.OperationHandlerFunc(func(params interface{}) (interface{}, error) { + return nil, errors.New(422, "expected") + })) + + context = NewContext(spec, api, nil) + context.router = DefaultRouter(spec, context.api) + mw = NewOperationExecutor(context) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "/api/pets", nil) + request.Header.Add("Accept", "application/json") + request.SetBasicAuth("admin", "admin") + mw.ServeHTTP(recorder, request) + assert.Equal(t, 422, recorder.Code) + assert.Equal(t, `{"code":422,"message":"expected"}`, recorder.Body.String()) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/parameter.go b/vendor/github.com/go-openapi/runtime/middleware/parameter.go new file mode 100644 index 0000000000..8975b6e1c8 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/parameter.go @@ -0,0 +1,480 @@ +// 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 middleware + +import ( + "encoding" + "encoding/base64" + "fmt" + "io" + "net/http" + "reflect" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +const defaultMaxMemory = 32 << 20 + +var textUnmarshalType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem() + +func newUntypedParamBinder(param spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedParamBinder { + binder := new(untypedParamBinder) + binder.Name = param.Name + binder.parameter = ¶m + binder.formats = formats + if param.In != "body" { + binder.validator = validate.NewParamValidator(¶m, formats) + } else { + binder.validator = validate.NewSchemaValidator(param.Schema, spec, param.Name, formats) + } + + return binder +} + +type untypedParamBinder struct { + parameter *spec.Parameter + formats strfmt.Registry + Name string + validator validate.EntityValidator +} + +func (p *untypedParamBinder) Type() reflect.Type { + return p.typeForSchema(p.parameter.Type, p.parameter.Format, p.parameter.Items) +} + +func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items) reflect.Type { + switch tpe { + case "boolean": + return reflect.TypeOf(true) + + case "string": + if tt, ok := p.formats.GetType(format); ok { + return tt + } + return reflect.TypeOf("") + + case "integer": + switch format { + case "int8": + return reflect.TypeOf(int8(0)) + case "int16": + return reflect.TypeOf(int16(0)) + case "int32": + return reflect.TypeOf(int32(0)) + case "int64": + return reflect.TypeOf(int64(0)) + default: + return reflect.TypeOf(int64(0)) + } + + case "number": + switch format { + case "float": + return reflect.TypeOf(float32(0)) + case "double": + return reflect.TypeOf(float64(0)) + } + + case "array": + if items == nil { + return nil + } + itemsType := p.typeForSchema(items.Type, items.Format, items.Items) + if itemsType == nil { + return nil + } + return reflect.MakeSlice(reflect.SliceOf(itemsType), 0, 0).Type() + + case "file": + return reflect.TypeOf(&runtime.File{}).Elem() + + case "object": + return reflect.TypeOf(map[string]interface{}{}) + } + return nil +} + +func (p *untypedParamBinder) allowsMulti() bool { + return p.parameter.In == "query" || p.parameter.In == "formData" +} + +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 cf == "multi" { + if !p.allowsMulti() { + return nil, false, false, errors.InvalidCollectionFormat(name, in, cf) + } + vv, hasKey, _ := values.GetOK(name) + return vv, false, hasKey, nil + } + + v, hk, hv := values.GetOK(name) + if !hv { + return nil, false, hk, nil + } + d, c, e := p.readFormattedSliceFieldValue(v[len(v)-1], target) + return d, c, hk, e + } + + vv, hk, _ := values.GetOK(name) + return vv, false, hk, nil +} + +func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, target reflect.Value) error { + // fmt.Println("binding", p.name, "as", p.Type()) + switch p.parameter.In { + case "query": + data, custom, hasKey, err := p.readValue(runtime.Values(request.URL.Query()), target) + if err != nil { + return err + } + if custom { + return nil + } + + return p.bindValue(data, hasKey, target) + + case "header": + data, custom, hasKey, err := p.readValue(runtime.Values(request.Header), target) + if err != nil { + return err + } + if custom { + return nil + } + return p.bindValue(data, hasKey, target) + + case "path": + data, custom, hasKey, err := p.readValue(routeParams, target) + if err != nil { + return err + } + if custom { + return nil + } + return p.bindValue(data, hasKey, target) + + case "formData": + var err error + var mt string + + mt, _, e := runtime.ContentType(request.Header) + if e != nil { + // because of the interface conversion go thinks the error is not nil + // so we first check for nil and then set the err var if it's not nil + err = e + } + + if err != nil { + return errors.InvalidContentType("", []string{"multipart/form-data", "application/x-www-form-urlencoded"}) + } + + if mt != "multipart/form-data" && mt != "application/x-www-form-urlencoded" { + return errors.InvalidContentType(mt, []string{"multipart/form-data", "application/x-www-form-urlencoded"}) + } + + if mt == "multipart/form-data" { + if err = request.ParseMultipartForm(defaultMaxMemory); err != nil { + return errors.NewParseError(p.Name, p.parameter.In, "", err) + } + } + + if err = request.ParseForm(); err != nil { + return errors.NewParseError(p.Name, p.parameter.In, "", err) + } + + if p.parameter.Type == "file" { + file, header, ffErr := request.FormFile(p.parameter.Name) + if ffErr != nil { + return errors.NewParseError(p.Name, p.parameter.In, "", ffErr) + } + target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header})) + return nil + } + + if request.MultipartForm != nil { + data, custom, hasKey, rvErr := p.readValue(runtime.Values(request.MultipartForm.Value), target) + if rvErr != nil { + return rvErr + } + if custom { + return nil + } + return p.bindValue(data, hasKey, target) + } + data, custom, hasKey, err := p.readValue(runtime.Values(request.PostForm), target) + if err != nil { + return err + } + if custom { + return nil + } + return p.bindValue(data, hasKey, target) + + case "body": + newValue := reflect.New(target.Type()) + if !runtime.HasBody(request) { + if p.parameter.Default != nil { + target.Set(reflect.ValueOf(p.parameter.Default)) + } + + return nil + } + if err := consumer.Consume(request.Body, newValue.Interface()); err != nil { + if err == io.EOF && p.parameter.Default != nil { + target.Set(reflect.ValueOf(p.parameter.Default)) + return nil + } + tpe := p.parameter.Type + if p.parameter.Format != "" { + tpe = p.parameter.Format + } + return errors.InvalidType(p.Name, p.parameter.In, tpe, nil) + } + target.Set(reflect.Indirect(newValue)) + return nil + default: + return errors.New(500, fmt.Sprintf("invalid parameter location %q", p.parameter.In)) + } +} + +func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflect.Value) error { + if p.parameter.Type == "array" { + return p.setSliceFieldValue(target, p.parameter.Default, data, hasKey) + } + var d string + if len(data) > 0 { + d = data[len(data)-1] + } + return p.setFieldValue(target, p.parameter.Default, d, hasKey) +} + +func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue interface{}, data string, hasKey bool) error { + tpe := p.parameter.Type + if p.parameter.Format != "" { + tpe = p.parameter.Format + } + + if (!hasKey || (!p.parameter.AllowEmptyValue && data == "")) && p.parameter.Required && p.parameter.Default == nil { + return errors.Required(p.Name, p.parameter.In) + } + + ok, err := p.tryUnmarshaler(target, defaultValue, data) + if err != nil { + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + if ok { + return nil + } + + defVal := reflect.Zero(target.Type()) + if defaultValue != nil { + defVal = reflect.ValueOf(defaultValue) + } + + if tpe == "byte" { + if data == "" { + if target.CanSet() { + target.SetBytes(defVal.Bytes()) + } + return nil + } + + b, err := base64.StdEncoding.DecodeString(data) + if err != nil { + b, err = base64.URLEncoding.DecodeString(data) + if err != nil { + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + } + if target.CanSet() { + target.SetBytes(b) + } + return nil + } + + switch target.Kind() { + case reflect.Bool: + if data == "" { + if target.CanSet() { + target.SetBool(defVal.Bool()) + } + return nil + } + b, err := swag.ConvertBool(data) + if err != nil { + return err + } + if target.CanSet() { + target.SetBool(b) + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if data == "" { + if target.CanSet() { + rd := defVal.Convert(reflect.TypeOf(int64(0))) + target.SetInt(rd.Int()) + } + return nil + } + i, err := strconv.ParseInt(data, 10, 64) + if err != nil { + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + if target.OverflowInt(i) { + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + if target.CanSet() { + target.SetInt(i) + } + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if data == "" { + if target.CanSet() { + rd := defVal.Convert(reflect.TypeOf(uint64(0))) + target.SetUint(rd.Uint()) + } + return nil + } + u, err := strconv.ParseUint(data, 10, 64) + if err != nil { + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + if target.OverflowUint(u) { + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + if target.CanSet() { + target.SetUint(u) + } + + case reflect.Float32, reflect.Float64: + if data == "" { + if target.CanSet() { + rd := defVal.Convert(reflect.TypeOf(float64(0))) + target.SetFloat(rd.Float()) + } + return nil + } + f, err := strconv.ParseFloat(data, 64) + if err != nil { + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + if target.OverflowFloat(f) { + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + if target.CanSet() { + target.SetFloat(f) + } + + case reflect.String: + value := data + if value == "" { + value = defVal.String() + } + // validate string + if target.CanSet() { + target.SetString(value) + } + + case reflect.Ptr: + if data == "" && defVal.Kind() == reflect.Ptr { + if target.CanSet() { + target.Set(defVal) + } + return nil + } + newVal := reflect.New(target.Type().Elem()) + if err := p.setFieldValue(reflect.Indirect(newVal), defVal, data, hasKey); err != nil { + return err + } + if target.CanSet() { + target.Set(newVal) + } + + default: + return errors.InvalidType(p.Name, p.parameter.In, tpe, data) + } + return nil +} + +func (p *untypedParamBinder) tryUnmarshaler(target reflect.Value, defaultValue interface{}, data string) (bool, error) { + if !target.CanSet() { + return false, nil + } + // When a type implements encoding.TextUnmarshaler we'll use that instead of reflecting some more + if reflect.PtrTo(target.Type()).Implements(textUnmarshalType) { + if defaultValue != nil && len(data) == 0 { + target.Set(reflect.ValueOf(defaultValue)) + return true, nil + } + value := reflect.New(target.Type()) + if err := value.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(data)); err != nil { + return true, err + } + target.Set(reflect.Indirect(value)) + return true, nil + } + return false, nil +} + +func (p *untypedParamBinder) readFormattedSliceFieldValue(data string, target reflect.Value) ([]string, bool, error) { + ok, err := p.tryUnmarshaler(target, p.parameter.Default, data) + if err != nil { + return nil, true, err + } + if ok { + return nil, true, nil + } + + return swag.SplitByFormat(data, p.parameter.CollectionFormat), false, nil +} + +func (p *untypedParamBinder) setSliceFieldValue(target reflect.Value, defaultValue interface{}, data []string, hasKey bool) error { + sz := len(data) + if (!hasKey || (!p.parameter.AllowEmptyValue && (sz == 0 || (sz == 1 && data[0] == "")))) && p.parameter.Required && defaultValue == nil { + return errors.Required(p.Name, p.parameter.In) + } + + defVal := reflect.Zero(target.Type()) + if defaultValue != nil { + defVal = reflect.ValueOf(defaultValue) + } + + if !target.CanSet() { + return nil + } + if sz == 0 { + target.Set(defVal) + return nil + } + + value := reflect.MakeSlice(reflect.SliceOf(target.Type().Elem()), sz, sz) + + for i := 0; i < sz; i++ { + if err := p.setFieldValue(value.Index(i), nil, data[i], hasKey); err != nil { + return err + } + } + + target.Set(value) + + return nil +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/parameter_test.go b/vendor/github.com/go-openapi/runtime/middleware/parameter_test.go new file mode 100644 index 0000000000..d0524ab9ad --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/parameter_test.go @@ -0,0 +1,340 @@ +// 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 middleware + +import ( + "math" + "net/url" + "reflect" + "strconv" + "testing" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +// type email struct { +// Address string +// } + +type paramFactory func(string) *spec.Parameter + +var paramFactories = []paramFactory{ + spec.QueryParam, + spec.HeaderParam, + spec.PathParam, + spec.FormDataParam, +} + +func np(param *spec.Parameter) *untypedParamBinder { + return newUntypedParamBinder(*param, new(spec.Swagger), strfmt.Default) +} + +var stringItems = new(spec.Items) + +func init() { + stringItems.Type = "string" +} + +func testCollectionFormat(t *testing.T, param *spec.Parameter, valid bool) { + binder := &untypedParamBinder{ + parameter: param, + } + _, _, _, err := binder.readValue(runtime.Values(nil), reflect.ValueOf(nil)) + if valid { + assert.NoError(t, err) + } else { + assert.Error(t, err) + assert.Equal(t, errors.InvalidCollectionFormat(param.Name, param.In, param.CollectionFormat), err) + } +} + +func requiredError(param *spec.Parameter) *errors.Validation { + return errors.Required(param.Name, param.In) +} + +func validateRequiredTest(t *testing.T, param *spec.Parameter, value reflect.Value) { + + binder := np(param) + err := binder.bindValue([]string{}, true, value) + assert.Error(t, err) + assert.NotNil(t, param) + assert.EqualError(t, requiredError(param), err.Error()) + err = binder.bindValue([]string{""}, true, value) + if assert.Error(t, err) { + assert.EqualError(t, requiredError(param), err.Error()) + } + + // should be impossible data, but let's go with it + err = binder.bindValue([]string{"a"}, false, value) + assert.Error(t, err) + assert.EqualError(t, requiredError(param), err.Error()) + err = binder.bindValue([]string{""}, false, value) + assert.Error(t, err) + assert.EqualError(t, requiredError(param), err.Error()) +} + +func validateRequiredAllowEmptyTest(t *testing.T, param *spec.Parameter, value reflect.Value) { + param.AllowEmptyValue = true + binder := np(param) + err := binder.bindValue([]string{}, true, value) + assert.NoError(t, err) + if assert.NotNil(t, param) { + err = binder.bindValue([]string{""}, true, value) + assert.NoError(t, err) + err = binder.bindValue([]string{"1"}, false, value) + assert.Error(t, err) + assert.EqualError(t, requiredError(param), err.Error()) + err = binder.bindValue([]string{""}, false, value) + assert.Error(t, err) + assert.EqualError(t, requiredError(param), err.Error()) + } +} + +func TestRequiredValidation(t *testing.T) { + strParam := spec.QueryParam("name").Typed("string", "").AsRequired() + validateRequiredTest(t, strParam, reflect.ValueOf("")) + validateRequiredAllowEmptyTest(t, strParam, reflect.ValueOf("")) + + intParam := spec.QueryParam("id").Typed("integer", "int32").AsRequired() + validateRequiredTest(t, intParam, reflect.ValueOf(int32(0))) + validateRequiredAllowEmptyTest(t, intParam, reflect.ValueOf(int32(0))) + longParam := spec.QueryParam("id").Typed("integer", "int64").AsRequired() + validateRequiredTest(t, longParam, reflect.ValueOf(int64(0))) + validateRequiredAllowEmptyTest(t, longParam, reflect.ValueOf(int64(0))) + + floatParam := spec.QueryParam("score").Typed("number", "float").AsRequired() + validateRequiredTest(t, floatParam, reflect.ValueOf(float32(0))) + validateRequiredAllowEmptyTest(t, floatParam, reflect.ValueOf(float32(0))) + doubleParam := spec.QueryParam("score").Typed("number", "double").AsRequired() + validateRequiredTest(t, doubleParam, reflect.ValueOf(float64(0))) + validateRequiredAllowEmptyTest(t, doubleParam, reflect.ValueOf(float64(0))) + + dateTimeParam := spec.QueryParam("registered").Typed("string", "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() + validateRequiredTest(t, dateParam, reflect.ValueOf(strfmt.Date{})) + // validateRequiredAllowEmptyTest(t, dateParam, reflect.ValueOf(strfmt.DateTime{})) + + sliceParam := spec.QueryParam("tags").CollectionOf(stringItems, "").AsRequired() + validateRequiredTest(t, sliceParam, reflect.MakeSlice(reflect.TypeOf([]string{}), 0, 0)) + validateRequiredAllowEmptyTest(t, sliceParam, reflect.MakeSlice(reflect.TypeOf([]string{}), 0, 0)) +} + +func TestInvalidCollectionFormat(t *testing.T) { + validCf1 := spec.QueryParam("validFmt").CollectionOf(stringItems, "multi") + validCf2 := spec.FormDataParam("validFmt2").CollectionOf(stringItems, "multi") + invalidCf1 := spec.HeaderParam("invalidHdr").CollectionOf(stringItems, "multi") + invalidCf2 := spec.PathParam("invalidPath").CollectionOf(stringItems, "multi") + + testCollectionFormat(t, validCf1, true) + testCollectionFormat(t, validCf2, true) + testCollectionFormat(t, invalidCf1, false) + testCollectionFormat(t, invalidCf2, false) +} + +func invalidTypeError(param *spec.Parameter, data interface{}) *errors.Validation { + tpe := param.Type + if param.Format != "" { + tpe = param.Format + } + return errors.InvalidType(param.Name, param.In, tpe, data) +} + +func TestTypeValidation(t *testing.T) { + for _, newParam := range paramFactories { + intParam := newParam("badInt").Typed("integer", "int32") + value := reflect.ValueOf(int32(0)) + binder := np(intParam) + err := binder.bindValue([]string{"yada"}, true, value) + // fails for invalid string + assert.Error(t, err) + assert.Equal(t, invalidTypeError(intParam, "yada"), err) + // fails for overflow + val := int64(math.MaxInt32) + str := strconv.FormatInt(val, 10) + "0" + v := int32(0) + value = reflect.ValueOf(&v).Elem() + binder = np(intParam) + err = binder.bindValue([]string{str}, true, value) + assert.Error(t, err) + assert.Equal(t, invalidTypeError(intParam, str), err) + + longParam := newParam("badLong").Typed("integer", "int64") + value = reflect.ValueOf(int64(0)) + binder = np(longParam) + err = binder.bindValue([]string{"yada"}, true, value) + // fails for invalid string + assert.Error(t, err) + assert.Equal(t, invalidTypeError(longParam, "yada"), err) + // fails for overflow + str2 := strconv.FormatInt(math.MaxInt64, 10) + "0" + v2 := int64(0) + vv2 := reflect.ValueOf(&v2).Elem() + binder = np(longParam) + err = binder.bindValue([]string{str2}, true, vv2) + assert.Error(t, err) + assert.Equal(t, invalidTypeError(longParam, str2), err) + + floatParam := newParam("badFloat").Typed("number", "float") + value = reflect.ValueOf(float64(0)) + binder = np(floatParam) + err = binder.bindValue([]string{"yada"}, true, value) + // fails for invalid string + assert.Error(t, err) + assert.Equal(t, invalidTypeError(floatParam, "yada"), err) + // fails for overflow + str3 := strconv.FormatFloat(math.MaxFloat64, 'f', 5, 64) + v3 := reflect.TypeOf(float32(0)) + value = reflect.New(v3).Elem() + binder = np(floatParam) + err = binder.bindValue([]string{str3}, true, value) + assert.Error(t, err) + assert.Equal(t, invalidTypeError(floatParam, str3), err) + + doubleParam := newParam("badDouble").Typed("number", "double") + value = reflect.ValueOf(float64(0)) + binder = np(doubleParam) + err = binder.bindValue([]string{"yada"}, true, value) + // fails for invalid string + assert.Error(t, err) + assert.Equal(t, invalidTypeError(doubleParam, "yada"), err) + // fails for overflow + str4 := "9" + strconv.FormatFloat(math.MaxFloat64, 'f', 5, 64) + v4 := reflect.TypeOf(float64(0)) + value = reflect.New(v4).Elem() + binder = np(doubleParam) + err = binder.bindValue([]string{str4}, true, value) + assert.Error(t, err) + assert.Equal(t, invalidTypeError(doubleParam, str4), err) + + dateParam := newParam("badDate").Typed("string", "date") + value = reflect.ValueOf(strfmt.Date{}) + binder = np(dateParam) + err = binder.bindValue([]string{"yada"}, true, value) + // fails for invalid string + assert.Error(t, err) + assert.Equal(t, invalidTypeError(dateParam, "yada"), err) + + dateTimeParam := newParam("badDateTime").Typed("string", "date-time") + value = reflect.ValueOf(strfmt.DateTime{}) + binder = np(dateTimeParam) + err = binder.bindValue([]string{"yada"}, true, value) + // fails for invalid string + assert.Error(t, err) + assert.Equal(t, invalidTypeError(dateTimeParam, "yada"), err) + + byteParam := newParam("badByte").Typed("string", "byte") + values := url.Values(map[string][]string{}) + values.Add("badByte", "yaüda") + v5 := []byte{} + value = reflect.ValueOf(&v5).Elem() + binder = np(byteParam) + err = binder.bindValue([]string{"yaüda"}, true, value) + // fails for invalid string + assert.Error(t, err) + assert.Equal(t, invalidTypeError(byteParam, "yaüda"), err) + } +} + +func TestTypeDetectionInvalidItems(t *testing.T) { + withoutItems := spec.QueryParam("without").CollectionOf(nil, "") + binder := &untypedParamBinder{ + Name: "without", + parameter: withoutItems, + } + assert.Nil(t, binder.Type()) + + items := new(spec.Items) + items.Type = "array" + withInvalidItems := spec.QueryParam("invalidItems").CollectionOf(items, "") + binder = &untypedParamBinder{ + Name: "invalidItems", + parameter: withInvalidItems, + } + assert.Nil(t, binder.Type()) + + noType := spec.QueryParam("invalidType") + noType.Type = "invalid" + binder = &untypedParamBinder{ + Name: "invalidType", + parameter: noType, + } + assert.Nil(t, binder.Type()) +} + +// type emailStrFmt struct { +// name string +// tpe reflect.Type +// validator FormatValidator +// } +// +// func (e *emailStrFmt) Name() string { +// return e.name +// } +// +// func (e *emailStrFmt) Type() reflect.Type { +// return e.tpe +// } +// +// func (e *emailStrFmt) Matches(str string) bool { +// return e.validator(str) +// } +// +// func TestTypeDetectionValid(t *testing.T) { +// // emlFmt := &emailStrFmt{ +// // name: "email", +// // tpe: reflect.TypeOf(email{}), +// // } +// // formats := []StringFormat{emlFmt} +// +// expected := map[string]reflect.Type{ +// "name": reflect.TypeOf(""), +// "id": reflect.TypeOf(int64(0)), +// "age": reflect.TypeOf(int32(0)), +// "score": reflect.TypeOf(float32(0)), +// "factor": reflect.TypeOf(float64(0)), +// "friend": reflect.TypeOf(map[string]interface{}{}), +// "X-Request-Id": reflect.TypeOf(int64(0)), +// "tags": reflect.TypeOf([]string{}), +// "confirmed": reflect.TypeOf(true), +// "planned": reflect.TypeOf(swagger.Date{}), +// "delivered": reflect.TypeOf(swagger.DateTime{}), +// "email": reflect.TypeOf(email{}), +// "picture": reflect.TypeOf([]byte{}), +// "file": reflect.TypeOf(&swagger.File{}).Elem(), +// } +// +// params := parametersForAllTypes("") +// emailParam := spec.QueryParam("email").Typed("string", "email") +// params["email"] = *emailParam +// +// fileParam := spec.FileParam("file") +// params["file"] = *fileParam +// +// for _, v := range params { +// binder := ¶mBinder{ +// formats: formats, +// name: v.Name, +// parameter: &v, +// } +// assert.Equal(t, expected[v.Name], binder.Type(), "name: %s", v.Name) +// } +// } diff --git a/vendor/github.com/go-openapi/runtime/middleware/pre_go18.go b/vendor/github.com/go-openapi/runtime/middleware/pre_go18.go new file mode 100644 index 0000000000..03385251e1 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/pre_go18.go @@ -0,0 +1,9 @@ +// +build !go1.8 + +package middleware + +import "net/url" + +func pathUnescape(path string) (string, error) { + return url.QueryUnescape(path) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/redoc.go b/vendor/github.com/go-openapi/runtime/middleware/redoc.go new file mode 100644 index 0000000000..21277948c0 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/redoc.go @@ -0,0 +1,101 @@ +package middleware + +import ( + "bytes" + "fmt" + "html/template" + "net/http" + "path" +) + +// RedocOpts configures the Redoc middlewares +type RedocOpts struct { + // BasePath for the UI path, defaults to: / + BasePath string + // Path combines with BasePath for the full UI path, defaults to: docs + Path string + // SpecURL the url to find the spec for + SpecURL string + // RedocURL for the js that generates the redoc site, defaults to: https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js + RedocURL string + // Title for the documentation site, default to: API documentation + Title string +} + +// EnsureDefaults in case some options are missing +func (r *RedocOpts) EnsureDefaults() { + if r.BasePath == "" { + r.BasePath = "/" + } + if r.Path == "" { + r.Path = "docs" + } + if r.SpecURL == "" { + r.SpecURL = "/swagger.json" + } + if r.RedocURL == "" { + r.RedocURL = redocLatest + } + if r.Title == "" { + r.Title = "API documentation" + } +} + +// Redoc creates a middleware to serve a documentation site for a swagger spec. +// This allows for altering the spec before starting the http listener. +// +func Redoc(opts RedocOpts, next http.Handler) http.Handler { + opts.EnsureDefaults() + + pth := path.Join(opts.BasePath, opts.Path) + tmpl := template.Must(template.New("redoc").Parse(redocTemplate)) + + buf := bytes.NewBuffer(nil) + _ = tmpl.Execute(buf, opts) + b := buf.Bytes() + + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + if r.URL.Path == pth { + rw.Header().Set("Content-Type", "text/html; charset=utf-8") + rw.WriteHeader(http.StatusOK) + + _, _ = rw.Write(b) + return + } + + if next == nil { + rw.Header().Set("Content-Type", "text/plain") + rw.WriteHeader(http.StatusNotFound) + _, _ = rw.Write([]byte(fmt.Sprintf("%q not found", pth))) + return + } + next.ServeHTTP(rw, r) + }) +} + +const ( + redocLatest = "https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js" + redocTemplate = ` + + + {{ .Title }} + + + + + + + + + + + +` +) diff --git a/vendor/github.com/go-openapi/runtime/middleware/redoc_test.go b/vendor/github.com/go-openapi/runtime/middleware/redoc_test.go new file mode 100644 index 0000000000..cf13da93c1 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/redoc_test.go @@ -0,0 +1,22 @@ +package middleware + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRedocMiddleware(t *testing.T) { + redoc := Redoc(RedocOpts{}, nil) + + req, _ := http.NewRequest("GET", "/docs", nil) + recorder := httptest.NewRecorder() + redoc.ServeHTTP(recorder, req) + assert.Equal(t, 200, 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(), "") + assert.Contains(t, recorder.Body.String(), redocLatest) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/request.go b/vendor/github.com/go-openapi/runtime/middleware/request.go new file mode 100644 index 0000000000..ee725f587a --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/request.go @@ -0,0 +1,104 @@ +// 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 middleware + +import ( + "net/http" + "reflect" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" +) + +// RequestBinder binds and validates the data from a http request +type untypedRequestBinder struct { + Spec *spec.Swagger + Parameters map[string]spec.Parameter + Formats strfmt.Registry + paramBinders map[string]*untypedParamBinder +} + +// NewRequestBinder creates a new binder for reading a request. +func newUntypedRequestBinder(parameters map[string]spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedRequestBinder { + binders := make(map[string]*untypedParamBinder) + for fieldName, param := range parameters { + binders[fieldName] = newUntypedParamBinder(param, spec, formats) + } + return &untypedRequestBinder{ + Parameters: parameters, + paramBinders: binders, + Spec: spec, + Formats: formats, + } +} + +// Bind perform the databinding and validation +func (o *untypedRequestBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, data interface{}) error { + val := reflect.Indirect(reflect.ValueOf(data)) + isMap := val.Kind() == reflect.Map + var result []error + debugLog("binding %d parameters for %s %s", len(o.Parameters), request.Method, request.URL.EscapedPath()) + for fieldName, param := range o.Parameters { + binder := o.paramBinders[fieldName] + debugLog("binding parameter %s for %s %s", fieldName, request.Method, request.URL.EscapedPath()) + var target reflect.Value + if !isMap { + binder.Name = fieldName + target = val.FieldByName(fieldName) + } + + if isMap { + tpe := binder.Type() + if tpe == nil { + if param.Schema.Type.Contains("array") { + tpe = reflect.TypeOf([]interface{}{}) + } else { + tpe = reflect.TypeOf(map[string]interface{}{}) + } + } + target = reflect.Indirect(reflect.New(tpe)) + + } + + if !target.IsValid() { + result = append(result, errors.New(500, "parameter name %q is an unknown field", binder.Name)) + continue + } + + if err := binder.Bind(request, routeParams, consumer, target); err != nil { + result = append(result, err) + continue + } + + if binder.validator != nil { + rr := binder.validator.Validate(target.Interface()) + if rr != nil && rr.HasErrors() { + result = append(result, rr.AsError()) + } + } + + if isMap { + val.SetMapIndex(reflect.ValueOf(param.Name), target) + } + } + + if len(result) > 0 { + return errors.CompositeValidationError(result...) + } + + return nil +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/request_test.go b/vendor/github.com/go-openapi/runtime/middleware/request_test.go new file mode 100644 index 0000000000..395065b808 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/request_test.go @@ -0,0 +1,466 @@ +// 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 middleware + +import ( + "bytes" + "io" + "io/ioutil" + "mime/multipart" + "net/http" + "net/url" + "strings" + "testing" + "time" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +type stubConsumer struct { +} + +func (s *stubConsumer) Consume(_ io.Reader, _ interface{}) error { + return nil +} + +type friend struct { + Name string `json:"name"` + Age int `json:"age"` +} + +type jsonRequestParams struct { + ID int64 // path + Name string // query + Friend friend // body + RequestID int64 // header + Tags []string // csv +} + +type jsonRequestPtr struct { + ID int64 // path + Name string // query + RequestID int64 // header + Tags []string // csv + Friend *friend +} + +type jsonRequestSlice struct { + ID int64 // path + Name string // query + RequestID int64 // header + Tags []string // csv + Friend []friend +} + +func parametersForAllTypes(fmt string) map[string]spec.Parameter { + if fmt == "" { + fmt = "csv" + } + nameParam := spec.QueryParam("name").Typed("string", "") + idParam := spec.PathParam("id").Typed("integer", "int64") + ageParam := spec.QueryParam("age").Typed("integer", "int32") + scoreParam := spec.QueryParam("score").Typed("number", "float") + factorParam := spec.QueryParam("factor").Typed("number", "double") + + friendSchema := new(spec.Schema).Typed("object", "") + friendParam := spec.BodyParam("friend", friendSchema) + + requestIDParam := spec.HeaderParam("X-Request-Id").Typed("integer", "int64") + requestIDParam.Extensions = spec.Extensions(map[string]interface{}{}) + requestIDParam.Extensions.Add("go-name", "RequestID") + + items := new(spec.Items) + items.Type = "string" + 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 + + return map[string]spec.Parameter{ + "ID": *idParam, + "Name": *nameParam, + "RequestID": *requestIDParam, + "Friend": *friendParam, + "Tags": *tagsParam, + "Age": *ageParam, + "Score": *scoreParam, + "Factor": *factorParam, + "Confirmed": *confirmedParam, + "Planned": *plannedParam, + "Delivered": *deliveredParam, + "Picture": *pictureParam, + } +} + +func parametersForJSONRequestParams(fmt string) map[string]spec.Parameter { + if fmt == "" { + fmt = "csv" + } + nameParam := spec.QueryParam("name").Typed("string", "") + idParam := spec.PathParam("id").Typed("integer", "int64") + + friendSchema := new(spec.Schema).Typed("object", "") + friendParam := spec.BodyParam("friend", friendSchema) + + requestIDParam := spec.HeaderParam("X-Request-Id").Typed("integer", "int64") + requestIDParam.Extensions = spec.Extensions(map[string]interface{}{}) + requestIDParam.Extensions.Add("go-name", "RequestID") + + items := new(spec.Items) + items.Type = "string" + tagsParam := spec.QueryParam("tags").CollectionOf(items, fmt) + + return map[string]spec.Parameter{ + "ID": *idParam, + "Name": *nameParam, + "RequestID": *requestIDParam, + "Friend": *friendParam, + "Tags": *tagsParam, + } +} +func parametersForJSONRequestSliceParams(fmt string) map[string]spec.Parameter { + if fmt == "" { + fmt = "csv" + } + nameParam := spec.QueryParam("name").Typed("string", "") + idParam := spec.PathParam("id").Typed("integer", "int64") + + friendSchema := new(spec.Schema).Typed("object", "") + friendParam := spec.BodyParam("friend", spec.ArrayProperty(friendSchema)) + + requestIDParam := spec.HeaderParam("X-Request-Id").Typed("integer", "int64") + requestIDParam.Extensions = spec.Extensions(map[string]interface{}{}) + requestIDParam.Extensions.Add("go-name", "RequestID") + + items := new(spec.Items) + items.Type = "string" + tagsParam := spec.QueryParam("tags").CollectionOf(items, fmt) + + return map[string]spec.Parameter{ + "ID": *idParam, + "Name": *nameParam, + "RequestID": *requestIDParam, + "Friend": *friendParam, + "Tags": *tagsParam, + } +} + +func TestRequestBindingDefaultValue(t *testing.T) { + confirmed := true + name := "thomas" + friend := map[string]interface{}{"name": "toby", "age": float64(32)} + id, age, score, factor := int64(7575), int32(348), float32(5.309), float64(37.403) + requestID := 19394858 + tags := []string{"one", "two", "three"} + dt1 := time.Date(2014, 8, 9, 0, 0, 0, 0, time.UTC) + planned := strfmt.Date(dt1) + dt2 := time.Date(2014, 10, 12, 8, 5, 5, 0, time.UTC) + delivered := strfmt.DateTime(dt2) + uri, _ := url.Parse("http://localhost:8002/hello") + defaults := map[string]interface{}{ + "id": id, + "age": age, + "score": score, + "factor": factor, + "name": name, + "friend": friend, + "X-Request-Id": requestID, + "tags": tags, + "confirmed": confirmed, + "planned": planned, + "delivered": delivered, + "picture": []byte("hello"), + } + op2 := parametersForAllTypes("") + op3 := make(map[string]spec.Parameter) + for k, p := range op2 { + p.Default = defaults[p.Name] + op3[k] = p + } + + req, _ := http.NewRequest("POST", uri.String(), bytes.NewBuffer(nil)) + req.Header.Set("Content-Type", "application/json") + binder := newUntypedRequestBinder(op3, new(spec.Swagger), strfmt.Default) + + data := make(map[string]interface{}) + err := binder.Bind(req, RouteParams(nil), runtime.JSONConsumer(), &data) + assert.NoError(t, err) + assert.Equal(t, defaults["id"], data["id"]) + assert.Equal(t, name, data["name"]) + assert.Equal(t, friend, data["friend"]) + assert.EqualValues(t, requestID, data["X-Request-Id"]) + assert.Equal(t, tags, data["tags"]) + assert.Equal(t, planned, data["planned"]) + assert.Equal(t, delivered, data["delivered"]) + assert.Equal(t, confirmed, data["confirmed"]) + assert.Equal(t, age, data["age"]) + assert.Equal(t, factor, data["factor"]) + assert.Equal(t, score, data["score"]) + assert.Equal(t, "hello", string(data["picture"].(strfmt.Base64))) +} + +func TestRequestBindingForInvalid(t *testing.T) { + + invalidParam := spec.QueryParam("some") + + op1 := map[string]spec.Parameter{"Some": *invalidParam} + + binder := newUntypedRequestBinder(op1, new(spec.Swagger), strfmt.Default) + req, _ := http.NewRequest("GET", "http://localhost:8002/hello?name=the-name", nil) + + err := binder.Bind(req, nil, new(stubConsumer), new(jsonRequestParams)) + assert.Error(t, err) + + op2 := parametersForJSONRequestParams("") + binder = newUntypedRequestBinder(op2, new(spec.Swagger), strfmt.Default) + + req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{"name":"toby","age":32}`))) + req.Header.Set("Content-Type", "application(") + data := jsonRequestParams{} + err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data) + assert.Error(t, err) + + req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{]`))) + req.Header.Set("Content-Type", "application/json") + data = jsonRequestParams{} + err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data) + assert.Error(t, err) + + invalidMultiParam := spec.HeaderParam("tags").CollectionOf(new(spec.Items), "multi") + op3 := map[string]spec.Parameter{"Tags": *invalidMultiParam} + binder = newUntypedRequestBinder(op3, new(spec.Swagger), strfmt.Default) + + req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{}`))) + req.Header.Set("Content-Type", "application/json") + data = jsonRequestParams{} + err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data) + assert.Error(t, err) + + invalidMultiParam = spec.PathParam("").CollectionOf(new(spec.Items), "multi") + + op4 := map[string]spec.Parameter{"Tags": *invalidMultiParam} + binder = newUntypedRequestBinder(op4, new(spec.Swagger), strfmt.Default) + + req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{}`))) + req.Header.Set("Content-Type", "application/json") + data = jsonRequestParams{} + err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data) + assert.Error(t, err) + + invalidInParam := spec.HeaderParam("tags").Typed("string", "") + invalidInParam.In = "invalid" + op5 := map[string]spec.Parameter{"Tags": *invalidInParam} + binder = newUntypedRequestBinder(op5, new(spec.Swagger), strfmt.Default) + + req, _ = http.NewRequest("POST", "http://localhost:8002/hello/1?name=the-name", bytes.NewBuffer([]byte(`{}`))) + req.Header.Set("Content-Type", "application/json") + data = jsonRequestParams{} + err = binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data) + assert.Error(t, err) +} + +func TestRequestBindingForValid(t *testing.T) { + + for _, fmt := range []string{"csv", "pipes", "tsv", "ssv", "multi"} { + op1 := parametersForJSONRequestParams(fmt) + + binder := newUntypedRequestBinder(op1, new(spec.Swagger), strfmt.Default) + + lval := []string{"one", "two", "three"} + var queryString string + switch fmt { + case "multi": + queryString = strings.Join(lval, "&tags=") + case "ssv": + queryString = strings.Join(lval, " ") + case "pipes": + queryString = strings.Join(lval, "|") + case "tsv": + queryString = strings.Join(lval, "\t") + default: + queryString = strings.Join(lval, ",") + } + + urlStr := "http://localhost:8002/hello/1?name=the-name&tags=" + queryString + + req, _ := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(`{"name":"toby","age":32}`))) + req.Header.Set("Content-Type", "application/json;charset=utf-8") + req.Header.Set("X-Request-Id", "1325959595") + + data := jsonRequestParams{} + err := binder.Bind(req, RouteParams([]RouteParam{{"id", "1"}}), runtime.JSONConsumer(), &data) + + expected := jsonRequestParams{ + ID: 1, + Name: "the-name", + Friend: friend{"toby", 32}, + RequestID: 1325959595, + Tags: []string{"one", "two", "three"}, + } + assert.NoError(t, err) + assert.Equal(t, expected, data) + } + + op1 := parametersForJSONRequestParams("") + + binder := newUntypedRequestBinder(op1, new(spec.Swagger), strfmt.Default) + urlStr := "http://localhost:8002/hello/1?name=the-name&tags=one,two,three" + req, _ := http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(`{"name":"toby","age":32}`))) + req.Header.Set("Content-Type", "application/json;charset=utf-8") + req.Header.Set("X-Request-Id", "1325959595") + + data2 := jsonRequestPtr{} + err := binder.Bind(req, []RouteParam{{"id", "1"}}, runtime.JSONConsumer(), &data2) + + expected2 := jsonRequestPtr{ + Friend: &friend{"toby", 32}, + Tags: []string{"one", "two", "three"}, + } + assert.NoError(t, err) + if data2.Friend == nil { + t.Fatal("friend is nil") + } + assert.Equal(t, *expected2.Friend, *data2.Friend) + assert.Equal(t, expected2.Tags, data2.Tags) + + req, _ = http.NewRequest("POST", urlStr, bytes.NewBuffer([]byte(`[{"name":"toby","age":32}]`))) + req.Header.Set("Content-Type", "application/json;charset=utf-8") + req.Header.Set("X-Request-Id", "1325959595") + op2 := parametersForJSONRequestSliceParams("") + binder = newUntypedRequestBinder(op2, new(spec.Swagger), strfmt.Default) + data3 := jsonRequestSlice{} + err = binder.Bind(req, []RouteParam{{"id", "1"}}, runtime.JSONConsumer(), &data3) + + expected3 := jsonRequestSlice{ + Friend: []friend{{"toby", 32}}, + Tags: []string{"one", "two", "three"}, + } + assert.NoError(t, err) + assert.Equal(t, expected3.Friend, data3.Friend) + assert.Equal(t, expected3.Tags, data3.Tags) +} + +type formRequest struct { + Name string + Age int +} + +func parametersForFormUpload() map[string]spec.Parameter { + nameParam := spec.FormDataParam("name").Typed("string", "") + + ageParam := spec.FormDataParam("age").Typed("integer", "int32") + + return map[string]spec.Parameter{"Name": *nameParam, "Age": *ageParam} +} + +func TestFormUpload(t *testing.T) { + params := parametersForFormUpload() + binder := newUntypedRequestBinder(params, new(spec.Swagger), strfmt.Default) + + urlStr := "http://localhost:8002/hello" + req, _ := http.NewRequest("POST", urlStr, bytes.NewBufferString(`name=the-name&age=32`)) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + data := formRequest{} + res := binder.Bind(req, nil, runtime.JSONConsumer(), &data) + assert.NoError(t, res) + assert.Equal(t, "the-name", data.Name) + assert.Equal(t, 32, data.Age) + + req, _ = http.NewRequest("POST", urlStr, bytes.NewBufferString(`name=%3&age=32`)) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + data = formRequest{} + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) +} + +type fileRequest struct { + Name string // body + File runtime.File // upload +} + +func paramsForFileUpload() *untypedRequestBinder { + nameParam := spec.FormDataParam("name").Typed("string", "") + + fileParam := spec.FileParam("file") + + params := map[string]spec.Parameter{"Name": *nameParam, "File": *fileParam} + return newUntypedRequestBinder(params, new(spec.Swagger), strfmt.Default) +} + +func TestBindingFileUpload(t *testing.T) { + binder := paramsForFileUpload() + + body := bytes.NewBuffer(nil) + writer := multipart.NewWriter(body) + part, err := writer.CreateFormFile("file", "plain-jane.txt") + assert.NoError(t, err) + + _, _ = part.Write([]byte("the file contents")) + _ = writer.WriteField("name", "the-name") + assert.NoError(t, writer.Close()) + + urlStr := "http://localhost:8002/hello" + req, _ := http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", writer.FormDataContentType()) + + data := fileRequest{} + assert.NoError(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + assert.Equal(t, "the-name", data.Name) + assert.NotNil(t, data.File) + assert.NotNil(t, data.File.Header) + assert.Equal(t, "plain-jane.txt", data.File.Header.Filename) + + bb, err := ioutil.ReadAll(data.File.Data) + assert.NoError(t, err) + assert.Equal(t, []byte("the file contents"), bb) + + req, _ = http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", "application/json") + data = fileRequest{} + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + + req, _ = http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", "application(") + data = fileRequest{} + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + + body = bytes.NewBuffer(nil) + writer = multipart.NewWriter(body) + part, err = writer.CreateFormFile("bad-name", "plain-jane.txt") + assert.NoError(t, err) + + _, _ = part.Write([]byte("the file contents")) + _ = writer.WriteField("name", "the-name") + assert.NoError(t, writer.Close()) + req, _ = http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", writer.FormDataContentType()) + + data = fileRequest{} + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + + req, _ = http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", writer.FormDataContentType()) + _, _ = req.MultipartReader() + + data = fileRequest{} + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/route_param_test.go b/vendor/github.com/go-openapi/runtime/middleware/route_param_test.go new file mode 100644 index 0000000000..78c92b654e --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/route_param_test.go @@ -0,0 +1,38 @@ +// 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 middleware + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRouteParams(t *testing.T) { + coll1 := RouteParams([]RouteParam{ + {"blah", "foo"}, + {"abc", "bar"}, + {"ccc", "efg"}, + }) + + v := coll1.Get("blah") + assert.Equal(t, v, "foo") + v2 := coll1.Get("abc") + assert.Equal(t, v2, "bar") + v3 := coll1.Get("ccc") + assert.Equal(t, v3, "efg") + v4 := coll1.Get("ydkdk") + assert.Empty(t, v4) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/router.go b/vendor/github.com/go-openapi/runtime/middleware/router.go new file mode 100644 index 0000000000..6ae4905086 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/router.go @@ -0,0 +1,270 @@ +// 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 middleware + +import ( + "net/http" + fpath "path" + "regexp" + "strings" + + "github.com/go-openapi/analysis" + "github.com/go-openapi/errors" + "github.com/go-openapi/loads" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware/denco" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" +) + +// RouteParam is a object to capture route params in a framework agnostic way. +// implementations of the muxer should use these route params to communicate with the +// swagger framework +type RouteParam struct { + Name string + Value string +} + +// RouteParams the collection of route params +type RouteParams []RouteParam + +// Get gets the value for the route param for the specified key +func (r RouteParams) Get(name string) string { + vv, _, _ := r.GetOK(name) + if len(vv) > 0 { + return vv[len(vv)-1] + } + return "" +} + +// GetOK gets the value but also returns booleans to indicate if a key or value +// is present. This aids in validation and satisfies an interface in use there +// +// The returned values are: data, has key, has value +func (r RouteParams) GetOK(name string) ([]string, bool, bool) { + for _, p := range r { + if p.Name == name { + return []string{p.Value}, true, p.Value != "" + } + } + return nil, false, false +} + +// NewRouter creates a new context aware router middleware +func NewRouter(ctx *Context, next http.Handler) http.Handler { + if ctx.router == nil { + ctx.router = DefaultRouter(ctx.spec, ctx.api) + } + + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + if _, rCtx, ok := ctx.RouteInfo(r); ok { + next.ServeHTTP(rw, rCtx) + return + } + + // Not found, check if it exists in the other methods first + if others := ctx.AllowedMethods(r); len(others) > 0 { + ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.MethodNotAllowed(r.Method, others)) + return + } + + ctx.Respond(rw, r, ctx.analyzer.RequiredProduces(), nil, errors.NotFound("path %s was not found", r.URL.EscapedPath())) + }) +} + +// RoutableAPI represents an interface for things that can serve +// as a provider of implementations for the swagger router +type RoutableAPI interface { + HandlerFor(string, string) (http.Handler, bool) + ServeErrorFor(string) func(http.ResponseWriter, *http.Request, error) + ConsumersFor([]string) map[string]runtime.Consumer + ProducersFor([]string) map[string]runtime.Producer + AuthenticatorsFor(map[string]spec.SecurityScheme) map[string]runtime.Authenticator + Authorizer() runtime.Authorizer + Formats() strfmt.Registry + DefaultProduces() string + DefaultConsumes() string +} + +// Router represents a swagger aware router +type Router interface { + Lookup(method, path string) (*MatchedRoute, bool) + OtherMethods(method, path string) []string +} + +type defaultRouteBuilder struct { + spec *loads.Document + analyzer *analysis.Spec + api RoutableAPI + records map[string][]denco.Record +} + +type defaultRouter struct { + spec *loads.Document + routers map[string]*denco.Router +} + +func newDefaultRouteBuilder(spec *loads.Document, api RoutableAPI) *defaultRouteBuilder { + return &defaultRouteBuilder{ + spec: spec, + analyzer: analysis.New(spec.Spec()), + api: api, + records: make(map[string][]denco.Record), + } +} + +// DefaultRouter creates a default implemenation of the router +func DefaultRouter(spec *loads.Document, api RoutableAPI) Router { + builder := newDefaultRouteBuilder(spec, api) + if spec != nil { + for method, paths := range builder.analyzer.Operations() { + for path, operation := range paths { + fp := fpath.Join(spec.BasePath(), path) + debugLog("adding route %s %s %q", method, fp, operation.ID) + builder.AddRoute(method, fp, operation) + } + } + } + return builder.Build() +} + +type routeEntry struct { + PathPattern string + BasePath string + Operation *spec.Operation + Consumes []string + Consumers map[string]runtime.Consumer + Produces []string + Producers map[string]runtime.Producer + Parameters map[string]spec.Parameter + Handler http.Handler + Formats strfmt.Registry + Binder *untypedRequestBinder + Authenticators map[string]runtime.Authenticator + Authorizer runtime.Authorizer + Scopes map[string][]string +} + +// MatchedRoute represents the route that was matched in this request +type MatchedRoute struct { + routeEntry + Params RouteParams + Consumer runtime.Consumer + Producer runtime.Producer +} + +func (d *defaultRouter) Lookup(method, path string) (*MatchedRoute, bool) { + mth := strings.ToUpper(method) + debugLog("looking up route for %s %s", method, path) + if Debug { + if len(d.routers) == 0 { + debugLog("there are no known routers") + } + for meth := range d.routers { + debugLog("got a router for %s", meth) + } + } + if router, ok := d.routers[mth]; ok { + if m, rp, ok := router.Lookup(fpath.Clean(path)); ok && m != nil { + if entry, ok := m.(*routeEntry); ok { + debugLog("found a route for %s %s with %d parameters", method, path, len(entry.Parameters)) + var params RouteParams + for _, p := range rp { + v, err := pathUnescape(p.Value) + if err != nil { + debugLog("failed to escape %q: %v", p.Value, err) + v = p.Value + } + params = append(params, RouteParam{Name: p.Name, Value: v}) + } + return &MatchedRoute{routeEntry: *entry, Params: params}, true + } + } else { + debugLog("couldn't find a route by path for %s %s", method, path) + } + } else { + debugLog("couldn't find a route by method for %s %s", method, path) + } + return nil, false +} + +func (d *defaultRouter) OtherMethods(method, path string) []string { + mn := strings.ToUpper(method) + var methods []string + for k, v := range d.routers { + if k != mn { + if _, _, ok := v.Lookup(fpath.Clean(path)); ok { + methods = append(methods, k) + continue + } + } + } + return methods +} + +var pathConverter = regexp.MustCompile(`{(.+?)}`) + +func (d *defaultRouteBuilder) AddRoute(method, path string, operation *spec.Operation) { + mn := strings.ToUpper(method) + + bp := fpath.Clean(d.spec.BasePath()) + if len(bp) > 0 && bp[len(bp)-1] == '/' { + bp = bp[:len(bp)-1] + } + + debugLog("operation: %#v", *operation) + if handler, ok := d.api.HandlerFor(method, strings.TrimPrefix(path, bp)); ok { + consumes := d.analyzer.ConsumesFor(operation) + produces := d.analyzer.ProducesFor(operation) + parameters := d.analyzer.ParamsFor(method, strings.TrimPrefix(path, bp)) + definitions := d.analyzer.SecurityDefinitionsFor(operation) + requirements := d.analyzer.SecurityRequirementsFor(operation) + scopes := make(map[string][]string, len(requirements)) + for _, v := range requirements { + scopes[v.Name] = v.Scopes + } + + record := denco.NewRecord(pathConverter.ReplaceAllString(path, ":$1"), &routeEntry{ + BasePath: bp, + PathPattern: path, + Operation: operation, + Handler: handler, + Consumes: consumes, + Produces: produces, + Consumers: d.api.ConsumersFor(normalizeOffers(consumes)), + Producers: d.api.ProducersFor(normalizeOffers(produces)), + Parameters: parameters, + Formats: d.api.Formats(), + Binder: newUntypedRequestBinder(parameters, d.spec.Spec(), d.api.Formats()), + Authenticators: d.api.AuthenticatorsFor(definitions), + Authorizer: d.api.Authorizer(), + Scopes: scopes, + }) + d.records[mn] = append(d.records[mn], record) + } +} + +func (d *defaultRouteBuilder) Build() *defaultRouter { + routers := make(map[string]*denco.Router) + for method, records := range d.records { + router := denco.New() + _ = router.Build(records) + routers[method] = router + } + return &defaultRouter{ + spec: d.spec, + routers: routers, + } +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/router_test.go b/vendor/github.com/go-openapi/runtime/middleware/router_test.go new file mode 100644 index 0000000000..fd73891f0d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/router_test.go @@ -0,0 +1,227 @@ +// 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 middleware + +import ( + "net/http" + "net/http/httptest" + "sort" + "strings" + "testing" + + "github.com/go-openapi/analysis" + "github.com/go-openapi/loads" + "github.com/go-openapi/runtime/internal/testing/petstore" + "github.com/go-openapi/runtime/middleware/untyped" + "github.com/stretchr/testify/assert" +) + +func terminator(rw http.ResponseWriter, r *http.Request) { + rw.WriteHeader(http.StatusOK) +} + +func TestRouterMiddleware(t *testing.T) { + spec, api := petstore.NewAPI(t) + context := NewContext(spec, api, nil) + mw := NewRouter(context, http.HandlerFunc(terminator)) + + recorder := httptest.NewRecorder() + request, _ := http.NewRequest("GET", "/api/pets", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("DELETE", "/api/pets", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusMethodNotAllowed, recorder.Code) + + methods := strings.Split(recorder.Header().Get("Allow"), ",") + sort.Sort(sort.StringSlice(methods)) + assert.Equal(t, "GET,POST", strings.Join(methods, ",")) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "/nopets", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusNotFound, recorder.Code) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "/pets", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusNotFound, recorder.Code) + + spec, api = petstore.NewRootAPI(t) + context = NewContext(spec, api, nil) + mw = NewRouter(context, http.HandlerFunc(terminator)) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "/pets", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("DELETE", "/pets", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusMethodNotAllowed, recorder.Code) + + methods = strings.Split(recorder.Header().Get("Allow"), ",") + sort.Sort(sort.StringSlice(methods)) + assert.Equal(t, "GET,POST", strings.Join(methods, ",")) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "/nopets", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusNotFound, recorder.Code) + +} + +func TestRouterBuilder(t *testing.T) { + spec, api := petstore.NewAPI(t) + analyzed := analysis.New(spec.Spec()) + + assert.Len(t, analyzed.RequiredConsumes(), 3) + assert.Len(t, analyzed.RequiredProduces(), 5) + assert.Len(t, analyzed.OperationIDs(), 4) + + // context := NewContext(spec, api) + builder := petAPIRouterBuilder(spec, api, analyzed) + getRecords := builder.records["GET"] + postRecords := builder.records["POST"] + deleteRecords := builder.records["DELETE"] + + assert.Len(t, getRecords, 2) + assert.Len(t, postRecords, 1) + assert.Len(t, deleteRecords, 1) + + assert.Empty(t, builder.records["PATCH"]) + assert.Empty(t, builder.records["OPTIONS"]) + assert.Empty(t, builder.records["HEAD"]) + assert.Empty(t, builder.records["PUT"]) + + rec := postRecords[0] + assert.Equal(t, rec.Key, "/pets") + val := rec.Value.(*routeEntry) + assert.Len(t, val.Consumers, 1) + assert.Len(t, val.Producers, 1) + assert.Len(t, val.Consumes, 1) + assert.Len(t, val.Produces, 1) + + assert.Len(t, val.Parameters, 1) + + recG := getRecords[0] + assert.Equal(t, recG.Key, "/pets") + valG := recG.Value.(*routeEntry) + assert.Len(t, valG.Consumers, 2) + assert.Len(t, valG.Producers, 4) + assert.Len(t, valG.Consumes, 2) + assert.Len(t, valG.Produces, 4) + + assert.Len(t, valG.Parameters, 2) +} + +func TestRouterCanonicalBasePath(t *testing.T) { + spec, api := petstore.NewAPI(t) + spec.Spec().BasePath = "/api///" + context := NewContext(spec, api, nil) + mw := NewRouter(context, http.HandlerFunc(terminator)) + + recorder := httptest.NewRecorder() + request, _ := http.NewRequest("GET", "/api/pets", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) +} + +func TestRouter_EscapedPath(t *testing.T) { + spec, api := petstore.NewAPI(t) + spec.Spec().BasePath = "/api/" + context := NewContext(spec, api, nil) + mw := NewRouter(context, http.HandlerFunc(terminator)) + + recorder := httptest.NewRecorder() + request, _ := http.NewRequest("GET", "/api/pets/123", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "/api/pets/abc%2Fdef", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + ri, _, _ := context.RouteInfo(request) + if assert.NotNil(t, ri) { + if assert.NotNil(t, ri.Params) { + assert.Equal(t, "abc/def", ri.Params.Get("id")) + } + } +} + +func TestRouterStruct(t *testing.T) { + spec, api := petstore.NewAPI(t) + router := DefaultRouter(spec, newRoutableUntypedAPI(spec, api, new(Context))) + + methods := router.OtherMethods("post", "/api/pets/{id}") + assert.Len(t, methods, 2) + + entry, ok := router.Lookup("delete", "/api/pets/{id}") + assert.True(t, ok) + assert.NotNil(t, entry) + assert.Len(t, entry.Params, 1) + assert.Equal(t, "id", entry.Params[0].Name) + + _, ok = router.Lookup("delete", "/pets") + assert.False(t, ok) + + _, ok = router.Lookup("post", "/no-pets") + assert.False(t, ok) +} + +func petAPIRouterBuilder(spec *loads.Document, api *untyped.API, analyzed *analysis.Spec) *defaultRouteBuilder { + builder := newDefaultRouteBuilder(spec, newRoutableUntypedAPI(spec, api, new(Context))) + builder.AddRoute("GET", "/pets", analyzed.AllPaths()["/pets"].Get) + builder.AddRoute("POST", "/pets", analyzed.AllPaths()["/pets"].Post) + builder.AddRoute("DELETE", "/pets/{id}", analyzed.AllPaths()["/pets/{id}"].Delete) + builder.AddRoute("GET", "/pets/{id}", analyzed.AllPaths()["/pets/{id}"].Get) + + return builder +} + +func TestPathConverter(t *testing.T) { + cases := []struct { + swagger string + denco string + }{ + {"/", "/"}, + {"/something", "/something"}, + {"/{id}", "/:id"}, + {"/{id}/something/{anotherId}", "/:id/something/:anotherId"}, + {"/{petid}", "/:petid"}, + {"/{pet_id}", "/:pet_id"}, + {"/{petId}", "/:petId"}, + {"/{pet-id}", "/:pet-id"}, + } + + for _, tc := range cases { + actual := pathConverter.ReplaceAllString(tc.swagger, ":$1") + assert.Equal(t, tc.denco, actual, "expected swagger path %s to match %s but got %s", tc.swagger, tc.denco, actual) + } +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/security.go b/vendor/github.com/go-openapi/runtime/middleware/security.go new file mode 100644 index 0000000000..399058310a --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/security.go @@ -0,0 +1,39 @@ +// 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 middleware + +import "net/http" + +func newSecureAPI(ctx *Context, next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := ctx.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + if route != nil && len(route.Authenticators) == 0 { + next.ServeHTTP(rw, r) + return + } + + _, rCtx, err := ctx.Authorize(r, route) + if err != nil { + ctx.Respond(rw, r, route.Produces, route, err) + return + } + r = rCtx + + next.ServeHTTP(rw, r) + }) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/security_test.go b/vendor/github.com/go-openapi/runtime/middleware/security_test.go new file mode 100644 index 0000000000..7c283fa705 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/security_test.go @@ -0,0 +1,58 @@ +// 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 middleware + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-openapi/runtime/internal/testing/petstore" + "github.com/stretchr/testify/assert" +) + +func TestSecurityMiddleware(t *testing.T) { + spec, api := petstore.NewAPI(t) + context := NewContext(spec, api, nil) + context.router = DefaultRouter(spec, context.api) + mw := newSecureAPI(context, http.HandlerFunc(terminator)) + + recorder := httptest.NewRecorder() + request, _ := http.NewRequest("GET", "/api/pets", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 401, recorder.Code) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "/api/pets", nil) + request.SetBasicAuth("admin", "wrong") + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 401, recorder.Code) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "/api/pets", nil) + request.SetBasicAuth("admin", "admin") + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("GET", "//apipets/1", nil) + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/spec.go b/vendor/github.com/go-openapi/runtime/middleware/spec.go new file mode 100644 index 0000000000..72bc5643ad --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/spec.go @@ -0,0 +1,47 @@ +// 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 middleware + +import ( + "net/http" + "path" +) + +// Spec creates a middleware to serve a swagger spec. +// This allows for altering the spec before starting the http listener. +// This can be useful if you want to serve the swagger spec from another path than /swagger.json +// +func Spec(basePath string, b []byte, next http.Handler) http.Handler { + if basePath == "" { + basePath = "/" + } + pth := path.Join(basePath, "swagger.json") + + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + if r.URL.Path == pth { + rw.Header().Set("Content-Type", "application/json") + rw.WriteHeader(http.StatusOK) + _, _ = rw.Write(b) + return + } + + if next == nil { + rw.Header().Set("Content-Type", "application/json") + rw.WriteHeader(http.StatusNotFound) + return + } + next.ServeHTTP(rw, r) + }) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/spec_test.go b/vendor/github.com/go-openapi/runtime/middleware/spec_test.go new file mode 100644 index 0000000000..822a7a6ad4 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/spec_test.go @@ -0,0 +1,56 @@ +// 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 middleware + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/internal/testing/petstore" + "github.com/stretchr/testify/assert" +) + +func TestServeSpecMiddleware(t *testing.T) { + spec, api := petstore.NewAPI(t) + ctx := NewContext(spec, api, nil) + + handler := Spec("", ctx.spec.Raw(), nil) + // serves spec + request, _ := http.NewRequest("GET", "/swagger.json", nil) + request.Header.Add(runtime.HeaderContentType, runtime.JSONMime) + recorder := httptest.NewRecorder() + handler.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + + // returns 404 when no next handler + request, _ = http.NewRequest("GET", "/api/pets", nil) + request.Header.Add(runtime.HeaderContentType, runtime.JSONMime) + recorder = httptest.NewRecorder() + handler.ServeHTTP(recorder, request) + assert.Equal(t, 404, recorder.Code) + + // forwards to next handler for other url + handler = Spec("", ctx.spec.Raw(), http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.WriteHeader(http.StatusOK) + })) + request, _ = http.NewRequest("GET", "/api/pets", nil) + request.Header.Add(runtime.HeaderContentType, runtime.JSONMime) + recorder = httptest.NewRecorder() + handler.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code) + +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/string_conversion_test.go b/vendor/github.com/go-openapi/runtime/middleware/string_conversion_test.go new file mode 100644 index 0000000000..c0ee01614e --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/string_conversion_test.go @@ -0,0 +1,301 @@ +// 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 middleware + +import ( + "errors" + "reflect" + "strings" + "testing" + "time" + + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/stretchr/testify/assert" +) + +var evaluatesAsTrue = []string{"true", "1", "yes", "ok", "y", "on", "selected", "checked", "t", "enabled"} + +type unmarshallerSlice []string + +func (u *unmarshallerSlice) UnmarshalText(data []byte) error { + if len(data) == 0 { + return errors.New("an error") + } + *u = strings.Split(string(data), ",") + return nil +} + +type SomeOperationParams struct { + Name string + ID int64 + Confirmed bool + Age int + Visits int32 + Count int16 + Seq int8 + UID uint64 + UAge uint + UVisits uint32 + UCount uint16 + USeq uint8 + Score float32 + Rate float64 + Timestamp strfmt.DateTime + Birthdate strfmt.Date + LastFailure *strfmt.DateTime + Unsupported struct{} + Tags []string + Prefs []int32 + Categories unmarshallerSlice +} + +func FloatParamTest(t *testing.T, fName, pName, format string, val reflect.Value, defVal, expectedDef interface{}, actual func() interface{}) { + fld := val.FieldByName(pName) + binder := &untypedParamBinder{ + parameter: spec.QueryParam(pName).Typed("number", "double").WithDefault(defVal), + Name: pName, + } + + err := binder.setFieldValue(fld, defVal, "5", true) + assert.NoError(t, err) + assert.EqualValues(t, 5, actual()) + + err = binder.setFieldValue(fld, defVal, "", true) + assert.NoError(t, err) + assert.EqualValues(t, expectedDef, actual()) + + err = binder.setFieldValue(fld, defVal, "yada", true) + assert.Error(t, err) +} + +func IntParamTest(t *testing.T, pName string, val reflect.Value, defVal, expectedDef interface{}, actual func() interface{}) { + fld := val.FieldByName(pName) + + binder := &untypedParamBinder{ + parameter: spec.QueryParam(pName).Typed("integer", "int64").WithDefault(defVal), + Name: pName, + } + err := binder.setFieldValue(fld, defVal, "5", true) + assert.NoError(t, err) + assert.EqualValues(t, 5, actual()) + + err = binder.setFieldValue(fld, defVal, "", true) + assert.NoError(t, err) + assert.EqualValues(t, expectedDef, actual()) + + err = binder.setFieldValue(fld, defVal, "yada", true) + assert.Error(t, err) +} + +func TestParamBinding(t *testing.T) { + + actual := new(SomeOperationParams) + val := reflect.ValueOf(actual).Elem() + pName := "Name" + fld := val.FieldByName(pName) + + binder := &untypedParamBinder{ + parameter: spec.QueryParam(pName).Typed("string", "").WithDefault("some-name"), + Name: pName, + } + + err := binder.setFieldValue(fld, "some-name", "the name value", true) + assert.NoError(t, err) + assert.Equal(t, "the name value", actual.Name) + + err = binder.setFieldValue(fld, "some-name", "", true) + assert.NoError(t, err) + assert.Equal(t, "some-name", actual.Name) + + IntParamTest(t, "ID", val, 1, 1, func() interface{} { return actual.ID }) + IntParamTest(t, "ID", val, nil, 0, func() interface{} { return actual.ID }) + IntParamTest(t, "Age", val, 1, 1, func() interface{} { return actual.Age }) + IntParamTest(t, "Age", val, nil, 0, func() interface{} { return actual.Age }) + IntParamTest(t, "Visits", val, 1, 1, func() interface{} { return actual.Visits }) + IntParamTest(t, "Visits", val, nil, 0, func() interface{} { return actual.Visits }) + IntParamTest(t, "Count", val, 1, 1, func() interface{} { return actual.Count }) + IntParamTest(t, "Count", val, nil, 0, func() interface{} { return actual.Count }) + IntParamTest(t, "Seq", val, 1, 1, func() interface{} { return actual.Seq }) + IntParamTest(t, "Seq", val, nil, 0, func() interface{} { return actual.Seq }) + IntParamTest(t, "UID", val, uint64(1), 1, func() interface{} { return actual.UID }) + IntParamTest(t, "UID", val, uint64(0), 0, func() interface{} { return actual.UID }) + IntParamTest(t, "UAge", val, uint(1), 1, func() interface{} { return actual.UAge }) + IntParamTest(t, "UAge", val, nil, 0, func() interface{} { return actual.UAge }) + IntParamTest(t, "UVisits", val, uint32(1), 1, func() interface{} { return actual.UVisits }) + IntParamTest(t, "UVisits", val, nil, 0, func() interface{} { return actual.UVisits }) + IntParamTest(t, "UCount", val, uint16(1), 1, func() interface{} { return actual.UCount }) + IntParamTest(t, "UCount", val, nil, 0, func() interface{} { return actual.UCount }) + IntParamTest(t, "USeq", val, uint8(1), 1, func() interface{} { return actual.USeq }) + IntParamTest(t, "USeq", val, nil, 0, func() interface{} { return actual.USeq }) + + FloatParamTest(t, "score", "Score", "float", val, 1.0, 1, func() interface{} { return actual.Score }) + FloatParamTest(t, "score", "Score", "float", val, nil, 0, func() interface{} { return actual.Score }) + FloatParamTest(t, "rate", "Rate", "double", val, 1.0, 1, func() interface{} { return actual.Rate }) + FloatParamTest(t, "rate", "Rate", "double", val, nil, 0, func() interface{} { return actual.Rate }) + + pName = "Confirmed" + confirmedField := val.FieldByName(pName) + binder = &untypedParamBinder{ + parameter: spec.QueryParam(pName).Typed("boolean", "").WithDefault(true), + Name: pName, + } + + for _, tv := range evaluatesAsTrue { + err = binder.setFieldValue(confirmedField, true, tv, true) + assert.NoError(t, err) + assert.True(t, actual.Confirmed) + } + + err = binder.setFieldValue(confirmedField, true, "", true) + assert.NoError(t, err) + assert.True(t, actual.Confirmed) + + err = binder.setFieldValue(confirmedField, true, "0", true) + assert.NoError(t, err) + assert.False(t, actual.Confirmed) + + pName = "Timestamp" + 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), + Name: pName, + } + exp := strfmt.DateTime(time.Date(2014, 5, 14, 2, 9, 0, 0, time.UTC)) + + err = binder.setFieldValue(timeField, dt, exp.String(), true) + assert.NoError(t, err) + assert.Equal(t, exp, actual.Timestamp) + + err = binder.setFieldValue(timeField, dt, "", true) + assert.NoError(t, err) + assert.Equal(t, dt, actual.Timestamp) + + err = binder.setFieldValue(timeField, dt, "yada", true) + assert.Error(t, err) + + ddt := strfmt.Date(time.Date(2014, 3, 19, 0, 0, 0, 0, time.UTC)) + pName = "Birthdate" + dateField := val.FieldByName(pName) + binder = &untypedParamBinder{ + parameter: spec.QueryParam(pName).Typed("string", "date").WithDefault(ddt), + Name: pName, + } + expd := strfmt.Date(time.Date(2014, 5, 14, 0, 0, 0, 0, time.UTC)) + + err = binder.setFieldValue(dateField, ddt, expd.String(), true) + assert.NoError(t, err) + assert.Equal(t, expd, actual.Birthdate) + + err = binder.setFieldValue(dateField, ddt, "", true) + assert.NoError(t, err) + assert.Equal(t, ddt, actual.Birthdate) + + err = binder.setFieldValue(dateField, ddt, "yada", true) + assert.Error(t, err) + + dt = strfmt.DateTime(time.Date(2014, 3, 19, 2, 9, 0, 0, time.UTC)) + fdt := &dt + pName = "LastFailure" + ftimeField := val.FieldByName(pName) + binder = &untypedParamBinder{ + parameter: spec.QueryParam(pName).Typed("string", "date").WithDefault(fdt), + Name: pName, + } + exp = strfmt.DateTime(time.Date(2014, 5, 14, 2, 9, 0, 0, time.UTC)) + fexp := &exp + + err = binder.setFieldValue(ftimeField, fdt, fexp.String(), true) + assert.NoError(t, err) + assert.Equal(t, fexp, actual.LastFailure) + + err = binder.setFieldValue(ftimeField, fdt, "", true) + assert.NoError(t, err) + assert.Equal(t, fdt, actual.LastFailure) + + err = binder.setFieldValue(ftimeField, fdt, "", true) + assert.NoError(t, err) + assert.Equal(t, fdt, actual.LastFailure) + + actual.LastFailure = nil + err = binder.setFieldValue(ftimeField, fdt, "yada", true) + assert.Error(t, err) + assert.Nil(t, actual.LastFailure) + + pName = "Unsupported" + unsupportedField := val.FieldByName(pName) + binder = &untypedParamBinder{ + parameter: spec.QueryParam(pName).Typed("string", ""), + Name: pName, + } + err = binder.setFieldValue(unsupportedField, nil, "", true) + assert.Error(t, err) +} + +func TestSliceConversion(t *testing.T) { + + actual := new(SomeOperationParams) + val := reflect.ValueOf(actual).Elem() + + // prefsField := val.FieldByName("Prefs") + // cData := "yada,2,3" + // _, _, err := readFormattedSliceFieldValue("Prefs", prefsField, cData, "csv", nil) + // assert.Error(t, err) + + sliced := []string{"some", "string", "values"} + seps := map[string]string{"ssv": " ", "tsv": "\t", "pipes": "|", "csv": ",", "": ","} + + tagsField := val.FieldByName("Tags") + for k, sep := range seps { + binder := &untypedParamBinder{ + Name: "Tags", + parameter: spec.QueryParam("tags").CollectionOf(stringItems, k), + } + + actual.Tags = nil + cData := strings.Join(sliced, sep) + tags, _, err := binder.readFormattedSliceFieldValue(cData, tagsField) + assert.NoError(t, err) + assert.Equal(t, sliced, tags) + cData = strings.Join(sliced, " "+sep+" ") + tags, _, err = binder.readFormattedSliceFieldValue(cData, tagsField) + assert.NoError(t, err) + assert.Equal(t, sliced, tags) + tags, _, err = binder.readFormattedSliceFieldValue("", tagsField) + assert.NoError(t, err) + assert.Empty(t, tags) + } + + assert.Nil(t, swag.SplitByFormat("yada", "multi")) + assert.Nil(t, swag.SplitByFormat("", "")) + + categoriesField := val.FieldByName("Categories") + binder := &untypedParamBinder{ + Name: "Categories", + parameter: spec.QueryParam("categories").CollectionOf(stringItems, "csv"), + } + cData := strings.Join(sliced, ",") + categories, custom, err := binder.readFormattedSliceFieldValue(cData, categoriesField) + assert.NoError(t, err) + assert.EqualValues(t, sliced, actual.Categories) + assert.True(t, custom) + assert.Empty(t, categories) + categories, custom, err = binder.readFormattedSliceFieldValue("", categoriesField) + assert.Error(t, err) + assert.True(t, custom) + assert.Empty(t, categories) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go b/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go new file mode 100644 index 0000000000..3b0cd4e285 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/untyped/api.go @@ -0,0 +1,286 @@ +// 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 ( + "fmt" + "net/http" + "sort" + "strings" + + "github.com/go-openapi/analysis" + "github.com/go-openapi/errors" + "github.com/go-openapi/loads" + "github.com/go-openapi/runtime" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" +) + +// NewAPI creates the default untyped API +func NewAPI(spec *loads.Document) *API { + var an *analysis.Spec + if spec != nil && spec.Spec() != nil { + an = analysis.New(spec.Spec()) + } + api := &API{ + spec: spec, + analyzer: an, + consumers: make(map[string]runtime.Consumer, 10), + producers: make(map[string]runtime.Producer, 10), + authenticators: make(map[string]runtime.Authenticator), + operations: make(map[string]map[string]runtime.OperationHandler), + ServeError: errors.ServeError, + Models: make(map[string]func() interface{}), + formats: strfmt.NewFormats(), + } + return api.WithJSONDefaults() +} + +// API represents an untyped mux for a swagger spec +type API struct { + spec *loads.Document + analyzer *analysis.Spec + DefaultProduces string + DefaultConsumes string + consumers map[string]runtime.Consumer + producers map[string]runtime.Producer + authenticators map[string]runtime.Authenticator + authorizer runtime.Authorizer + operations map[string]map[string]runtime.OperationHandler + ServeError func(http.ResponseWriter, *http.Request, error) + Models map[string]func() interface{} + formats strfmt.Registry +} + +// WithJSONDefaults loads the json defaults for this api +func (d *API) WithJSONDefaults() *API { + d.DefaultConsumes = runtime.JSONMime + d.DefaultProduces = runtime.JSONMime + d.consumers[runtime.JSONMime] = runtime.JSONConsumer() + d.producers[runtime.JSONMime] = runtime.JSONProducer() + return d +} + +// WithoutJSONDefaults clears the json defaults for this api +func (d *API) WithoutJSONDefaults() *API { + d.DefaultConsumes = "" + d.DefaultProduces = "" + delete(d.consumers, runtime.JSONMime) + delete(d.producers, runtime.JSONMime) + return d +} + +// Formats returns the registered string formats +func (d *API) Formats() strfmt.Registry { + if d.formats == nil { + d.formats = strfmt.NewFormats() + } + return d.formats +} + +// RegisterFormat registers a custom format validator +func (d *API) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) { + if d.formats == nil { + d.formats = strfmt.NewFormats() + } + d.formats.Add(name, format, validator) +} + +// RegisterAuth registers an auth handler in this api +func (d *API) RegisterAuth(scheme string, handler runtime.Authenticator) { + if d.authenticators == nil { + d.authenticators = make(map[string]runtime.Authenticator) + } + d.authenticators[scheme] = handler +} + +// RegisterAuthorizer registers an authorizer handler in this api +func (d *API) RegisterAuthorizer(handler runtime.Authorizer) { + d.authorizer = handler +} + +// RegisterConsumer registers a consumer for a media type. +func (d *API) RegisterConsumer(mediaType string, handler runtime.Consumer) { + if d.consumers == nil { + d.consumers = make(map[string]runtime.Consumer, 10) + } + d.consumers[strings.ToLower(mediaType)] = handler +} + +// RegisterProducer registers a producer for a media type +func (d *API) RegisterProducer(mediaType string, handler runtime.Producer) { + if d.producers == nil { + d.producers = make(map[string]runtime.Producer, 10) + } + d.producers[strings.ToLower(mediaType)] = handler +} + +// RegisterOperation registers an operation handler for an operation name +func (d *API) RegisterOperation(method, path string, handler runtime.OperationHandler) { + if d.operations == nil { + d.operations = make(map[string]map[string]runtime.OperationHandler, 30) + } + um := strings.ToUpper(method) + if b, ok := d.operations[um]; !ok || b == nil { + d.operations[um] = make(map[string]runtime.OperationHandler) + } + d.operations[um][path] = handler +} + +// OperationHandlerFor returns the operation handler for the specified id if it can be found +func (d *API) OperationHandlerFor(method, path string) (runtime.OperationHandler, bool) { + if d.operations == nil { + return nil, false + } + if pi, ok := d.operations[strings.ToUpper(method)]; ok { + h, ok := pi[path] + return h, ok + } + return nil, false +} + +// ConsumersFor gets the consumers for the specified media types +func (d *API) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer { + result := make(map[string]runtime.Consumer) + for _, mt := range mediaTypes { + if consumer, ok := d.consumers[mt]; ok { + result[mt] = consumer + } + } + return result +} + +// ProducersFor gets the producers for the specified media types +func (d *API) ProducersFor(mediaTypes []string) map[string]runtime.Producer { + result := make(map[string]runtime.Producer) + for _, mt := range mediaTypes { + if producer, ok := d.producers[mt]; ok { + result[mt] = producer + } + } + return result +} + +// AuthenticatorsFor gets the authenticators for the specified security schemes +func (d *API) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator { + result := make(map[string]runtime.Authenticator) + for k := range schemes { + if a, ok := d.authenticators[k]; ok { + result[k] = a + } + } + return result +} + +// AuthorizersFor returns the registered authorizer +func (d *API) Authorizer() runtime.Authorizer { + return d.authorizer +} + +// Validate validates this API for any missing items +func (d *API) Validate() error { + return d.validate() +} + +// validateWith validates the registrations in this API against the provided spec analyzer +func (d *API) validate() error { + var consumes []string + for k := range d.consumers { + consumes = append(consumes, k) + } + + var produces []string + for k := range d.producers { + produces = append(produces, k) + } + + var authenticators []string + for k := range d.authenticators { + authenticators = append(authenticators, k) + } + + var operations []string + for m, v := range d.operations { + for p := range v { + operations = append(operations, fmt.Sprintf("%s %s", strings.ToUpper(m), p)) + } + } + + var definedAuths []string + for k := range d.spec.Spec().SecurityDefinitions { + definedAuths = append(definedAuths, k) + } + + if err := d.verify("consumes", consumes, d.analyzer.RequiredConsumes()); err != nil { + return err + } + if err := d.verify("produces", produces, d.analyzer.RequiredProduces()); err != nil { + return err + } + if err := d.verify("operation", operations, d.analyzer.OperationMethodPaths()); err != nil { + return err + } + + requiredAuths := d.analyzer.RequiredSecuritySchemes() + if err := d.verify("auth scheme", authenticators, requiredAuths); err != nil { + return err + } + if err := d.verify("security definitions", definedAuths, requiredAuths); err != nil { + return err + } + return nil +} + +func (d *API) verify(name string, registrations []string, expectations []string) error { + + sort.Sort(sort.StringSlice(registrations)) + sort.Sort(sort.StringSlice(expectations)) + + expected := map[string]struct{}{} + seen := map[string]struct{}{} + + for _, v := range expectations { + expected[v] = struct{}{} + } + + var unspecified []string + for _, v := range registrations { + seen[v] = struct{}{} + if _, ok := expected[v]; !ok { + unspecified = append(unspecified, v) + } + } + + for k := range seen { + delete(expected, k) + } + + var unregistered []string + for k := range expected { + unregistered = append(unregistered, k) + } + sort.Sort(sort.StringSlice(unspecified)) + sort.Sort(sort.StringSlice(unregistered)) + + if len(unregistered) > 0 || len(unspecified) > 0 { + return &errors.APIVerificationFailed{ + Section: name, + MissingSpecification: unspecified, + MissingRegistration: unregistered, + } + } + + return nil +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/untyped/api_test.go b/vendor/github.com/go-openapi/runtime/middleware/untyped/api_test.go new file mode 100644 index 0000000000..551bec71f8 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/untyped/api_test.go @@ -0,0 +1,286 @@ +// 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" +) + +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(params interface{}) (interface{}, error) { + return nil, 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), "") + assert.NoError(t, err) + assert.NotNil(t, validSpec) + + spec, err := loads.Analyzed([]byte(invalidSpecStr), "") + assert.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() + assert.Error(t, err) + assert.Equal(t, "missing [application/x-yaml] consumes registrations", err.Error()) + api1.RegisterConsumer("application/x-yaml", new(stubConsumer)) + err = api1.validate() + assert.Error(t, err) + assert.Equal(t, "missing [application/x-yaml] produces registrations", err.Error()) + api1.RegisterProducer("application/x-yaml", new(stubProducer)) + err = api1.validate() + assert.Error(t, err) + assert.Equal(t, "missing [GET /] operation registrations", err.Error()) + api1.RegisterOperation("get", "/", new(stubOperationHandler)) + err = api1.validate() + assert.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() + assert.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() + assert.NoError(t, err) + api3.RegisterConsumer("application/something", new(stubConsumer)) + err = api3.validate() + assert.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() + assert.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() + assert.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.Sort(sort.StringSlice(expected)) + consumes := analyzed.ConsumesFor(analyzed.AllPaths()["/"].Get) + sort.Sort(sort.StringSlice(consumes)) + assert.Equal(t, expected, consumes) + consumers := api1.ConsumersFor(consumes) + assert.Len(t, consumers, 1) + + produces := analyzed.ProducesFor(analyzed.AllPaths()["/"].Get) + sort.Sort(sort.StringSlice(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) + assert.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) + assert.NoError(t, err) + assert.Equal(t, "hello", p) +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/untyped_request_test.go b/vendor/github.com/go-openapi/runtime/middleware/untyped_request_test.go new file mode 100644 index 0000000000..5c226f62ea --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/untyped_request_test.go @@ -0,0 +1,164 @@ +// 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 middleware + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "io/ioutil" + "mime/multipart" + "net/http" + "net/url" + "strings" + "testing" + "time" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +func TestUntypedFormPost(t *testing.T) { + params := parametersForFormUpload() + binder := newUntypedRequestBinder(params, nil, strfmt.Default) + + urlStr := "http://localhost:8002/hello" + req, _ := http.NewRequest("POST", urlStr, bytes.NewBufferString(`name=the-name&age=32`)) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + data := make(map[string]interface{}) + assert.NoError(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + assert.Equal(t, "the-name", data["name"]) + assert.EqualValues(t, 32, data["age"]) + + req, _ = http.NewRequest("POST", urlStr, bytes.NewBufferString(`name=%3&age=32`)) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + data = make(map[string]interface{}) + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) +} + +func TestUntypedFileUpload(t *testing.T) { + binder := paramsForFileUpload() + + body := bytes.NewBuffer(nil) + writer := multipart.NewWriter(body) + part, err := writer.CreateFormFile("file", "plain-jane.txt") + assert.NoError(t, err) + + _, _ = part.Write([]byte("the file contents")) + _ = writer.WriteField("name", "the-name") + assert.NoError(t, writer.Close()) + + urlStr := "http://localhost:8002/hello" + req, _ := http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", writer.FormDataContentType()) + + data := make(map[string]interface{}) + assert.NoError(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + assert.Equal(t, "the-name", data["name"]) + assert.NotNil(t, data["file"]) + assert.IsType(t, runtime.File{}, data["file"]) + file := data["file"].(runtime.File) + assert.NotNil(t, file.Header) + assert.Equal(t, "plain-jane.txt", file.Header.Filename) + + bb, err := ioutil.ReadAll(file.Data) + assert.NoError(t, err) + assert.Equal(t, []byte("the file contents"), bb) + + req, _ = http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", "application/json") + data = make(map[string]interface{}) + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + + req, _ = http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", "application(") + data = make(map[string]interface{}) + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + + body = bytes.NewBuffer(nil) + writer = multipart.NewWriter(body) + part, err = writer.CreateFormFile("bad-name", "plain-jane.txt") + assert.NoError(t, err) + + _, _ = part.Write([]byte("the file contents")) + _ = writer.WriteField("name", "the-name") + assert.NoError(t, writer.Close()) + req, _ = http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", writer.FormDataContentType()) + + data = make(map[string]interface{}) + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) + + req, _ = http.NewRequest("POST", urlStr, body) + req.Header.Set("Content-Type", writer.FormDataContentType()) + _, _ = req.MultipartReader() + + data = make(map[string]interface{}) + assert.Error(t, binder.Bind(req, nil, runtime.JSONConsumer(), &data)) +} + +func TestUntypedBindingTypesForValid(t *testing.T) { + + op2 := parametersForAllTypes("") + binder := newUntypedRequestBinder(op2, nil, strfmt.Default) + + confirmed := true + name := "thomas" + friend := map[string]interface{}{"name": "toby", "age": json.Number("32")} + id, age, score, factor := int64(7575), int32(348), float32(5.309), float64(37.403) + requestID := 19394858 + tags := []string{"one", "two", "three"} + dt1 := time.Date(2014, 8, 9, 0, 0, 0, 0, time.UTC) + planned := strfmt.Date(dt1) + dt2 := time.Date(2014, 10, 12, 8, 5, 5, 0, time.UTC) + delivered := strfmt.DateTime(dt2) + picture := base64.URLEncoding.EncodeToString([]byte("hello")) + uri, _ := url.Parse("http://localhost:8002/hello/7575") + qs := uri.Query() + qs.Add("name", name) + qs.Add("confirmed", "true") + qs.Add("age", "348") + qs.Add("score", "5.309") + qs.Add("factor", "37.403") + qs.Add("tags", strings.Join(tags, ",")) + qs.Add("planned", planned.String()) + qs.Add("delivered", delivered.String()) + qs.Add("picture", picture) + + req, _ := http.NewRequest("POST", uri.String()+"?"+qs.Encode(), bytes.NewBuffer([]byte(`{"name":"toby","age":32}`))) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Request-Id", "19394858") + + data := make(map[string]interface{}) + err := binder.Bind(req, RouteParams([]RouteParam{{"id", "7575"}}), runtime.JSONConsumer(), &data) + assert.NoError(t, err) + assert.Equal(t, id, data["id"]) + assert.Equal(t, name, data["name"]) + assert.Equal(t, friend, data["friend"]) + assert.EqualValues(t, requestID, data["X-Request-Id"]) + assert.Equal(t, tags, data["tags"]) + assert.Equal(t, planned, data["planned"]) + assert.Equal(t, delivered, data["delivered"]) + assert.Equal(t, confirmed, data["confirmed"]) + assert.Equal(t, age, data["age"]) + assert.Equal(t, factor, data["factor"]) + assert.Equal(t, score, data["score"]) + pb, _ := base64.URLEncoding.DecodeString(picture) + assert.EqualValues(t, pb, data["picture"].(strfmt.Base64)) + +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/validation.go b/vendor/github.com/go-openapi/runtime/middleware/validation.go new file mode 100644 index 0000000000..bb8df3cb3d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/validation.go @@ -0,0 +1,122 @@ +// 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 middleware + +import ( + "mime" + "net/http" + "strings" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/swag" +) + +type validation struct { + context *Context + result []error + request *http.Request + route *MatchedRoute + bound map[string]interface{} +} + +// ContentType validates the content type of a request +func validateContentType(allowed []string, actual string) error { + debugLog("validating content type for %q against [%s]", actual, strings.Join(allowed, ", ")) + if len(allowed) == 0 { + return nil + } + mt, _, err := mime.ParseMediaType(actual) + if err != nil { + return errors.InvalidContentType(actual, allowed) + } + if swag.ContainsStringsCI(allowed, mt) { + return nil + } + if swag.ContainsStringsCI(allowed, "*/*") { + return nil + } + parts := strings.Split(actual, "/") + if len(parts) == 2 && swag.ContainsStringsCI(allowed, parts[0]+"/*") { + return nil + } + return errors.InvalidContentType(actual, allowed) +} + +func validateRequest(ctx *Context, request *http.Request, route *MatchedRoute) *validation { + debugLog("validating request %s %s", request.Method, request.URL.EscapedPath()) + validate := &validation{ + context: ctx, + request: request, + route: route, + bound: make(map[string]interface{}), + } + + validate.contentType() + if len(validate.result) == 0 { + validate.responseFormat() + } + if len(validate.result) == 0 { + validate.parameters() + } + + return validate +} + +func (v *validation) parameters() { + debugLog("validating request parameters for %s %s", v.request.Method, v.request.URL.EscapedPath()) + if result := v.route.Binder.Bind(v.request, v.route.Params, v.route.Consumer, v.bound); result != nil { + if result.Error() == "validation failure list" { + for _, e := range result.(*errors.Validation).Value.([]interface{}) { + v.result = append(v.result, e.(error)) + } + return + } + v.result = append(v.result, result) + } +} + +func (v *validation) contentType() { + if len(v.result) == 0 && runtime.HasBody(v.request) { + debugLog("validating body content type for %s %s", v.request.Method, v.request.URL.EscapedPath()) + ct, _, req, err := v.context.ContentType(v.request) + if err != nil { + v.result = append(v.result, err) + } else { + v.request = req + } + + if len(v.result) == 0 { + if err := validateContentType(v.route.Consumes, ct); err != nil { + v.result = append(v.result, err) + } + } + if ct != "" && v.route.Consumer == nil { + cons, ok := v.route.Consumers[ct] + if !ok { + v.result = append(v.result, errors.New(500, "no consumer registered for %s", ct)) + } else { + v.route.Consumer = cons + } + } + } +} + +func (v *validation) responseFormat() { + if str, rCtx := v.context.ResponseFormat(v.request, v.route.Produces); str == "" && runtime.HasBody(v.request) { + v.request = rCtx + v.result = append(v.result, errors.InvalidResponseFormat(v.request.Header.Get(runtime.HeaderAccept), v.route.Produces)) + } +} diff --git a/vendor/github.com/go-openapi/runtime/middleware/validation_test.go b/vendor/github.com/go-openapi/runtime/middleware/validation_test.go new file mode 100644 index 0000000000..10ec57879d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/middleware/validation_test.go @@ -0,0 +1,155 @@ +// 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 middleware + +import ( + "bytes" + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/internal/testing/petstore" + "github.com/stretchr/testify/assert" +) + +func newTestValidation(ctx *Context, next http.Handler) http.Handler { + + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + matched, rCtx, _ := ctx.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + if matched == nil { + ctx.NotFound(rw, r) + return + } + _, r, result := ctx.BindAndValidate(r, matched) + + if result != nil { + ctx.Respond(rw, r, matched.Produces, matched, result) + return + } + + next.ServeHTTP(rw, r) + }) +} + +func TestContentTypeValidation(t *testing.T) { + spec, api := petstore.NewAPI(t) + context := NewContext(spec, api, nil) + context.router = DefaultRouter(spec, context.api) + mw := newTestValidation(context, http.HandlerFunc(terminator)) + + recorder := httptest.NewRecorder() + request, _ := http.NewRequest("GET", "/api/pets", nil) + request.Header.Add("Accept", "*/*") + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusOK, recorder.Code) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("POST", "/api/pets", nil) + request.Header.Add("content-type", "application(") + request.Header.Add("Accept", "application/json") + request.ContentLength = 1 + + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusBadRequest, recorder.Code) + assert.Equal(t, "application/json", recorder.Header().Get("content-type")) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("POST", "/api/pets", nil) + request.Header.Add("Accept", "application/json") + request.Header.Add("content-type", "text/html") + request.ContentLength = 1 + + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusUnsupportedMediaType, recorder.Code) + assert.Equal(t, "application/json", recorder.Header().Get("content-type")) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("POST", "/api/pets", nil) + request.Header.Add("Accept", "application/json") + request.Header.Add("content-type", "text/html") + request.TransferEncoding = []string{"chunked"} + + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusUnsupportedMediaType, recorder.Code) + assert.Equal(t, "application/json", recorder.Header().Get("content-type")) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("POST", "/api/pets", nil) + request.Header.Add("Accept", "application/json") + request.Header.Add("content-type", "text/html") + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 422, recorder.Code) + assert.Equal(t, "application/json", recorder.Header().Get("content-type")) +} + +func TestResponseFormatValidation(t *testing.T) { + spec, api := petstore.NewAPI(t) + context := NewContext(spec, api, nil) + context.router = DefaultRouter(spec, context.api) + mw := newTestValidation(context, http.HandlerFunc(terminator)) + + recorder := httptest.NewRecorder() + request, _ := http.NewRequest("POST", "/api/pets", bytes.NewBuffer([]byte(`name: Dog`))) + request.Header.Set(runtime.HeaderContentType, "application/x-yaml") + request.Header.Set(runtime.HeaderAccept, "application/x-yaml") + + mw.ServeHTTP(recorder, request) + assert.Equal(t, 200, recorder.Code, recorder.Body.String()) + + recorder = httptest.NewRecorder() + request, _ = http.NewRequest("POST", "/api/pets", bytes.NewBuffer([]byte(`name: Dog`))) + request.Header.Set(runtime.HeaderContentType, "application/x-yaml") + request.Header.Set(runtime.HeaderAccept, "application/sml") + + mw.ServeHTTP(recorder, request) + assert.Equal(t, http.StatusNotAcceptable, recorder.Code) +} + +func TestValidateContentType(t *testing.T) { + data := []struct { + hdr string + allowed []string + err *errors.Validation + }{ + {"application/json", []string{"application/json"}, nil}, + {"application/json", []string{"application/x-yaml", "text/html"}, errors.InvalidContentType("application/json", []string{"application/x-yaml", "text/html"})}, + {"text/html; charset=utf-8", []string{"text/html"}, nil}, + {"text/html;charset=utf-8", []string{"text/html"}, nil}, + {"", []string{"application/json"}, errors.InvalidContentType("", []string{"application/json"})}, + {"text/html; charset=utf-8", []string{"application/json"}, errors.InvalidContentType("text/html; charset=utf-8", []string{"application/json"})}, + {"application(", []string{"application/json"}, errors.InvalidContentType("application(", []string{"application/json"})}, + {"application/json;char*", []string{"application/json"}, errors.InvalidContentType("application/json;char*", []string{"application/json"})}, + {"application/octet-stream", []string{"image/jpeg", "application/*"}, nil}, + {"image/png", []string{"*/*", "application/json"}, nil}, + } + + for _, v := range data { + err := validateContentType(v.allowed, v.hdr) + if v.err == nil { + assert.NoError(t, err, "input: %q", v.hdr) + } else { + assert.Error(t, err, "input: %q", v.hdr) + assert.IsType(t, &errors.Validation{}, err, "input: %q", v.hdr) + assert.Equal(t, v.err.Error(), err.Error(), "input: %q", v.hdr) + assert.EqualValues(t, http.StatusUnsupportedMediaType, err.(*errors.Validation).Code()) + } + } +} diff --git a/vendor/github.com/go-openapi/runtime/request.go b/vendor/github.com/go-openapi/runtime/request.go new file mode 100644 index 0000000000..87b73da45c --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/request.go @@ -0,0 +1,77 @@ +// 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 runtime + +import ( + "io" + "net/http" + "strings" + + "github.com/go-openapi/swag" +) + +// CanHaveBody returns true if this method can have a body +func CanHaveBody(method string) bool { + mn := strings.ToUpper(method) + return mn == "POST" || mn == "PUT" || mn == "PATCH" || mn == "DELETE" +} + +// IsSafe returns true if this is a request with a safe method +func IsSafe(r *http.Request) bool { + mn := strings.ToUpper(r.Method) + return mn == "GET" || mn == "HEAD" +} + +// AllowsBody returns true if the request allows for a body +func AllowsBody(r *http.Request) bool { + mn := strings.ToUpper(r.Method) + return mn != "HEAD" +} + +// HasBody returns true if this method needs a content-type +func HasBody(r *http.Request) bool { + return len(r.TransferEncoding) > 0 || r.ContentLength > 0 +} + +// JSONRequest creates a new http request with json headers set +func JSONRequest(method, urlStr string, body io.Reader) (*http.Request, error) { + req, err := http.NewRequest(method, urlStr, body) + if err != nil { + return nil, err + } + req.Header.Add(HeaderContentType, JSONMime) + req.Header.Add(HeaderAccept, JSONMime) + return req, nil +} + +// Gettable for things with a method GetOK(string) (data string, hasKey bool, hasValue bool) +type Gettable interface { + GetOK(string) ([]string, bool, bool) +} + +// ReadSingleValue reads a single value from the source +func ReadSingleValue(values Gettable, name string) string { + vv, _, hv := values.GetOK(name) + if hv { + return vv[len(vv)-1] + } + return "" +} + +// ReadCollectionValue reads a collection value from a string data source +func ReadCollectionValue(values Gettable, name, collectionFormat string) []string { + v := ReadSingleValue(values, name) + return swag.SplitByFormat(v, collectionFormat) +} diff --git a/vendor/github.com/go-openapi/runtime/request_test.go b/vendor/github.com/go-openapi/runtime/request_test.go new file mode 100644 index 0000000000..ba65f75f76 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/request_test.go @@ -0,0 +1,122 @@ +// 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 runtime + +import ( + "net/url" + "testing" + + "github.com/stretchr/testify/assert" +) + +/* +type tstreadcloser struct { + closed bool +} + +func (t *tstreadcloser) Read(p []byte) (int, error) { return 0, nil } +func (t *tstreadcloser) Close() error { + t.closed = true + return nil +} + +func TestPeekingReader(t *testing.T) { + // just passes to original reader when nothing called + exp1 := []byte("original") + pr1 := &peekingReader{rdr: ioutil.NopCloser(bytes.NewReader(exp1))} + b1, err := ioutil.ReadAll(pr1) + if assert.NoError(t, err) { + assert.Equal(t, exp1, b1) + } + + // uses actual when there was some buffering + exp2 := []byte("actual") + pt1, pt2 := []byte("a"), []byte("ctual") + pr2 := &peekingReader{ + rdr: ioutil.NopCloser(bytes.NewReader(exp1)), + actual: io.MultiReader(bytes.NewReader(pt1), bytes.NewReader(pt2)), + peeked: pt1, + } + b2, err := ioutil.ReadAll(pr2) + if assert.NoError(t, err) { + assert.Equal(t, exp2, b2) + } + + // closes original reader + tr := new(tstreadcloser) + pr3 := &peekingReader{ + rdr: tr, + actual: ioutil.NopCloser(bytes.NewBuffer(nil)), + peeked: pt1, + } + + + // returns true when peeked previously with data + // returns true when peeked with data +} +*/ + +func TestJSONRequest(t *testing.T) { + req, err := JSONRequest("GET", "/swagger.json", nil) + assert.NoError(t, err) + assert.Equal(t, "GET", req.Method) + assert.Equal(t, JSONMime, req.Header.Get(HeaderContentType)) + assert.Equal(t, JSONMime, req.Header.Get(HeaderAccept)) + + req, err = JSONRequest("GET", "%2", nil) + assert.Error(t, err) + assert.Nil(t, req) +} + +//func TestCanHaveBody(t *testing.T) { +//assert.True(t, CanHaveBody("put")) +//assert.True(t, CanHaveBody("post")) +//assert.True(t, CanHaveBody("patch")) +//assert.True(t, CanHaveBody("delete")) +//assert.False(t, CanHaveBody("")) +//assert.False(t, CanHaveBody("get")) +//assert.False(t, CanHaveBody("options")) +//assert.False(t, CanHaveBody("head")) +//assert.False(t, CanHaveBody("invalid")) +//} + +func TestReadSingle(t *testing.T) { + values := url.Values(make(map[string][]string)) + values.Add("something", "the thing") + assert.Equal(t, "the thing", ReadSingleValue(tv(values), "something")) + assert.Empty(t, ReadSingleValue(tv(values), "notthere")) +} + +func TestReadCollection(t *testing.T) { + values := url.Values(make(map[string][]string)) + values.Add("something", "value1,value2") + assert.Equal(t, []string{"value1", "value2"}, ReadCollectionValue(tv(values), "something", "csv")) + assert.Empty(t, ReadCollectionValue(tv(values), "notthere", "")) +} + +type tv map[string][]string + +func (v tv) GetOK(key string) (value []string, hasKey bool, hasValue bool) { + value, hasKey = v[key] + if !hasKey { + return + } + if len(value) == 0 { + return + } + hasValue = true + return + +} diff --git a/vendor/github.com/go-openapi/runtime/security/apikey_auth_test.go b/vendor/github.com/go-openapi/runtime/security/apikey_auth_test.go new file mode 100644 index 0000000000..958b2ea423 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/security/apikey_auth_test.go @@ -0,0 +1,94 @@ +// 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 security + +import ( + "net/http" + "testing" + + "github.com/go-openapi/errors" + "github.com/stretchr/testify/assert" +) + +var tokenAuth = TokenAuthentication(func(token string) (interface{}, error) { + if token == "token123" { + return "admin", nil + } + return nil, errors.Unauthenticated("token") +}) + +func TestInvalidApiKeyAuthInitialization(t *testing.T) { + assert.Panics(t, func() { APIKeyAuth("api_key", "qery", tokenAuth) }) +} + +func TestValidApiKeyAuth(t *testing.T) { + ta := APIKeyAuth("api_key", "query", tokenAuth) + ta2 := APIKeyAuth("X-API-KEY", "header", tokenAuth) + + req1, _ := http.NewRequest("GET", "/blah?api_key=token123", nil) + + ok, usr, err := ta.Authenticate(req1) + assert.True(t, ok) + assert.Equal(t, "admin", usr) + assert.NoError(t, err) + + req2, _ := http.NewRequest("GET", "/blah", nil) + req2.Header.Set("X-API-KEY", "token123") + + ok, usr, err = ta2.Authenticate(req2) + assert.True(t, ok) + assert.Equal(t, "admin", usr) + assert.NoError(t, err) +} + +func TestInvalidApiKeyAuth(t *testing.T) { + ta := APIKeyAuth("api_key", "query", tokenAuth) + ta2 := APIKeyAuth("X-API-KEY", "header", tokenAuth) + + req1, _ := http.NewRequest("GET", "/blah?api_key=token124", nil) + + ok, usr, err := ta.Authenticate(req1) + assert.True(t, ok) + assert.Equal(t, nil, usr) + assert.Error(t, err) + + req2, _ := http.NewRequest("GET", "/blah", nil) + req2.Header.Set("X-API-KEY", "token124") + + ok, usr, err = ta2.Authenticate(req2) + assert.True(t, ok) + assert.Equal(t, nil, usr) + assert.Error(t, err) +} + +func TestMissingApiKeyAuth(t *testing.T) { + ta := APIKeyAuth("api_key", "query", tokenAuth) + ta2 := APIKeyAuth("X-API-KEY", "header", tokenAuth) + + req1, _ := http.NewRequest("GET", "/blah", nil) + req1.Header.Set("X-API-KEY", "token123") + + ok, usr, err := ta.Authenticate(req1) + assert.False(t, ok) + assert.Equal(t, nil, usr) + assert.NoError(t, err) + + req2, _ := http.NewRequest("GET", "/blah?api_key=token123", nil) + + ok, usr, err = ta2.Authenticate(req2) + assert.False(t, ok) + assert.Equal(t, nil, usr) + assert.NoError(t, err) +} diff --git a/vendor/github.com/go-openapi/runtime/security/authenticator.go b/vendor/github.com/go-openapi/runtime/security/authenticator.go new file mode 100644 index 0000000000..251854e6dc --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/security/authenticator.go @@ -0,0 +1,128 @@ +// 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 security + +import ( + "net/http" + "strings" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" +) + +// HttpAuthenticator is a function that authenticates a HTTP request +func HttpAuthenticator(handler func(*http.Request) (bool, interface{}, error)) runtime.Authenticator { + return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) { + if request, ok := params.(*http.Request); ok { + return handler(request) + } + if scoped, ok := params.(*ScopedAuthRequest); ok { + return handler(scoped.Request) + } + return false, nil, nil + }) +} + +// ScopedAuthenticator is a function that authenticates a HTTP request against a list of valid scopes +func ScopedAuthenticator(handler func(*ScopedAuthRequest) (bool, interface{}, error)) runtime.Authenticator { + return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) { + if request, ok := params.(*ScopedAuthRequest); ok { + return handler(request) + } + return false, nil, nil + }) +} + +// UserPassAuthentication authentication function +type UserPassAuthentication func(string, string) (interface{}, error) + +// TokenAuthentication authentication function +type TokenAuthentication func(string) (interface{}, error) + +// ScopedTokenAuthentication authentication function +type ScopedTokenAuthentication func(string, []string) (interface{}, error) + +// BasicAuth creates a basic auth authenticator with the provided authentication function +func BasicAuth(authenticate UserPassAuthentication) runtime.Authenticator { + return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) { + if usr, pass, ok := r.BasicAuth(); ok { + p, err := authenticate(usr, pass) + return true, p, err + } + + return false, nil, nil + }) +} + +// APIKeyAuth creates an authenticator that uses a token for authorization. +// This token can be obtained from either a header or a query string +func APIKeyAuth(name, in string, authenticate TokenAuthentication) runtime.Authenticator { + 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\".")) + } + + var getToken func(*http.Request) string + switch inl { + case "header": + getToken = func(r *http.Request) string { return r.Header.Get(name) } + case "query": + getToken = func(r *http.Request) string { return r.URL.Query().Get(name) } + } + + return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) { + token := getToken(r) + if token == "" { + return false, nil, nil + } + + p, err := authenticate(token) + return true, p, err + }) +} + +// ScopedAuthRequest contains both a http request and the required scopes for a particular operation +type ScopedAuthRequest struct { + Request *http.Request + RequiredScopes []string +} + +// BearerAuth for use with oauth2 flows +func BearerAuth(name string, authenticate ScopedTokenAuthentication) runtime.Authenticator { + const prefix = "Bearer " + return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, interface{}, error) { + var token string + hdr := r.Request.Header.Get("Authorization") + if strings.HasPrefix(hdr, prefix) { + token = strings.TrimPrefix(hdr, prefix) + } + if token == "" { + qs := r.Request.URL.Query() + token = qs.Get("access_token") + } + ct, _, _ := runtime.ContentType(r.Request.Header) + if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") { + token = r.Request.FormValue("access_token") + } + + if token == "" { + return false, nil, nil + } + + p, err := authenticate(token, r.RequiredScopes) + return true, p, err + }) +} diff --git a/vendor/github.com/go-openapi/runtime/security/authorizer.go b/vendor/github.com/go-openapi/runtime/security/authorizer.go new file mode 100644 index 0000000000..00c1a4d6a4 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/security/authorizer.go @@ -0,0 +1,27 @@ +// 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 security + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// Authorized provides a default implementation of the Authorizer interface where all +// requests are authorized (successful) +func Authorized() runtime.Authorizer { + return runtime.AuthorizerFunc(func(_ *http.Request, _ interface{}) error { return nil }) +} diff --git a/vendor/github.com/go-openapi/runtime/security/authorizer_test.go b/vendor/github.com/go-openapi/runtime/security/authorizer_test.go new file mode 100644 index 0000000000..7f1f9b053d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/security/authorizer_test.go @@ -0,0 +1,28 @@ +// 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 security + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAuthorized(t *testing.T) { + authorizer := Authorized() + + err := authorizer.Authorize(nil, nil) + assert.NoError(t, err) +} diff --git a/vendor/github.com/go-openapi/runtime/security/basic_auth_test.go b/vendor/github.com/go-openapi/runtime/security/basic_auth_test.go new file mode 100644 index 0000000000..94830bca5d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/security/basic_auth_test.go @@ -0,0 +1,75 @@ +// 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 security + +import ( + "net/http" + "testing" + + "github.com/go-openapi/errors" + "github.com/stretchr/testify/assert" +) + +var basicAuthHandler = UserPassAuthentication(func(user, pass string) (interface{}, error) { + if user == "admin" && pass == "123456" { + return "admin", nil + } + return "", errors.Unauthenticated("basic") +}) + +func TestValidBasicAuth(t *testing.T) { + ba := BasicAuth(basicAuthHandler) + + req, _ := http.NewRequest("GET", "/blah", nil) + req.SetBasicAuth("admin", "123456") + ok, usr, err := ba.Authenticate(req) + + assert.NoError(t, err) + assert.True(t, ok) + assert.Equal(t, "admin", usr) +} + +func TestInvalidBasicAuth(t *testing.T) { + ba := BasicAuth(basicAuthHandler) + + req, _ := http.NewRequest("GET", "/blah", nil) + req.SetBasicAuth("admin", "admin") + ok, usr, err := ba.Authenticate(req) + + assert.Error(t, err) + assert.True(t, ok) + assert.Equal(t, "", usr) +} + +func TestMissingbasicAuth(t *testing.T) { + ba := BasicAuth(basicAuthHandler) + + req, _ := http.NewRequest("GET", "/blah", nil) + + ok, usr, err := ba.Authenticate(req) + assert.NoError(t, err) + assert.False(t, ok) + assert.Equal(t, nil, usr) +} + +func TestNoRequestBasicAuth(t *testing.T) { + ba := BasicAuth(basicAuthHandler) + + ok, usr, err := ba.Authenticate("token") + + assert.NoError(t, err) + assert.False(t, ok) + assert.Nil(t, usr) +} diff --git a/vendor/github.com/go-openapi/runtime/security/bearer_auth_test.go b/vendor/github.com/go-openapi/runtime/security/bearer_auth_test.go new file mode 100644 index 0000000000..899dc73d9d --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/security/bearer_auth_test.go @@ -0,0 +1,143 @@ +package security + +import ( + "bytes" + "mime/multipart" + "net/http" + "net/url" + "strings" + "testing" + + "github.com/go-openapi/errors" + "github.com/stretchr/testify/assert" +) + +var bearerAuth = ScopedTokenAuthentication(func(token string, requiredScopes []string) (interface{}, error) { + if token == "token123" { + return "admin", nil + } + return nil, errors.Unauthenticated("bearer") +}) + +func TestValidBearerAuth(t *testing.T) { + ba := BearerAuth("owners_auth", bearerAuth) + + req1, _ := http.NewRequest("GET", "/blah?access_token=token123", nil) + + ok, usr, err := ba.Authenticate(&ScopedAuthRequest{Request: req1}) + assert.True(t, ok) + assert.Equal(t, "admin", usr) + assert.NoError(t, err) + + req2, _ := http.NewRequest("GET", "/blah", nil) + req2.Header.Set("Authorization", "Bearer token123") + + ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req2}) + assert.True(t, ok) + assert.Equal(t, "admin", usr) + assert.NoError(t, err) + + body := url.Values(map[string][]string{}) + body.Set("access_token", "token123") + req3, _ := http.NewRequest("POST", "/blah", strings.NewReader(body.Encode())) + req3.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req3}) + assert.True(t, ok) + assert.Equal(t, "admin", usr) + assert.NoError(t, err) + + mpbody := bytes.NewBuffer(nil) + writer := multipart.NewWriter(mpbody) + _ = writer.WriteField("access_token", "token123") + writer.Close() + req4, _ := http.NewRequest("POST", "/blah", mpbody) + req4.Header.Set("Content-Type", writer.FormDataContentType()) + + ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req4}) + assert.True(t, ok) + assert.Equal(t, "admin", usr) + assert.NoError(t, err) +} + +func TestInvalidBearerAuth(t *testing.T) { + ba := BearerAuth("owners_auth", bearerAuth) + + req1, _ := http.NewRequest("GET", "/blah?access_token=token124", nil) + + ok, usr, err := ba.Authenticate(&ScopedAuthRequest{Request: req1}) + assert.True(t, ok) + assert.Equal(t, nil, usr) + assert.Error(t, err) + + req2, _ := http.NewRequest("GET", "/blah", nil) + req2.Header.Set("Authorization", "Bearer token124") + + ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req2}) + assert.True(t, ok) + assert.Equal(t, nil, usr) + assert.Error(t, err) + + body := url.Values(map[string][]string{}) + body.Set("access_token", "token124") + req3, _ := http.NewRequest("POST", "/blah", strings.NewReader(body.Encode())) + req3.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req3}) + assert.True(t, ok) + assert.Equal(t, nil, usr) + assert.Error(t, err) + + mpbody := bytes.NewBuffer(nil) + writer := multipart.NewWriter(mpbody) + _ = writer.WriteField("access_token", "token124") + writer.Close() + req4, _ := http.NewRequest("POST", "/blah", mpbody) + req4.Header.Set("Content-Type", writer.FormDataContentType()) + + ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req4}) + assert.True(t, ok) + assert.Equal(t, nil, usr) + assert.Error(t, err) +} + +func TestMissingBearerAuth(t *testing.T) { + ba := BearerAuth("owners_auth", bearerAuth) + + req1, _ := http.NewRequest("GET", "/blah?access_toke=token123", nil) + + ok, usr, err := ba.Authenticate(&ScopedAuthRequest{Request: req1}) + assert.False(t, ok) + assert.Equal(t, nil, usr) + assert.NoError(t, err) + + req2, _ := http.NewRequest("GET", "/blah", nil) + req2.Header.Set("Authorization", "Beare token123") + + ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req2}) + assert.False(t, ok) + assert.Equal(t, nil, usr) + assert.NoError(t, err) + + body := url.Values(map[string][]string{}) + body.Set("access_toke", "token123") + req3, _ := http.NewRequest("POST", "/blah", strings.NewReader(body.Encode())) + req3.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req3}) + assert.False(t, ok) + assert.Equal(t, nil, usr) + assert.NoError(t, err) + + mpbody := bytes.NewBuffer(nil) + writer := multipart.NewWriter(mpbody) + _ = writer.WriteField("access_toke", "token123") + writer.Close() + req4, _ := http.NewRequest("POST", "/blah", mpbody) + req4.Header.Set("Content-Type", writer.FormDataContentType()) + + ok, usr, err = ba.Authenticate(&ScopedAuthRequest{Request: req4}) + assert.False(t, ok) + assert.Equal(t, nil, usr) + assert.NoError(t, err) +} diff --git a/vendor/github.com/go-openapi/runtime/statuses.go b/vendor/github.com/go-openapi/runtime/statuses.go new file mode 100644 index 0000000000..3b011a0bff --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/statuses.go @@ -0,0 +1,90 @@ +// 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 runtime + +// Statuses lists the most common HTTP status codes to default message +// taken from https://httpstatuses.com/ +var Statuses = map[int]string{ + 100: "Continue", + 101: "Switching Protocols", + 102: "Processing", + 103: "Checkpoint", + 122: "URI too long", + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Request Processed", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 207: "Multi-Status", + 208: "Already Reported", + 226: "IM Used", + 300: "Multiple Choices", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 306: "Switch Proxy", + 307: "Temporary Redirect", + 308: "Permanent Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request-URI Too Long", + 415: "Unsupported Media Type", + 416: "Request Range Not Satisfiable", + 417: "Expectation Failed", + 418: "I'm a teapot", + 420: "Enhance Your Calm", + 422: "Unprocessable Entity", + 423: "Locked", + 424: "Failed Dependency", + 426: "Upgrade Required", + 428: "Precondition Required", + 429: "Too Many Requests", + 431: "Request Header Fields Too Large", + 444: "No Response", + 449: "Retry With", + 450: "Blocked by Windows Parental Controls", + 451: "Wrong Exchange Server", + 499: "Client Closed Request", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported", + 506: "Variant Also Negotiates", + 507: "Insufficient Storage", + 508: "Loop Detected", + 509: "Bandwidth Limit Exceeded", + 510: "Not Extended", + 511: "Network Authentication Required", + 598: "Network read timeout error", + 599: "Network connect timeout error", +} diff --git a/vendor/github.com/go-openapi/runtime/text.go b/vendor/github.com/go-openapi/runtime/text.go new file mode 100644 index 0000000000..77099fedac --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/text.go @@ -0,0 +1,111 @@ +// 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 runtime + +import ( + "bytes" + "encoding" + "errors" + "fmt" + "io" + "reflect" + + "github.com/go-openapi/swag" +) + +// TextConsumer creates a new text consumer +func TextConsumer() Consumer { + return ConsumerFunc(func(reader io.Reader, data interface{}) error { + if reader == nil { + return errors.New("TextConsumer requires a reader") // early exit + } + + buf := new(bytes.Buffer) + _, err := buf.ReadFrom(reader) + if err != nil { + return err + } + b := buf.Bytes() + + if tu, ok := data.(encoding.TextUnmarshaler); ok { + err := tu.UnmarshalText(b) + if err != nil { + return fmt.Errorf("text consumer: %v", err) + } + + return nil + } + + t := reflect.TypeOf(data) + if data != nil && t.Kind() == reflect.Ptr { + v := reflect.Indirect(reflect.ValueOf(data)) + if t.Elem().Kind() == reflect.String { + v.SetString(string(b)) + return nil + } + } + + return fmt.Errorf("%v (%T) is not supported by the TextConsumer, %s", + data, data, "can be resolved by supporting TextUnmarshaler interface") + }) +} + +// TextProducer creates a new text producer +func TextProducer() Producer { + return ProducerFunc(func(writer io.Writer, data interface{}) error { + if writer == nil { + return errors.New("TextProducer requires a writer") // early exit + } + + if data == nil { + return errors.New("no data given to produce text from") + } + + if tm, ok := data.(encoding.TextMarshaler); ok { + txt, err := tm.MarshalText() + if err != nil { + return fmt.Errorf("text producer: %v", err) + } + _, err = writer.Write(txt) + return err + } + + if str, ok := data.(error); ok { + _, err := writer.Write([]byte(str.Error())) + return err + } + + if str, ok := data.(fmt.Stringer); ok { + _, err := writer.Write([]byte(str.String())) + return err + } + + v := reflect.Indirect(reflect.ValueOf(data)) + if t := v.Type(); t.Kind() == reflect.Struct || t.Kind() == reflect.Slice { + b, err := swag.WriteJSON(data) + if err != nil { + return err + } + _, err = writer.Write(b) + return err + } + if v.Kind() != reflect.String { + return fmt.Errorf("%T is not a supported type by the TextProducer", data) + } + + _, err := writer.Write([]byte(v.String())) + return err + }) +} diff --git a/vendor/github.com/go-openapi/runtime/text_test.go b/vendor/github.com/go-openapi/runtime/text_test.go new file mode 100644 index 0000000000..86f8f5682a --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/text_test.go @@ -0,0 +1,176 @@ +// 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 runtime + +import ( + "bytes" + "errors" + "fmt" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +var consProdText = `The quick brown fox jumped over the lazy dog.` + +func TestTextConsumer(t *testing.T) { + cons := TextConsumer() + + // can consume as a string + var str string + err1 := cons.Consume(bytes.NewBuffer([]byte(consProdText)), &str) + assert.NoError(t, err1) + assert.Equal(t, consProdText, str) + + var tu textUnmarshalDummy + + // can consume as a TextUnmarshaler + err3 := cons.Consume(bytes.NewBuffer([]byte(consProdText)), &tu) + assert.NoError(t, err3) + assert.Equal(t, consProdText, tu.str) + + // text unmarshal objects can return an error as well, this will be propagated + assert.Error(t, cons.Consume(bytes.NewBuffer(nil), &tu)) + + // when readers can't be read, those errors will be propogated as well + assert.Error(t, cons.Consume(new(nopReader), &tu)) + + // readers can also not be nil + assert.Error(t, cons.Consume(nil, &tu)) + + // can't consume nil ptr's or unsupported types + assert.Error(t, cons.Consume(bytes.NewBuffer([]byte(consProdText)), nil)) + assert.Error(t, cons.Consume(bytes.NewBuffer([]byte(consProdText)), 42)) + assert.Error(t, cons.Consume(bytes.NewBuffer([]byte(consProdText)), &struct{}{})) +} + +type textUnmarshalDummy struct { + str string +} + +func (t *textUnmarshalDummy) UnmarshalText(b []byte) error { + if len(b) == 0 { + return errors.New("no text given") + } + + t.str = string(b) + return nil +} + +type nopReader struct{} + +func (n *nopReader) Read(p []byte) (int, error) { + return 0, errors.New("nop") +} + +func TestTextProducer(t *testing.T) { + prod := TextProducer() + rw := httptest.NewRecorder() + err := prod.Produce(rw, consProdText) + assert.NoError(t, err) + assert.Equal(t, consProdText, rw.Body.String()) + rw2 := httptest.NewRecorder() + err2 := prod.Produce(rw2, &consProdText) + assert.NoError(t, err2) + assert.Equal(t, consProdText, rw2.Body.String()) + + // should always work with type aliases + // as an alias is sometimes given by generated go-swagger code + type alias string + aliasProdText := alias(consProdText) + rw3 := httptest.NewRecorder() + err3 := prod.Produce(rw3, aliasProdText) + assert.NoError(t, err3) + assert.Equal(t, consProdText, rw3.Body.String()) + rw4 := httptest.NewRecorder() + err4 := prod.Produce(rw4, &aliasProdText) + assert.NoError(t, err4) + assert.Equal(t, consProdText, rw4.Body.String()) + + const answer = "42" + + // Should always work with objects implementing Stringer interface + rw5 := httptest.NewRecorder() + err5 := prod.Produce(rw5, &stringerDummy{answer}) + assert.NoError(t, err5) + assert.Equal(t, answer, rw5.Body.String()) + + // Should always work with objects implementing TextMarshaler interface + rw6 := httptest.NewRecorder() + err6 := prod.Produce(rw6, &textMarshalDummy{answer}) + assert.NoError(t, err6) + assert.Equal(t, answer, rw6.Body.String()) + + rw10 := httptest.NewRecorder() + err10 := prod.Produce(rw10, errors.New(answer)) + assert.NoError(t, err10) + assert.Equal(t, answer, rw10.Body.String()) + + rw11 := httptest.NewRecorder() + err11 := prod.Produce(rw11, Error{Message: answer}) + assert.NoError(t, err11) + assert.Equal(t, fmt.Sprintf(`{"message":%q}`, answer), rw11.Body.String()) + + rw12 := httptest.NewRecorder() + err12 := prod.Produce(rw12, &Error{Message: answer}) + assert.NoError(t, err12) + assert.Equal(t, fmt.Sprintf(`{"message":%q}`, answer), rw12.Body.String()) + + rw13 := httptest.NewRecorder() + err13 := prod.Produce(rw13, []string{answer}) + assert.NoError(t, err13) + assert.Equal(t, fmt.Sprintf(`[%q]`, answer), rw13.Body.String()) + + // should not work with anything that's not (indirectly) a string + rw7 := httptest.NewRecorder() + err7 := prod.Produce(rw7, 42) + assert.Error(t, err7) + // nil values should also be safely caught with an error + rw8 := httptest.NewRecorder() + err8 := prod.Produce(rw8, nil) + assert.Error(t, err8) + + // writer can not be nil + assert.Error(t, prod.Produce(nil, &textMarshalDummy{answer})) + + // should not work for a textMarshaler that returns an error during marshalling + rw9 := httptest.NewRecorder() + err9 := prod.Produce(rw9, new(textMarshalDummy)) + assert.Error(t, err9) +} + +type Error struct { + Message string `json:"message"` +} + +type stringerDummy struct { + str string +} + +func (t *stringerDummy) String() string { + return t.str +} + +type textMarshalDummy struct { + str string +} + +func (t *textMarshalDummy) MarshalText() ([]byte, error) { + if t.str == "" { + return nil, errors.New("no text set") + } + return []byte(t.str), nil +} diff --git a/vendor/github.com/go-openapi/runtime/values.go b/vendor/github.com/go-openapi/runtime/values.go new file mode 100644 index 0000000000..11f5732af4 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/values.go @@ -0,0 +1,19 @@ +package runtime + +// Values typically represent parameters on a http request. +type Values map[string][]string + +// GetOK returns the values collection for the given key. +// When the key is present in the map it will return true for hasKey. +// When the value is not empty it will return true for hasValue. +func (v Values) GetOK(key string) (value []string, hasKey bool, hasValue bool) { + value, hasKey = v[key] + if !hasKey { + return + } + if len(value) == 0 { + return + } + hasValue = true + return +} diff --git a/vendor/github.com/go-openapi/runtime/xml.go b/vendor/github.com/go-openapi/runtime/xml.go new file mode 100644 index 0000000000..821c7393df --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/xml.go @@ -0,0 +1,36 @@ +// 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 runtime + +import ( + "encoding/xml" + "io" +) + +// XMLConsumer creates a new XML consumer +func XMLConsumer() Consumer { + return ConsumerFunc(func(reader io.Reader, data interface{}) error { + dec := xml.NewDecoder(reader) + return dec.Decode(data) + }) +} + +// XMLProducer creates a new XML producer +func XMLProducer() Producer { + return ProducerFunc(func(writer io.Writer, data interface{}) error { + enc := xml.NewEncoder(writer) + return enc.Encode(data) + }) +} diff --git a/vendor/github.com/go-openapi/runtime/xml_test.go b/vendor/github.com/go-openapi/runtime/xml_test.go new file mode 100644 index 0000000000..1f2dfd2505 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/xml_test.go @@ -0,0 +1,53 @@ +// 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 runtime + +import ( + "bytes" + "encoding/xml" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +var consProdXML = `Somebody1` + +func TestXMLConsumer(t *testing.T) { + cons := XMLConsumer() + var data struct { + XMLName xml.Name `xml:"person"` + Name string `xml:"name"` + ID int `xml:"id"` + } + err := cons.Consume(bytes.NewBuffer([]byte(consProdXML)), &data) + assert.NoError(t, err) + assert.Equal(t, "Somebody", data.Name) + assert.Equal(t, 1, data.ID) +} + +func TestXMLProducer(t *testing.T) { + prod := XMLProducer() + data := struct { + XMLName xml.Name `xml:"person"` + Name string `xml:"name"` + ID int `xml:"id"` + }{Name: "Somebody", ID: 1} + + rw := httptest.NewRecorder() + err := prod.Produce(rw, data) + assert.NoError(t, err) + assert.Equal(t, consProdXML, rw.Body.String()) +} diff --git a/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go b/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go new file mode 100644 index 0000000000..fdbcc529c8 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/yamlpc/yaml.go @@ -0,0 +1,44 @@ +// 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 yamlpc + +import ( + "io" + "io/ioutil" + + "github.com/go-openapi/runtime" + + "gopkg.in/yaml.v2" +) + +// YAMLConsumer creates a consumer for yaml data +func YAMLConsumer() runtime.Consumer { + return runtime.ConsumerFunc(func(r io.Reader, v interface{}) error { + buf, err := ioutil.ReadAll(r) + if err != nil { + return err + } + return yaml.Unmarshal(buf, v) + }) +} + +// YAMLProducer creates a producer for yaml data +func YAMLProducer() runtime.Producer { + return runtime.ProducerFunc(func(w io.Writer, v interface{}) error { + b, _ := yaml.Marshal(v) // can't make this error come up + _, err := w.Write(b) + return err + }) +} diff --git a/vendor/github.com/go-openapi/runtime/yamlpc/yaml_test.go b/vendor/github.com/go-openapi/runtime/yamlpc/yaml_test.go new file mode 100644 index 0000000000..5cfe539516 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/yamlpc/yaml_test.go @@ -0,0 +1,62 @@ +// 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 yamlpc + +import ( + "bytes" + "errors" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +var consProdYAML = "name: Somebody\nid: 1\n" + +func TestYAMLConsumer(t *testing.T) { + cons := YAMLConsumer() + var data struct { + Name string + ID int + } + err := cons.Consume(bytes.NewBuffer([]byte(consProdYAML)), &data) + assert.NoError(t, err) + assert.Equal(t, "Somebody", data.Name) + assert.Equal(t, 1, data.ID) +} + +func TestYAMLProducer(t *testing.T) { + prod := YAMLProducer() + data := struct { + Name string `yaml:"name"` + ID int `yaml:"id"` + }{Name: "Somebody", ID: 1} + + rw := httptest.NewRecorder() + err := prod.Produce(rw, data) + assert.NoError(t, err) + assert.Equal(t, consProdYAML, rw.Body.String()) +} + +type failReader struct { +} + +func (f *failReader) Read(p []byte) (n int, err error) { + return 0, errors.New("expected") +} +func TestFailYAMLReader(t *testing.T) { + cons := YAMLConsumer() + assert.Error(t, cons.Consume(&failReader{}, nil)) +} diff --git a/vendor/github.com/go-openapi/strfmt/.editorconfig b/vendor/github.com/go-openapi/strfmt/.editorconfig new file mode 100644 index 0000000000..3152da69a5 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/.editorconfig @@ -0,0 +1,26 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +# Set default charset +[*.{js,py,go,scala,rb,java,html,css,less,sass,md}] +charset = utf-8 + +# Tab indentation (no size specified) +[*.go] +indent_style = tab + +[*.md] +trim_trailing_whitespace = false + +# Matches the exact files either package.json or .travis.yml +[{package.json,.travis.yml}] +indent_style = space +indent_size = 2 diff --git a/vendor/github.com/go-openapi/strfmt/.github/CONTRIBUTING.md b/vendor/github.com/go-openapi/strfmt/.github/CONTRIBUTING.md new file mode 100644 index 0000000000..7dea4240d7 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/.github/CONTRIBUTING.md @@ -0,0 +1,117 @@ +## Contribution Guidelines + +### Pull requests are always welcome + +We are always thrilled to receive pull requests, and do our best to +process them as fast as possible. Not sure if that typo is worth a pull +request? Do it! We will appreciate it. + +If your pull request is not accepted on the first try, don't be +discouraged! If there's a problem with the implementation, hopefully you +received feedback on what to improve. + +We're trying very hard to keep go-swagger lean and focused. We don't want it +to do everything for everybody. This means that we might decide against +incorporating a new feature. However, there might be a way to implement +that feature *on top of* go-swagger. + + +### Conventions + +Fork the repo and make changes on your fork in a feature branch: + +- If it's a bugfix branch, name it XXX-something where XXX is the number of the + issue +- If it's a feature branch, create an enhancement issue to announce your + intentions, and name it XXX-something where XXX is the number of the issue. + +Submit unit tests for your changes. Go has a great test framework built in; use +it! Take a look at existing tests for inspiration. Run the full test suite on +your branch before submitting a pull request. + +Update the documentation when creating or modifying features. Test +your documentation changes for clarity, concision, and correctness, as +well as a clean documentation build. See ``docs/README.md`` for more +information on building the docs and how docs get released. + +Write clean code. Universally formatted code promotes ease of writing, reading, +and maintenance. Always run `gofmt -s -w file.go` on each changed file before +committing your changes. Most editors have plugins that do this automatically. + +Pull requests descriptions should be as clear as possible and include a +reference to all the issues that they address. + +Pull requests must not contain commits from other users or branches. + +Commit messages must start with a capitalized and short summary (max. 50 +chars) written in the imperative, followed by an optional, more detailed +explanatory text which is separated from the summary by an empty line. + +Code review comments may be added to your pull request. Discuss, then make the +suggested modifications and push additional commits to your feature branch. Be +sure to post a comment after pushing. The new commits will show up in the pull +request automatically, but the reviewers will not be notified unless you +comment. + +Before the pull request is merged, make sure that you squash your commits into +logical units of work using `git rebase -i` and `git push -f`. After every +commit the test suite should be passing. Include documentation changes in the +same commit so that a revert would remove all traces of the feature or fix. + +Commits that fix or close an issue should include a reference like `Closes #XXX` +or `Fixes #XXX`, which will automatically close the issue when merged. + +### Sign your work + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right to +pass it on as an open-source patch. The rules are pretty simple: if you +can certify the below (from +[developercertificate.org](http://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +You can add the sign off when creating the git commit via `git commit -s`. diff --git a/vendor/github.com/go-openapi/strfmt/.gitignore b/vendor/github.com/go-openapi/strfmt/.gitignore new file mode 100644 index 0000000000..dd91ed6a04 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/.gitignore @@ -0,0 +1,2 @@ +secrets.yml +coverage.out diff --git a/vendor/github.com/go-openapi/strfmt/.travis.yml b/vendor/github.com/go-openapi/strfmt/.travis.yml new file mode 100644 index 0000000000..88a3a6eae2 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/.travis.yml @@ -0,0 +1,18 @@ +language: go +go: +- 1.7.1 +install: +- go get -u github.com/stretchr/testify/assert +- go get -u github.com/pborman/uuid +- go get -u github.com/asaskevich/govalidator +- go get -u github.com/mailru/easyjson +- go get -u github.com/go-openapi/errors +- go get -u github.com/mitchellh/mapstructure +- go get -u gopkg.in/mgo.v2/bson +script: +- ./hack/coverage +after_success: +- bash <(curl -s https://codecov.io/bash) +notifications: + slack: + secure: zE5AtIYTpYfQPnTzP+EaQPN7JKtfFAGv6PrJqoIZLOXa8B6zGb6+J1JRNNxWi7faWbyJOxa4FSSsuPsKZMycUK6wlLFIdhDxwqeo7Ew8r6rdZKdfUHQggfNS9wO79ARoNYUDHtmnaBUS+eWSM1YqSc4i99QxyyfuURLOeAaA/q14YbdlTlaw3lrZ0qT92ot1FnVGNOx064zuHtFeUf+jAVRMZ6Q3rvqllwIlPszE6rmHGXBt2VoJxRaBetdwd7FgkcYw9FPXKHhadwC7/75ZAdmxIukhxNMw4Tr5NuPcqNcnbYLenDP7B3lssGVIrP4BRSqekS1d/tqvdvnnFWHMwrNCkSnSc065G5+qWTlXKAemIclgiXXqE2furBNLm05MDdG8fn5epS0UNarkjD+zX336RiqwBlOX4KbF+vPyqcO98CsN0lnd+H6loc9reiTHs37orFFpQ+309av9be2GGsHUsRB9ssIyrewmhAccOmkRtr2dVTZJNFQwa5Kph5TNJuTjnZEwG/xUkEX2YSfwShOsb062JWiflV6PJdnl80pc9Tn7D5sO5Bf9DbijGRJwwP+YiiJtwtr+vsvS+n4sM0b5eqm4UoRo+JJO8ffoJtHS7ItuyRbVQCwEPJ4221WLcf5PquEEDdAPwR+K4Gj8qTXqTDdxOiES1xFUKVgmzhI= diff --git a/vendor/github.com/go-openapi/strfmt/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/strfmt/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..9322b065e3 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at ivan+abuse@flanders.co.nz. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/strfmt/LICENSE b/vendor/github.com/go-openapi/strfmt/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/go-openapi/strfmt/README.md b/vendor/github.com/go-openapi/strfmt/README.md new file mode 100644 index 0000000000..9d1300e8e0 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/README.md @@ -0,0 +1,5 @@ +# Strfmt [![Build Status](https://travis-ci.org/go-openapi/strfmt.svg?branch=master)](https://travis-ci.org/go-openapi/strfmt) [![codecov](https://codecov.io/gh/go-openapi/strfmt/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/strfmt) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) + +[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/strfmt/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/strfmt?status.svg)](http://godoc.org/github.com/go-openapi/strfmt) + +strfmt represents a well known string format such as credit card or email. The go toolkit for open api specifications knows how to deal with those. diff --git a/vendor/github.com/go-openapi/strfmt/bson.go b/vendor/github.com/go-openapi/strfmt/bson.go new file mode 100644 index 0000000000..39c6d8f7eb --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/bson.go @@ -0,0 +1,124 @@ +// 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 strfmt + +import ( + "database/sql/driver" + "errors" + "fmt" + + "github.com/mailru/easyjson/jlexer" + "github.com/mailru/easyjson/jwriter" + + "gopkg.in/mgo.v2/bson" +) + +func init() { + var id ObjectId + Default.Add("bsonobjectid", &id, IsBSONObjectID) +} + +// IsBSONObjectID returns true when the string is a valid BSON.ObjectId +func IsBSONObjectID(str string) bool { + var id bson.ObjectId + return id.UnmarshalText([]byte(str)) == nil +} + +type ObjectId bson.ObjectId + +// NewObjectId creates a ObjectId from a Hex String +func NewObjectId(hex string) ObjectId { + return ObjectId(bson.ObjectIdHex(hex)) +} + +// MarshalText turns this instance into text +func (id *ObjectId) MarshalText() ([]byte, error) { + return []byte(bson.ObjectId(*id).Hex()), nil +} + +// UnmarshalText hydrates this instance from text +func (id *ObjectId) UnmarshalText(data []byte) error { // validation is performed later on + var rawID bson.ObjectId + if err := rawID.UnmarshalText(data); err != nil { + return err + } + + *id = ObjectId(rawID) + return nil +} + +// Scan read a value from a database driver +func (id *ObjectId) Scan(raw interface{}) error { + var data []byte + switch v := raw.(type) { + case []byte: + data = v + case string: + data = []byte(v) + default: + return fmt.Errorf("cannot sql.Scan() strfmt.URI from: %#v", v) + } + + return id.UnmarshalText(data) +} + +// Value converts a value to a database driver value +func (id *ObjectId) Value() (driver.Value, error) { + return driver.Value(string(*id)), nil +} + +func (id *ObjectId) String() string { + return string(*id) +} + +func (id *ObjectId) MarshalJSON() ([]byte, error) { + var w jwriter.Writer + id.MarshalEasyJSON(&w) + return w.BuildBytes() +} + +func (id *ObjectId) MarshalEasyJSON(w *jwriter.Writer) { + w.String(bson.ObjectId(*id).Hex()) +} + +func (id *ObjectId) UnmarshalJSON(data []byte) error { + l := jlexer.Lexer{Data: data} + id.UnmarshalEasyJSON(&l) + return l.Error() +} + +func (id *ObjectId) UnmarshalEasyJSON(in *jlexer.Lexer) { + if data := in.String(); in.Ok() { + *id = NewObjectId(data) + } +} + +func (id *ObjectId) GetBSON() (interface{}, error) { + return bson.M{"data": bson.ObjectId(*id).Hex()}, nil +} + +func (id *ObjectId) SetBSON(raw bson.Raw) error { + var m bson.M + if err := raw.Unmarshal(&m); err != nil { + return err + } + + if data, ok := m["data"].(string); ok { + *id = NewObjectId(data) + return nil + } + + return errors.New("couldn't unmarshal bson raw value as ObjectId") +} diff --git a/vendor/github.com/go-openapi/strfmt/bson_test.go b/vendor/github.com/go-openapi/strfmt/bson_test.go new file mode 100644 index 0000000000..32ba962b11 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/bson_test.go @@ -0,0 +1,53 @@ +// 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 strfmt + +import ( + "testing" + + "gopkg.in/mgo.v2/bson" + + "github.com/stretchr/testify/assert" +) + +func TestBSONObjectId_fullCycle(t *testing.T) { + id := NewObjectId("507f1f77bcf86cd799439011") + bytes, err := id.MarshalText() + assert.NoError(t, err) + + var idCopy ObjectId + + err = idCopy.Scan(bytes) + assert.NoError(t, err) + assert.Equal(t, id, idCopy) + + err = idCopy.UnmarshalText(bytes) + assert.NoError(t, err) + assert.Equal(t, id, idCopy) + + jsonBytes, err := id.MarshalJSON() + assert.NoError(t, err) + + err = idCopy.UnmarshalJSON(jsonBytes) + assert.NoError(t, err) + assert.Equal(t, id, idCopy) + + bsonBytes, err := bson.Marshal(&id) + assert.NoError(t, err) + + err = bson.Unmarshal(bsonBytes, &idCopy) + assert.NoError(t, err) + assert.Equal(t, id, idCopy) +} diff --git a/vendor/github.com/go-openapi/strfmt/conv/date.go b/vendor/github.com/go-openapi/strfmt/conv/date.go new file mode 100644 index 0000000000..b5c3820609 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/conv/date.go @@ -0,0 +1,18 @@ +package conv + +import "github.com/go-openapi/strfmt" + +// Date returns a pointer to of the Date value passed in. +func Date(v strfmt.Date) *strfmt.Date { + return &v +} + +// DateValue returns the value of the Date pointer passed in or +// the default value if the pointer is nil. +func DateValue(v *strfmt.Date) strfmt.Date { + if v == nil { + return strfmt.Date{} + } + + return *v +} diff --git a/vendor/github.com/go-openapi/strfmt/conv/date_test.go b/vendor/github.com/go-openapi/strfmt/conv/date_test.go new file mode 100644 index 0000000000..da9788892c --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/conv/date_test.go @@ -0,0 +1,15 @@ +package conv + +import ( + "testing" + "time" + + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +func TestDateValue(t *testing.T) { + assert.Equal(t, strfmt.Date{}, DateValue(nil)) + date := strfmt.Date(time.Now()) + assert.Equal(t, date, DateValue(&date)) +} diff --git a/vendor/github.com/go-openapi/strfmt/conv/default.go b/vendor/github.com/go-openapi/strfmt/conv/default.go new file mode 100644 index 0000000000..d00fa175e3 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/conv/default.go @@ -0,0 +1,290 @@ +package conv + +import ( + "github.com/go-openapi/strfmt" +) + +// Base64 returns a pointer to of the Base64 value passed in. +func Base64(v strfmt.Base64) *strfmt.Base64 { + return &v +} + +// Base64Value returns the value of the Base64 pointer passed in or +// the default value if the pointer is nil. +func Base64Value(v *strfmt.Base64) strfmt.Base64 { + if v == nil { + return nil + } + + return *v +} + +// URI returns a pointer to of the URI value passed in. +func URI(v strfmt.URI) *strfmt.URI { + return &v +} + +// URIValue returns the value of the URI pointer passed in or +// the default value if the pointer is nil. +func URIValue(v *strfmt.URI) strfmt.URI { + if v == nil { + return strfmt.URI("") + } + + return *v +} + +// Email returns a pointer to of the Email value passed in. +func Email(v strfmt.Email) *strfmt.Email { + return &v +} + +// EmailValue returns the value of the Email pointer passed in or +// the default value if the pointer is nil. +func EmailValue(v *strfmt.Email) strfmt.Email { + if v == nil { + return strfmt.Email("") + } + + return *v +} + +// Hostname returns a pointer to of the Hostname value passed in. +func Hostname(v strfmt.Hostname) *strfmt.Hostname { + return &v +} + +// HostnameValue returns the value of the Hostname pointer passed in or +// the default value if the pointer is nil. +func HostnameValue(v *strfmt.Hostname) strfmt.Hostname { + if v == nil { + return strfmt.Hostname("") + } + + return *v +} + +// IPv4 returns a pointer to of the IPv4 value passed in. +func IPv4(v strfmt.IPv4) *strfmt.IPv4 { + return &v +} + +// IPv4Value returns the value of the IPv4 pointer passed in or +// the default value if the pointer is nil. +func IPv4Value(v *strfmt.IPv4) strfmt.IPv4 { + if v == nil { + return strfmt.IPv4("") + } + + return *v +} + +// IPv6 returns a pointer to of the IPv6 value passed in. +func IPv6(v strfmt.IPv6) *strfmt.IPv6 { + return &v +} + +// IPv6Value returns the value of the IPv6 pointer passed in or +// the default value if the pointer is nil. +func IPv6Value(v *strfmt.IPv6) strfmt.IPv6 { + if v == nil { + return strfmt.IPv6("") + } + + return *v +} + +// MAC returns a pointer to of the MAC value passed in. +func MAC(v strfmt.MAC) *strfmt.MAC { + return &v +} + +// MACValue returns the value of the MAC pointer passed in or +// the default value if the pointer is nil. +func MACValue(v *strfmt.MAC) strfmt.MAC { + if v == nil { + return strfmt.MAC("") + } + + return *v +} + +// UUID returns a pointer to of the UUID value passed in. +func UUID(v strfmt.UUID) *strfmt.UUID { + return &v +} + +// UUIDValue returns the value of the UUID pointer passed in or +// the default value if the pointer is nil. +func UUIDValue(v *strfmt.UUID) strfmt.UUID { + if v == nil { + return strfmt.UUID("") + } + + return *v +} + +// UUID3 returns a pointer to of the UUID3 value passed in. +func UUID3(v strfmt.UUID3) *strfmt.UUID3 { + return &v +} + +// UUID3Value returns the value of the UUID3 pointer passed in or +// the default value if the pointer is nil. +func UUID3Value(v *strfmt.UUID3) strfmt.UUID3 { + if v == nil { + return strfmt.UUID3("") + } + + return *v +} + +// UUID4 returns a pointer to of the UUID4 value passed in. +func UUID4(v strfmt.UUID4) *strfmt.UUID4 { + return &v +} + +// UUID4Value returns the value of the UUID4 pointer passed in or +// the default value if the pointer is nil. +func UUID4Value(v *strfmt.UUID4) strfmt.UUID4 { + if v == nil { + return strfmt.UUID4("") + } + + return *v +} + +// UUID5 returns a pointer to of the UUID5 value passed in. +func UUID5(v strfmt.UUID5) *strfmt.UUID5 { + return &v +} + +// UUID5Value returns the value of the UUID5 pointer passed in or +// the default value if the pointer is nil. +func UUID5Value(v *strfmt.UUID5) strfmt.UUID5 { + if v == nil { + return strfmt.UUID5("") + } + + return *v +} + +// ISBN returns a pointer to of the ISBN value passed in. +func ISBN(v strfmt.ISBN) *strfmt.ISBN { + return &v +} + +// ISBNValue returns the value of the ISBN pointer passed in or +// the default value if the pointer is nil. +func ISBNValue(v *strfmt.ISBN) strfmt.ISBN { + if v == nil { + return strfmt.ISBN("") + } + + return *v +} + +// ISBN10 returns a pointer to of the ISBN10 value passed in. +func ISBN10(v strfmt.ISBN10) *strfmt.ISBN10 { + return &v +} + +// ISBN10Value returns the value of the ISBN10 pointer passed in or +// the default value if the pointer is nil. +func ISBN10Value(v *strfmt.ISBN10) strfmt.ISBN10 { + if v == nil { + return strfmt.ISBN10("") + } + + return *v +} + +// ISBN13 returns a pointer to of the ISBN13 value passed in. +func ISBN13(v strfmt.ISBN13) *strfmt.ISBN13 { + return &v +} + +// ISBN13Value returns the value of the ISBN13 pointer passed in or +// the default value if the pointer is nil. +func ISBN13Value(v *strfmt.ISBN13) strfmt.ISBN13 { + if v == nil { + return strfmt.ISBN13("") + } + + return *v +} + +// CreditCard returns a pointer to of the CreditCard value passed in. +func CreditCard(v strfmt.CreditCard) *strfmt.CreditCard { + return &v +} + +// CreditCardValue returns the value of the CreditCard pointer passed in or +// the default value if the pointer is nil. +func CreditCardValue(v *strfmt.CreditCard) strfmt.CreditCard { + if v == nil { + return strfmt.CreditCard("") + } + + return *v +} + +// SSN returns a pointer to of the SSN value passed in. +func SSN(v strfmt.SSN) *strfmt.SSN { + return &v +} + +// SSNValue returns the value of the SSN pointer passed in or +// the default value if the pointer is nil. +func SSNValue(v *strfmt.SSN) strfmt.SSN { + if v == nil { + return strfmt.SSN("") + } + + return *v +} + +// HexColor returns a pointer to of the HexColor value passed in. +func HexColor(v strfmt.HexColor) *strfmt.HexColor { + return &v +} + +// HexColorValue returns the value of the HexColor pointer passed in or +// the default value if the pointer is nil. +func HexColorValue(v *strfmt.HexColor) strfmt.HexColor { + if v == nil { + return strfmt.HexColor("") + } + + return *v +} + +// RGBColor returns a pointer to of the RGBColor value passed in. +func RGBColor(v strfmt.RGBColor) *strfmt.RGBColor { + return &v +} + +// RGBColorValue returns the value of the RGBColor pointer passed in or +// the default value if the pointer is nil. +func RGBColorValue(v *strfmt.RGBColor) strfmt.RGBColor { + if v == nil { + return strfmt.RGBColor("") + } + + return *v +} + +// Password returns a pointer to of the Password value passed in. +func Password(v strfmt.Password) *strfmt.Password { + return &v +} + +// PasswordValue returns the value of the Password pointer passed in or +// the default value if the pointer is nil. +func PasswordValue(v *strfmt.Password) strfmt.Password { + if v == nil { + return strfmt.Password("") + } + + return *v +} diff --git a/vendor/github.com/go-openapi/strfmt/conv/default_test.go b/vendor/github.com/go-openapi/strfmt/conv/default_test.go new file mode 100644 index 0000000000..b182ef7418 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/conv/default_test.go @@ -0,0 +1,122 @@ +package conv + +import ( + "testing" + + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +func TestBase64Value(t *testing.T) { + assert.Equal(t, strfmt.Base64(nil), Base64Value(nil)) + base64 := strfmt.Base64([]byte{4, 2}) + assert.Equal(t, base64, Base64Value(&base64)) +} + +func TestURIValue(t *testing.T) { + assert.Equal(t, strfmt.URI(""), URIValue(nil)) + value := strfmt.URI("foo") + assert.Equal(t, value, URIValue(&value)) +} + +func TestEmailValue(t *testing.T) { + assert.Equal(t, strfmt.Email(""), EmailValue(nil)) + value := strfmt.Email("foo") + assert.Equal(t, value, EmailValue(&value)) +} + +func TestHostnameValue(t *testing.T) { + assert.Equal(t, strfmt.Hostname(""), HostnameValue(nil)) + value := strfmt.Hostname("foo") + assert.Equal(t, value, HostnameValue(&value)) +} + +func TestIPv4Value(t *testing.T) { + assert.Equal(t, strfmt.IPv4(""), IPv4Value(nil)) + value := strfmt.IPv4("foo") + assert.Equal(t, value, IPv4Value(&value)) +} + +func TestIPv6Value(t *testing.T) { + assert.Equal(t, strfmt.IPv6(""), IPv6Value(nil)) + value := strfmt.IPv6("foo") + assert.Equal(t, value, IPv6Value(&value)) +} + +func TestMACValue(t *testing.T) { + assert.Equal(t, strfmt.MAC(""), MACValue(nil)) + value := strfmt.MAC("foo") + assert.Equal(t, value, MACValue(&value)) +} + +func TestUUIDValue(t *testing.T) { + assert.Equal(t, strfmt.UUID(""), UUIDValue(nil)) + value := strfmt.UUID("foo") + assert.Equal(t, value, UUIDValue(&value)) +} + +func TestUUID3Value(t *testing.T) { + assert.Equal(t, strfmt.UUID3(""), UUID3Value(nil)) + value := strfmt.UUID3("foo") + assert.Equal(t, value, UUID3Value(&value)) +} + +func TestUUID4Value(t *testing.T) { + assert.Equal(t, strfmt.UUID4(""), UUID4Value(nil)) + value := strfmt.UUID4("foo") + assert.Equal(t, value, UUID4Value(&value)) +} + +func TestUUID5Value(t *testing.T) { + assert.Equal(t, strfmt.UUID5(""), UUID5Value(nil)) + value := strfmt.UUID5("foo") + assert.Equal(t, value, UUID5Value(&value)) +} + +func TestISBNValue(t *testing.T) { + assert.Equal(t, strfmt.ISBN(""), ISBNValue(nil)) + value := strfmt.ISBN("foo") + assert.Equal(t, value, ISBNValue(&value)) +} + +func TestISBN10Value(t *testing.T) { + assert.Equal(t, strfmt.ISBN10(""), ISBN10Value(nil)) + value := strfmt.ISBN10("foo") + assert.Equal(t, value, ISBN10Value(&value)) +} + +func TestISBN13Value(t *testing.T) { + assert.Equal(t, strfmt.ISBN13(""), ISBN13Value(nil)) + value := strfmt.ISBN13("foo") + assert.Equal(t, value, ISBN13Value(&value)) +} + +func TestCreditCardValue(t *testing.T) { + assert.Equal(t, strfmt.CreditCard(""), CreditCardValue(nil)) + value := strfmt.CreditCard("foo") + assert.Equal(t, value, CreditCardValue(&value)) +} + +func TestSSNValue(t *testing.T) { + assert.Equal(t, strfmt.SSN(""), SSNValue(nil)) + value := strfmt.SSN("foo") + assert.Equal(t, value, SSNValue(&value)) +} + +func TestHexColorValue(t *testing.T) { + assert.Equal(t, strfmt.HexColor(""), HexColorValue(nil)) + value := strfmt.HexColor("foo") + assert.Equal(t, value, HexColorValue(&value)) +} + +func TestRGBColorValue(t *testing.T) { + assert.Equal(t, strfmt.RGBColor(""), RGBColorValue(nil)) + value := strfmt.RGBColor("foo") + assert.Equal(t, value, RGBColorValue(&value)) +} + +func TestPasswordValue(t *testing.T) { + assert.Equal(t, strfmt.Password(""), PasswordValue(nil)) + value := strfmt.Password("foo") + assert.Equal(t, value, PasswordValue(&value)) +} diff --git a/vendor/github.com/go-openapi/strfmt/conv/duration.go b/vendor/github.com/go-openapi/strfmt/conv/duration.go new file mode 100644 index 0000000000..ea30132b54 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/conv/duration.go @@ -0,0 +1,18 @@ +package conv + +import "github.com/go-openapi/strfmt" + +// Duration returns a pointer to of the Duration value passed in. +func Duration(v strfmt.Duration) *strfmt.Duration { + return &v +} + +// DurationValue returns the value of the Duration pointer passed in or +// the default value if the pointer is nil. +func DurationValue(v *strfmt.Duration) strfmt.Duration { + if v == nil { + return strfmt.Duration(0) + } + + return *v +} diff --git a/vendor/github.com/go-openapi/strfmt/conv/duration_test.go b/vendor/github.com/go-openapi/strfmt/conv/duration_test.go new file mode 100644 index 0000000000..f19173f4e6 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/conv/duration_test.go @@ -0,0 +1,14 @@ +package conv + +import ( + "testing" + + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +func TestDurationValue(t *testing.T) { + assert.Equal(t, strfmt.Duration(0), DurationValue(nil)) + duration := strfmt.Duration(42) + assert.Equal(t, duration, DurationValue(&duration)) +} diff --git a/vendor/github.com/go-openapi/strfmt/conv/time.go b/vendor/github.com/go-openapi/strfmt/conv/time.go new file mode 100644 index 0000000000..627cd12d7f --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/conv/time.go @@ -0,0 +1,18 @@ +package conv + +import "github.com/go-openapi/strfmt" + +// DateTime returns a pointer to of the DateTime value passed in. +func DateTime(v strfmt.DateTime) *strfmt.DateTime { + return &v +} + +// DateTimeValue returns the value of the DateTime pointer passed in or +// the default value if the pointer is nil. +func DateTimeValue(v *strfmt.DateTime) strfmt.DateTime { + if v == nil { + return strfmt.DateTime{} + } + + return *v +} diff --git a/vendor/github.com/go-openapi/strfmt/conv/time_test.go b/vendor/github.com/go-openapi/strfmt/conv/time_test.go new file mode 100644 index 0000000000..89a427df2c --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/conv/time_test.go @@ -0,0 +1,15 @@ +package conv + +import ( + "testing" + "time" + + "github.com/go-openapi/strfmt" + "github.com/stretchr/testify/assert" +) + +func TestDateTimeValue(t *testing.T) { + assert.Equal(t, strfmt.DateTime{}, DateTimeValue(nil)) + time := strfmt.DateTime(time.Now()) + assert.Equal(t, time, DateTimeValue(&time)) +} diff --git a/vendor/github.com/go-openapi/strfmt/date.go b/vendor/github.com/go-openapi/strfmt/date.go new file mode 100644 index 0000000000..24a11db260 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/date.go @@ -0,0 +1,152 @@ +// 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 strfmt + +import ( + "database/sql/driver" + "errors" + "fmt" + "regexp" + "time" + + "gopkg.in/mgo.v2/bson" + + "github.com/mailru/easyjson/jlexer" + "github.com/mailru/easyjson/jwriter" +) + +func init() { + d := Date{} + Default.Add("date", &d, IsDate) +} + +// IsDate returns true when the string is a valid date +func IsDate(str string) bool { + matches := rxDate.FindAllStringSubmatch(str, -1) + if len(matches) == 0 || len(matches[0]) == 0 { + return false + } + m := matches[0] + return !(m[2] < "01" || m[2] > "12" || m[3] < "01" || m[3] > "31") +} + +const ( + // RFC3339FullDate represents a full-date as specified by RFC3339 + // See: http://goo.gl/xXOvVd + RFC3339FullDate = "2006-01-02" + // DatePattern pattern to match for the date format from http://tools.ietf.org/html/rfc3339#section-5.6 + DatePattern = `^([0-9]{4})-([0-9]{2})-([0-9]{2})` +) + +var ( + rxDate = regexp.MustCompile(DatePattern) +) + +// Date represents a date from the API +// +// swagger:strfmt date +type Date time.Time + +// String converts this date into a string +func (d Date) String() string { + return time.Time(d).Format(RFC3339FullDate) +} + +// UnmarshalText parses a text representation into a date type +func (d *Date) UnmarshalText(text []byte) error { + if len(text) == 0 { + return nil + } + dd, err := time.Parse(RFC3339FullDate, string(text)) + if err != nil { + return err + } + *d = Date(dd) + return nil +} + +// MarshalText serializes this date type to string +func (d Date) MarshalText() ([]byte, error) { + return []byte(d.String()), nil +} + +// Scan scans a Date value from database driver type. +func (d *Date) Scan(raw interface{}) error { + switch v := raw.(type) { + case []byte: + return d.UnmarshalText(v) + case string: + return d.UnmarshalText([]byte(v)) + case time.Time: + *d = Date(v) + return nil + case nil: + *d = Date{} + return nil + default: + return fmt.Errorf("cannot sql.Scan() strfmt.Date from: %#v", v) + } +} + +// Value converts Date to a primitive value ready to written to a database. +func (d Date) Value() (driver.Value, error) { + return driver.Value(d.String()), nil +} + +func (t Date) MarshalJSON() ([]byte, error) { + var w jwriter.Writer + t.MarshalEasyJSON(&w) + return w.BuildBytes() +} + +func (t Date) MarshalEasyJSON(w *jwriter.Writer) { + w.String(time.Time(t).Format(RFC3339FullDate)) +} + +func (t *Date) UnmarshalJSON(data []byte) error { + l := jlexer.Lexer{Data: data} + t.UnmarshalEasyJSON(&l) + return l.Error() +} + +func (t *Date) UnmarshalEasyJSON(in *jlexer.Lexer) { + if data := in.String(); in.Ok() { + tt, err := time.Parse(RFC3339FullDate, data) + if err != nil { + in.AddError(err) + return + } + *t = Date(tt) + } +} + +func (t *Date) GetBSON() (interface{}, error) { + return bson.M{"data": t.String()}, nil +} + +func (t *Date) SetBSON(raw bson.Raw) error { + var m bson.M + if err := raw.Unmarshal(&m); err != nil { + return err + } + + if data, ok := m["data"].(string); ok { + rd, err := time.Parse(RFC3339FullDate, data) + *t = Date(rd) + return err + } + + return errors.New("couldn't unmarshal bson raw value as Duration") +} diff --git a/vendor/github.com/go-openapi/strfmt/date_test.go b/vendor/github.com/go-openapi/strfmt/date_test.go new file mode 100644 index 0000000000..87e5611177 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/date_test.go @@ -0,0 +1,83 @@ +// 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 strfmt + +import ( + "database/sql" + "database/sql/driver" + "testing" + "time" + + "gopkg.in/mgo.v2/bson" + + "github.com/stretchr/testify/assert" +) + +var _ sql.Scanner = &Date{} +var _ driver.Valuer = Date{} + +func TestDate(t *testing.T) { + pp := Date{} + err := pp.UnmarshalText([]byte{}) + assert.NoError(t, err) + err = pp.UnmarshalText([]byte("yada")) + assert.Error(t, err) + orig := "2014-12-15" + b := []byte(orig) + bj := []byte("\"" + orig + "\"") + err = pp.UnmarshalText([]byte(orig)) + assert.NoError(t, err) + txt, err := pp.MarshalText() + assert.NoError(t, err) + assert.Equal(t, orig, string(txt)) + + err = pp.UnmarshalJSON(bj) + assert.NoError(t, err) + assert.EqualValues(t, orig, pp.String()) + + b, err = pp.MarshalJSON() + assert.NoError(t, err) + assert.Equal(t, bj, b) + + dateOriginal := Date(time.Date(2014, 10, 10, 0, 0, 0, 0, time.UTC)) + + bsonData, err := bson.Marshal(&dateOriginal) + assert.NoError(t, err) + + var dateCopy Date + err = bson.Unmarshal(bsonData, &dateCopy) + assert.NoError(t, err) + assert.Equal(t, dateOriginal, dateCopy) +} + +func TestDate_Scan(t *testing.T) { + ref := time.Now().Truncate(24 * time.Hour).UTC() + date, str := Date(ref), ref.Format(RFC3339FullDate) + + values := []interface{}{str, []byte(str), ref} + for _, value := range values { + result := Date{} + (&result).Scan(value) + assert.Equal(t, date, result, "value: %#v", value) + } +} + +func TestDate_Value(t *testing.T) { + ref := time.Now().Truncate(24 * time.Hour).UTC() + date := Date(ref) + dbv, err := date.Value() + assert.NoError(t, err) + assert.EqualValues(t, dbv, ref.Format("2006-01-02")) +} diff --git a/vendor/github.com/go-openapi/strfmt/default.go b/vendor/github.com/go-openapi/strfmt/default.go new file mode 100644 index 0000000000..437142a300 --- /dev/null +++ b/vendor/github.com/go-openapi/strfmt/default.go @@ -0,0 +1,1697 @@ +// 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 strfmt + +import ( + "database/sql/driver" + "encoding/base64" + "errors" + "fmt" + "regexp" + "strings" + + "github.com/asaskevich/govalidator" + "github.com/mailru/easyjson/jlexer" + "github.com/mailru/easyjson/jwriter" + + "gopkg.in/mgo.v2/bson" +) + +const ( + // HostnamePattern http://json-schema.org/latest/json-schema-validation.html#anchor114 + // A string instance is valid against this attribute if it is a valid + // representation for an Internet host name, as defined by RFC 1034, section 3.1 [RFC1034]. + // http://tools.ietf.org/html/rfc1034#section-3.5 + // ::= any one of the ten digits 0 through 9 + // var digit = /[0-9]/; + // ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case + // var letter = /[a-zA-Z]/; + // ::= | + // var letDig = /[0-9a-zA-Z]/; + // ::= | "-" + // var letDigHyp = /[-0-9a-zA-Z]/; + // ::= | + // var ldhStr = /[-0-9a-zA-Z]+/; + //