swagger-parser 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +23 -0
  6. data/.travis.yml +6 -0
  7. data/.yardopts +4 -0
  8. data/Gemfile +5 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +114 -0
  11. data/Rakefile +11 -0
  12. data/lib/swagger.rb +56 -0
  13. data/lib/swagger/api.rb +26 -0
  14. data/lib/swagger/attachable.rb +39 -0
  15. data/lib/swagger/boolean.rb +13 -0
  16. data/lib/swagger/builder.rb +109 -0
  17. data/lib/swagger/mime_type.rb +46 -0
  18. data/lib/swagger/notes.md +35 -0
  19. data/lib/swagger/parsers.rb +36 -0
  20. data/lib/swagger/schema.rb +63 -0
  21. data/lib/swagger/swagger_object.rb +49 -0
  22. data/lib/swagger/uri.rb +11 -0
  23. data/lib/swagger/uri_template.rb +11 -0
  24. data/lib/swagger/v2/api.rb +90 -0
  25. data/lib/swagger/v2/deterministic_json_schema.rb +130 -0
  26. data/lib/swagger/v2/example.rb +32 -0
  27. data/lib/swagger/v2/header.rb +22 -0
  28. data/lib/swagger/v2/info.rb +33 -0
  29. data/lib/swagger/v2/operation.rb +66 -0
  30. data/lib/swagger/v2/parameter.rb +35 -0
  31. data/lib/swagger/v2/path.rb +47 -0
  32. data/lib/swagger/v2/response.rb +26 -0
  33. data/lib/swagger/v2/security_requirement.rb +12 -0
  34. data/lib/swagger/v2/security_scheme.rb +25 -0
  35. data/lib/swagger/v2/tag.rb +11 -0
  36. data/lib/swagger/version.rb +3 -0
  37. data/resources/schemas/json_schema/draft-04.json +150 -0
  38. data/resources/schemas/swagger/v2.0/schema.json +1483 -0
  39. data/spec/fixtures/custom-properties.yaml +61 -0
  40. data/spec/fixtures/petstore-full.yaml +245 -0
  41. data/spec/fixtures/swagger.yaml +100 -0
  42. data/spec/spec_helper.rb +2 -0
  43. data/spec/swagger/api_spec.rb +87 -0
  44. data/spec/swagger/builder_spec.rb +52 -0
  45. data/spec/swagger/custom_properties_spec.rb +22 -0
  46. data/spec/swagger/info_spec.rb +76 -0
  47. data/spec/swagger/operation_spec.rb +99 -0
  48. data/spec/swagger/swagger_spec.rb +74 -0
  49. data/swagger-parser.gemspec +32 -0
  50. metadata +250 -0
@@ -0,0 +1,46 @@
1
+ require 'mime/types'
2
+
3
+ module Swagger
4
+ # Class representing Media Types (commonly known as MIME Types).
5
+ # @see http://en.wikipedia.org/wiki/Internet_media_type
6
+ class MimeType < String
7
+ extend Forwardable
8
+ def_delegators :@mime_type, :media_type, :sub_type
9
+
10
+ MIME_TYPE_FORMAT = /(\w+)\/(\w+\.)?([\w\.]+)(\+\w+)?\s*(;.*)?/
11
+
12
+ COMMON_ALIASES = {
13
+ txt: 'text/plain',
14
+ text: 'text/plain',
15
+ json: 'application/json',
16
+ xml: 'application/xml',
17
+ binary: 'application/octet-stream'
18
+ }
19
+
20
+ def initialize(mime_type_name)
21
+ @mime_type_name = mime_type_name.to_s
22
+ @mime_type = MIME::Types[@mime_type_name].first || base_type(@mime_type_name)
23
+ #fail ArgumentError, "Unknown mime type or suffix: #{mime_type_name}" if @mime_type.nil?
24
+ @mime_type ||= MIME::Types["text/plain"].first
25
+ super @mime_type_name
26
+ end
27
+
28
+ def self.parser_for(mime_type)
29
+ mime_type = COMMON_ALIASES[mime_type] if COMMON_ALIASES.key? mime_type
30
+ case mime_type
31
+ when 'application/json'
32
+ return JSON
33
+ else
34
+ fail NotImplementedError, "Parser support for #{mime_type} is not implemented"
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def base_type(mime_type_name)
41
+ media_type, _sub_type, _tree, suffix, _parameters = MIME_TYPE_FORMAT.match mime_type_name
42
+ return MIME::Types["#{media_type}/#{suffix}"].first if media_type && suffix
43
+ nil
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,35 @@
1
+ Classes added to Swagger-Core (Java) for 2.0:
2
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/converter/ModelConverters.java
3
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Contact.java
4
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Info.java
5
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/License.java
6
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Model.java
7
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/ModelFactory.java
8
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Operation.java
9
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Path.java
10
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/RefModel.java
11
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Response.java
12
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Scheme.java
13
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Security.java
14
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/Swagger.java
15
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/AbstractParameter.java
16
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/BodyParameter.java
17
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/CookieParameter.java
18
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/HeaderParameter.java
19
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/Parameter.java
20
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/PathParameter.java
21
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/parameters/QueryParameter.java
22
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/AbstractProperty.java
23
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/ArrayProperty.java
24
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/BooleanProperty.java
25
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/DateProperty.java
26
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/DateTimeProperty.java
27
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/DoubleProperty.java
28
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/IntegerProperty.java
29
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/LongProperty.java
30
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/MapProperty.java
31
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/Property.java
32
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/RefProperty.java
33
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/StringProperty.java
34
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/models/properties/Xml.java
35
+ - [] modules/swagger-core/src/main/java/com/wordnik/swagger/util/Json.java
@@ -0,0 +1,36 @@
1
+ autoload :YAML, 'yaml'
2
+ autoload :JSON, 'json'
3
+
4
+ module Swagger
5
+ # Provides classes for loading Swagger from YAML or JSON.
6
+ module Parsers
7
+ def self.parser_for(format)
8
+ case format
9
+ when '.yaml', '.yml', :yaml
10
+ YAMLParser
11
+ when '.json', '.js', :json
12
+ JSONParser
13
+ end
14
+ end
15
+
16
+ # Parses YAML content
17
+ class YAMLParser
18
+ # Parses a YAML document
19
+ # @param content [String] The YAML content to parse
20
+ # @return [Hash] the parsed content
21
+ def self.parse(content)
22
+ YAML.load(content)
23
+ end
24
+ end
25
+
26
+ # Parses JSON content
27
+ class JSONParser
28
+ # Parses a JSON document
29
+ # @param content [String] The JSON content to parse
30
+ # @return [Hash] the parsed content
31
+ def self.parse(content)
32
+ JSON.parse(content)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,63 @@
1
+ module Swagger
2
+ # Represents a Swagger Schema Object, a more deterministic subset of JSON Schema.
3
+ # @see https://github.com/wordnik/swagger-spec/blob/master/versions/2.0.md#schema-object- Schema Object
4
+ # @see http://json-schema.org/ JSON Schema
5
+ class Schema < Hashie::Mash
6
+ include Attachable
7
+ include Hashie::Extensions::MergeInitializer
8
+ include Hashie::Extensions::DeepFind
9
+ attr_accessor :parent
10
+
11
+ def initialize(hash, default = nil)
12
+ super
13
+ attach_to_children
14
+ end
15
+
16
+ def parse
17
+ schema = clone
18
+ if schema.key?('$ref')
19
+ key = schema.delete('$ref').split('/').last
20
+ model = root.definitions[key]
21
+ schema.merge!(model)
22
+ end
23
+
24
+ count = 0
25
+ until schema.refs_resolved?
26
+ fail 'Could not resolve non-remote $refs 5 cycles - circular references?' if count >= 5
27
+ schema.resolve_refs
28
+ count += 1
29
+ end
30
+
31
+ schema.to_hash
32
+ end
33
+
34
+ protected
35
+
36
+ def refs
37
+ deep_find_all('$ref')
38
+ end
39
+
40
+ def resolve_refs
41
+ children.each do |child|
42
+ child.resolve_refs if child.is_a?(Swagger::Schema)
43
+ end
44
+ key = self.delete('$ref')
45
+ return if key.nil? || remote_ref?(key)
46
+ key = key.split('/').last
47
+ model = root.definitions[key]
48
+ self.merge!(model)
49
+ end
50
+
51
+ def refs_resolved?
52
+ return true if refs.nil?
53
+
54
+ refs.all? do |ref|
55
+ remote_ref?(ref)
56
+ end
57
+ end
58
+
59
+ def remote_ref?(ref)
60
+ ref.match(%r{\A\w+\://})
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ module Swagger
2
+ # A class that represents an Object defined in the Swagger specification.
3
+ # Provides methods for defining fields in the object.
4
+ class SwaggerObject < Hashie::Dash
5
+ include Hashie::Extensions::Coercion
6
+ include Hashie::Extensions::IndifferentAccess
7
+ include Swagger::Attachable
8
+
9
+ CUSTOM_PROPERTY_PREFIX = /^x\-/
10
+
11
+ # Swagger allows any properties starting with `x-`
12
+ def self.property?(name)
13
+ super(name) || name.to_s =~ CUSTOM_PROPERTY_PREFIX
14
+ end
15
+
16
+ attr_accessor :parent
17
+
18
+ # @api private
19
+ # Initializes a Swagger object, using Hashie::Dash,
20
+ # and attaches to children objects so navigation via +parent+
21
+ # and +root+ is possible.
22
+ def initialize(hash)
23
+ super
24
+ attach_to_children
25
+ end
26
+
27
+ # @api private
28
+ # @!macro [attach] field
29
+ # @!attribute [rw] $1
30
+ # Swagger field $1. $3
31
+ # @return [$2]
32
+ # Defines a Swagger field on a class.
33
+ def self.field(name, type, opts = {})
34
+ property name, opts
35
+ coerce_key name, type
36
+ end
37
+
38
+ # @api private
39
+ # @!macro [attach] required_field
40
+ # @!attribute [rw] $1
41
+ # **Required** Swagger field $1. $3
42
+ # @return [$2]
43
+ # Defines a required Swagger field on a class.
44
+ def self.required_field(name, type, opts = {})
45
+ opts[:required] = true
46
+ field(name, type, opts)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ module Swagger
2
+ # Class representing a URI. Backed by Addressable::URI.
3
+ # @see http://en.wikipedia.org/wiki/Uniform_resource_identifier
4
+ class URI < String
5
+ attr_reader :uri
6
+ def initialize(string)
7
+ @uri = Addressable::URI.heuristic_parse string
8
+ super
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Swagger
2
+ # Class representing a URI Template. Backed by Addressable::Template.
3
+ # @see http://tools.ietf.org/html/rfc6570
4
+ class URITemplate < String
5
+ attr_reader :uri_template
6
+ def initialize(string)
7
+ @uri_template = Addressable::Template.new(string)
8
+ super
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,90 @@
1
+ require 'swagger/swagger_object'
2
+ require 'swagger/v2/deterministic_json_schema'
3
+ require 'swagger/v2/info'
4
+ require 'swagger/v2/path'
5
+ require 'swagger/v2/tag'
6
+ require 'swagger/v2/security_scheme'
7
+ require 'swagger/v2/security_requirement'
8
+ require 'json-schema'
9
+
10
+ module Swagger
11
+ # Module containing classes that handle version 2 of the Swagger specification.
12
+ # @see https://github.com/wordnik/swagger-spec/blob/master/versions/2.0.md Swagger Specification 2.0
13
+ module V2
14
+ SWAGGER_SCHEMA = File.expand_path 'schemas/swagger/v2.0/schema.json', Swagger::RESOURCES_DIR
15
+ JSON_SCHEMA = File.expand_path 'schemas/json_schema/draft-04.json', Swagger::RESOURCES_DIR
16
+
17
+ # Class representing the top level "Swagger Object"
18
+ # @see https://github.com/wordnik/swagger-spec/blob/master/versions/2.0.md#swagger-object- Swagger Object
19
+ class API < Swagger::API
20
+ # @group Swagger Fields
21
+ required_field :swagger, String
22
+ required_field :info, Info
23
+ field :host, Swagger::URITemplate
24
+ field :basePath, Swagger::URITemplate
25
+ field :schemes, Array[String]
26
+ field :consumes, Array[String]
27
+ field :produces, Array[String]
28
+ required_field :paths, Hash[String => Path]
29
+ field :definitions, Hash[String => Schema]
30
+ field :parameters, Hash[String => Parameter]
31
+ field :responses, Hash[String => Response]
32
+ field :securityDefinitions, Hash[String => SecurityScheme]
33
+ field :security, Array[SecurityRequirement]
34
+ field :tags, Array[Object] # FIXME: This is actually an array of Tag objects
35
+ field :externalDocs, Object # TODO: ExternalDocs class
36
+ # @endgroup
37
+
38
+ alias_method :base_path, :basePath
39
+
40
+ # All operations under all paths
41
+ # @return [Array<Operation>]
42
+ def operations
43
+ # Perhaps not the best way...
44
+ paths.values.map do |path|
45
+ path.operations.values
46
+ end.flatten
47
+ end
48
+
49
+ # A complete (including host) URI Template for the basePath.
50
+ # @return [Swagger::URITemplate]
51
+ def uri_template
52
+ Swagger::URITemplate.new("#{host}#{basePath}")
53
+ end
54
+
55
+ # Validates this object against the Swagger specification and returns all detected errors.
56
+ # Slower than {#validate}.
57
+ # @return [true] if the object fully complies with the Swagger specification.
58
+ # @raise [Swagger::InvalidDefinition] if any errors are found.
59
+ def fully_validate
60
+ # NOTE: fully_validate is ideal, but very slow with the current schema/validator
61
+ errors = JSON::Validator.fully_validate(swagger_schema, to_json)
62
+ fail Swagger::InvalidDefinition, errors unless errors.empty?
63
+ true
64
+ end
65
+
66
+ # Validates this object against the Swagger specification and returns the first detected error.
67
+ # Faster than {#fully_validate}.
68
+ # @return [true] if the object fully complies with the Swagger specification.
69
+ # @raise [Swagger::InvalidDefinition] if an error is found.
70
+ def validate
71
+ JSON::Validator.validate!(swagger_schema, to_json)
72
+ rescue JSON::Schema::ValidationError => e
73
+ raise Swagger::InvalidDefinition, e.message
74
+ end
75
+
76
+ private
77
+
78
+ def swagger_schema
79
+ @swagger_schema ||= JSON.parse(File.read(SWAGGER_SCHEMA))
80
+
81
+ # FIXME: Swagger should be able to parse offline. Blocked by json-schema.
82
+ # Offline workaround
83
+ # @swagger_schema = JSON.parse(File.read(SWAGGER_SCHEMA)
84
+ # .gsub('http://json-schema.org/draft-04/schema', "file://#{SWAGGER_SCHEMA}"))
85
+ # @swagger_schema['$schema'] = 'http://json-schema.org/draft-04/schema#'
86
+ # @swagger_schema
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,130 @@
1
+ module Swagger
2
+ module V2
3
+ # A Swagger Schema Object, which is subset of JSON-Schema that's constrainted to be more deterministic.
4
+ # @see https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#schema-object- Schema Object
5
+ # @see http://json-schema.org/ JSON-Schema
6
+ module DeterministicJSONSchema
7
+ # FIXME: yard group doesn't seem to work below
8
+
9
+ # @!group Deterministic JSON Schema
10
+ # @!attribute [rw] $ref
11
+ # JSON-Schema field $ref.
12
+ # @return String
13
+ # @!attribute [rw] format
14
+ # JSON-Schema field format.
15
+ # @return String
16
+ # @!attribute [rw] title
17
+ # JSON-Schema field title.
18
+ # @return String
19
+ # @!attribute [rw] description
20
+ # JSON-Schema field description.
21
+ # @return String
22
+ # @!attribute [rw] default
23
+ # JSON-Schema field default.
24
+ # @return Object
25
+ # @!attribute [rw] multipleOf
26
+ # JSON-Schema field multipleOf.
27
+ # @return Object
28
+ # @!attribute [rw] maximum
29
+ # JSON-Schema field maximum.
30
+ # @return Numeric
31
+ # @!attribute [rw] exclusiveMaximum
32
+ # JSON-Schema field exclusiveMaximum.
33
+ # @return boolean
34
+ # @!attribute [rw] minimum
35
+ # JSON-Schema field minimum.
36
+ # @return Numeric
37
+ # @!attribute [rw] exclusiveMinimum
38
+ # JSON-Schema field exclusiveMinimum.
39
+ # @return boolean
40
+ # @!attribute [rw] minLength
41
+ # JSON-Schema field minLength.
42
+ # @return Integer
43
+ # @!attribute [rw] maxLength
44
+ # JSON-Schema field maxLength.
45
+ # @return Integer
46
+ # @!attribute [rw] pattern
47
+ # JSON-Schema field pattern.
48
+ # @return Regexp
49
+ # @!attribute [rw] minItems
50
+ # JSON-Schema field minItems.
51
+ # @return Integer
52
+ # @!attribute [rw] maxItems
53
+ # JSON-Schema field maxItems.
54
+ # @return Integer
55
+ # @!attribute [rw] uniqueItems
56
+ # JSON-Schema field uniqueItems.
57
+ # @return boolean
58
+ # @!attribute [rw] maxProperties
59
+ # JSON-Schema field maxProperties.
60
+ # @return Integer
61
+ # @!attribute [rw] minProperties
62
+ # JSON-Schema field minProperties.
63
+ # @return Integer
64
+ # @!attribute [rw] required
65
+ # JSON-Schema field required.
66
+ # @return boolean
67
+ # @!attribute [rw] enum
68
+ # JSON-Schema field enum.
69
+ # @return Array[Object]
70
+ # @!attribute [rw] type
71
+ # JSON-Schema field type.
72
+ # @return Object
73
+ # @!endgroup
74
+
75
+ # @!group Swagger specific extensions
76
+ # @!attribute [rw] discriminator
77
+ # Swagger Schema field discriminator.
78
+ # @return String
79
+ # @!attribute [rw] readOnly
80
+ # Swagger Schema field readOnly.
81
+ # @return boolean
82
+ # @!attribute [rw] xml
83
+ # Swagger Schema field xml.
84
+ # @return Object
85
+ # @!attribute [rw] externalDocs
86
+ # Swagger Schema field externalDocs.
87
+ # @return ExternalDocumentation
88
+ # @!attribute [rw] example
89
+ # Swagger Schema field example.
90
+ # @return Object
91
+ # @!endgroup
92
+
93
+ def self.included(base) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
94
+ # Subset of standard JSON schema
95
+ base.field :$ref, String
96
+ base.field :format, String
97
+ base.field :title, String
98
+ base.field :description, String
99
+ base.field :default, Object
100
+ base.field :multipleOf, Numeric
101
+ base.field :maximum, Numeric
102
+ base.field :exclusiveMaximum, Swagger::Boolean
103
+ base.send(:alias_method, :exclusiveMaximum?, :exclusiveMaximum)
104
+ base.field :minimum, Numeric
105
+ base.field :exclusiveMinimum, Swagger::Boolean
106
+ base.send(:alias_method, :exclusiveMinimum?, :exclusiveMinimum)
107
+ base.field :maxLength, Integer
108
+ base.field :minLength, Integer
109
+ base.field :pattern, String
110
+ base.field :maxItems, Integer
111
+ base.field :minItems, Integer
112
+ base.field :uniqueItems, Swagger::Boolean
113
+ base.send(:alias_method, :uniqueItems?, :uniqueItems)
114
+ base.field :maxProperties, Integer
115
+ base.field :minProperties, Integer
116
+ base.field :required, Swagger::Boolean
117
+ base.send(:alias_method, :required?, :required)
118
+ base.field :enum, Array[Object]
119
+ base.field :type, Object
120
+
121
+ # Swagger extensions to JSON schema :\
122
+ base.field :discriminator, String
123
+ base.field :readOnly, Swagger::Boolean
124
+ base.field :xml, Object # TODO: Swagger XML object / XML support
125
+ base.field :externalDocs, Object # TODO: ExternalDocumentation class
126
+ base.field :example, Object
127
+ end
128
+ end
129
+ end
130
+ end