committee 3.1.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/bin/committee-stub +1 -0
  3. data/lib/committee.rb +12 -34
  4. data/lib/committee/bin/committee_stub.rb +6 -4
  5. data/lib/committee/drivers.rb +15 -67
  6. data/lib/committee/drivers/driver.rb +47 -0
  7. data/lib/committee/drivers/hyper_schema.rb +8 -171
  8. data/lib/committee/drivers/hyper_schema/driver.rb +105 -0
  9. data/lib/committee/drivers/hyper_schema/link.rb +68 -0
  10. data/lib/committee/drivers/hyper_schema/schema.rb +22 -0
  11. data/lib/committee/drivers/open_api_2.rb +9 -416
  12. data/lib/committee/drivers/open_api_2/driver.rb +253 -0
  13. data/lib/committee/drivers/open_api_2/header_schema_builder.rb +33 -0
  14. data/lib/committee/drivers/open_api_2/link.rb +36 -0
  15. data/lib/committee/drivers/open_api_2/parameter_schema_builder.rb +83 -0
  16. data/lib/committee/drivers/open_api_2/schema.rb +26 -0
  17. data/lib/committee/drivers/open_api_2/schema_builder.rb +33 -0
  18. data/lib/committee/drivers/open_api_3.rb +7 -75
  19. data/lib/committee/drivers/open_api_3/driver.rb +51 -0
  20. data/lib/committee/drivers/open_api_3/schema.rb +41 -0
  21. data/lib/committee/drivers/schema.rb +23 -0
  22. data/lib/committee/errors.rb +2 -0
  23. data/lib/committee/middleware.rb +11 -0
  24. data/lib/committee/middleware/base.rb +38 -34
  25. data/lib/committee/middleware/request_validation.rb +51 -30
  26. data/lib/committee/middleware/response_validation.rb +49 -26
  27. data/lib/committee/middleware/stub.rb +55 -51
  28. data/lib/committee/request_unpacker.rb +3 -1
  29. data/lib/committee/schema_validator.rb +23 -0
  30. data/lib/committee/schema_validator/hyper_schema.rb +85 -74
  31. data/lib/committee/schema_validator/hyper_schema/parameter_coercer.rb +60 -54
  32. data/lib/committee/schema_validator/hyper_schema/request_validator.rb +43 -37
  33. data/lib/committee/schema_validator/hyper_schema/response_generator.rb +86 -80
  34. data/lib/committee/schema_validator/hyper_schema/response_validator.rb +65 -59
  35. data/lib/committee/schema_validator/hyper_schema/router.rb +35 -29
  36. data/lib/committee/schema_validator/hyper_schema/string_params_coercer.rb +87 -81
  37. data/lib/committee/schema_validator/open_api_3.rb +71 -61
  38. data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +121 -115
  39. data/lib/committee/schema_validator/open_api_3/request_validator.rb +24 -18
  40. data/lib/committee/schema_validator/open_api_3/response_validator.rb +22 -16
  41. data/lib/committee/schema_validator/open_api_3/router.rb +30 -24
  42. data/lib/committee/schema_validator/option.rb +42 -38
  43. data/lib/committee/test/methods.rb +55 -51
  44. data/lib/committee/validation_error.rb +2 -0
  45. data/test/bin/committee_stub_test.rb +3 -1
  46. data/test/bin_test.rb +3 -1
  47. data/test/committee_test.rb +3 -1
  48. data/test/drivers/hyper_schema/driver_test.rb +49 -0
  49. data/test/drivers/{hyper_schema_test.rb → hyper_schema/link_test.rb} +2 -45
  50. data/test/drivers/open_api_2/driver_test.rb +156 -0
  51. data/test/drivers/open_api_2/header_schema_builder_test.rb +26 -0
  52. data/test/drivers/open_api_2/link_test.rb +52 -0
  53. data/test/drivers/open_api_2/parameter_schema_builder_test.rb +195 -0
  54. data/test/drivers/{open_api_3_test.rb → open_api_3/driver_test.rb} +5 -3
  55. data/test/drivers_test.rb +12 -10
  56. data/test/middleware/base_test.rb +3 -1
  57. data/test/middleware/request_validation_open_api_3_test.rb +4 -2
  58. data/test/middleware/request_validation_test.rb +46 -5
  59. data/test/middleware/response_validation_open_api_3_test.rb +3 -1
  60. data/test/middleware/response_validation_test.rb +39 -4
  61. data/test/middleware/stub_test.rb +3 -1
  62. data/test/request_unpacker_test.rb +2 -2
  63. data/test/schema_validator/hyper_schema/parameter_coercer_test.rb +2 -2
  64. data/test/schema_validator/hyper_schema/request_validator_test.rb +3 -1
  65. data/test/schema_validator/hyper_schema/response_generator_test.rb +3 -1
  66. data/test/schema_validator/hyper_schema/response_validator_test.rb +3 -1
  67. data/test/schema_validator/hyper_schema/router_test.rb +5 -3
  68. data/test/schema_validator/hyper_schema/string_params_coercer_test.rb +3 -1
  69. data/test/schema_validator/open_api_3/operation_wrapper_test.rb +3 -1
  70. data/test/schema_validator/open_api_3/request_validator_test.rb +11 -1
  71. data/test/schema_validator/open_api_3/response_validator_test.rb +3 -1
  72. data/test/test/methods_new_version_test.rb +3 -1
  73. data/test/test/methods_test.rb +4 -2
  74. data/test/test_helper.rb +16 -16
  75. data/test/validation_error_test.rb +3 -1
  76. metadata +52 -6
  77. data/lib/committee/schema_validator/schema_validator.rb +0 -15
  78. data/test/drivers/open_api_2_test.rb +0 -416
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0261ef5b9991afdc79316a4aa67e05293b5cc0dc83a8b7dc80a330fcc2d633b9
4
- data.tar.gz: a67badbaa49fa492e9bd562293666734a9c733a9d5fa8c54b6a7cf6b3a414305
3
+ metadata.gz: 169dfa8f079626447ca5086429c0bd025d8180f3ef5b7a7194d1333bdeff8fab
4
+ data.tar.gz: 2c8eeece5b411266f482808b7caf08d2de285f64e78e705990a4b7b9606902d3
5
5
  SHA512:
6
- metadata.gz: 8de3637d5059cb2dee41b9d78aa6b448d3c60fc246485bca06cbceb1e2f993c8b86f9d76a9388359c1f05b05e429eaf5949d6e6dfd587246ac4ab8c59f0f37bd
7
- data.tar.gz: 510f84e62e9f52239845130b14a6f9432bc2c391c92ab5334b74b301c9119378a491add7f7cfb33fd711a522b727da325a045be31e04ac94fd8c0ead858042a6
6
+ metadata.gz: b891ea4d1498b2fc16f0d241520486736b0b707bf401e96bdab09795ff165c23d86344a2b29cfcf1dbca83d8a773b85a08e59dc09220c5acca2738e485c3994f
7
+ data.tar.gz: ca657dfb18edaf157cb01ca48b522882c165a8c06216c84deda9a88a7718fb61da4ea3a3b017e4ac8594e83f97f904d4f0f1ad1947ee9418b977ddf4884e8c52
data/bin/committee-stub CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'optparse'
4
5
  require 'yaml'
data/lib/committee.rb CHANGED
@@ -1,43 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
2
4
  require "yaml"
3
5
  require "json_schema"
4
6
  require "rack"
5
7
  require 'openapi_parser'
6
8
 
7
- require_relative "committee/errors"
8
- require_relative "committee/request_unpacker"
9
-
10
- require_relative "committee/validation_error"
11
-
12
- require_relative "committee/drivers"
13
- require_relative "committee/drivers/hyper_schema"
14
- require_relative "committee/drivers/open_api_2"
15
- require_relative "committee/drivers/open_api_3"
16
-
17
- require_relative "committee/middleware/base"
18
- require_relative "committee/middleware/request_validation"
19
- require_relative "committee/middleware/response_validation"
20
- require_relative "committee/middleware/stub"
21
-
22
- require_relative "committee/schema_validator/option"
23
- require_relative "committee/schema_validator/schema_validator"
24
- require_relative "committee/schema_validator/open_api_3"
25
- require_relative "committee/schema_validator/open_api_3/router"
26
- require_relative "committee/schema_validator/open_api_3/operation_wrapper"
27
- require_relative "committee/schema_validator/open_api_3/request_validator"
28
- require_relative "committee/schema_validator/open_api_3/response_validator"
29
- require_relative "committee/schema_validator/hyper_schema"
30
- require_relative "committee/schema_validator/hyper_schema/request_validator"
31
- require_relative "committee/schema_validator/hyper_schema/response_generator"
32
- require_relative "committee/schema_validator/hyper_schema/response_validator"
33
- require_relative "committee/schema_validator/hyper_schema/router"
34
- require_relative "committee/schema_validator/hyper_schema/string_params_coercer"
35
- require_relative "committee/schema_validator/hyper_schema/parameter_coercer"
36
-
37
- require_relative "committee/bin/committee_stub"
38
-
39
- require_relative "committee/test/methods"
40
-
41
9
  module Committee
42
10
  def self.debug?
43
11
  ENV["COMMITTEE_DEBUG"]
@@ -53,3 +21,13 @@ module Committee
53
21
  end
54
22
  end
55
23
  end
24
+
25
+ require_relative "committee/drivers"
26
+ require_relative "committee/errors"
27
+ require_relative "committee/middleware"
28
+ require_relative "committee/request_unpacker"
29
+ require_relative "committee/schema_validator"
30
+ require_relative "committee/validation_error"
31
+
32
+ require_relative "committee/bin/committee_stub"
33
+ require_relative "committee/test/methods"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Don't Support OpenAPI3
2
4
 
3
5
  module Committee
@@ -29,10 +31,10 @@ module Committee
29
31
  # Gets an option parser for command line arguments.
30
32
  def get_options_parser
31
33
  options = {
32
- :driver => nil,
33
- :help => false,
34
- :port => 9292,
35
- :tolerant => false,
34
+ driver: nil,
35
+ help: false,
36
+ port: 9292,
37
+ tolerant: false,
36
38
  }
37
39
 
38
40
  parser = OptionParser.new do |opts|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Committee
2
4
  module Drivers
3
5
  # Gets a driver instance from the specified name. Raises ArgumentError for
@@ -5,11 +7,11 @@ module Committee
5
7
  def self.driver_from_name(name)
6
8
  case name
7
9
  when :hyper_schema
8
- Committee::Drivers::HyperSchema.new
10
+ Committee::Drivers::HyperSchema::Driver.new
9
11
  when :open_api_2
10
- Committee::Drivers::OpenAPI2.new
12
+ Committee::Drivers::OpenAPI2::Driver.new
11
13
  when :open_api_3
12
- Committee::Drivers::OpenAPI3.new
14
+ Committee::Drivers::OpenAPI3::Driver.new
13
15
  else
14
16
  raise ArgumentError, %{Committee: unknown driver "#{name}".}
15
17
  end
@@ -49,76 +51,22 @@ module Committee
49
51
  def self.load_from_data(hash)
50
52
  if hash['openapi']&.start_with?('3.0.')
51
53
  parser = OpenAPIParser.parse(hash)
52
- return Committee::Drivers::OpenAPI3.new.parse(parser)
54
+ return Committee::Drivers::OpenAPI3::Driver.new.parse(parser)
53
55
  end
54
56
 
55
57
  driver = if hash['swagger'] == '2.0'
56
- Committee::Drivers::OpenAPI2.new
58
+ Committee::Drivers::OpenAPI2::Driver.new
57
59
  else
58
- Committee::Drivers::HyperSchema.new
60
+ Committee::Drivers::HyperSchema::Driver.new
59
61
  end
60
62
 
61
63
  driver.parse(hash)
62
64
  end
63
-
64
- # Driver is a base class for driver implementations.
65
- class Driver
66
- # Whether parameters that were form-encoded will be coerced by default.
67
- def default_coerce_form_params
68
- raise "needs implementation"
69
- end
70
-
71
- # Use GET request body to request parameter (request body merge to parameter)
72
- def default_allow_get_body
73
- raise "needs implementation"
74
- end
75
-
76
- # Whether parameters in a request's path will be considered and coerced
77
- # by default.
78
- def default_path_params
79
- raise "needs implementation"
80
- end
81
-
82
- # Whether parameters in a request's query string will be considered and
83
- # coerced by default.
84
- def default_query_params
85
- raise "needs implementation"
86
- end
87
-
88
- def name
89
- raise "needs implementation"
90
- end
91
-
92
- # Parses an API schema and builds a set of route definitions for use with
93
- # Committee.
94
- #
95
- # The expected input format is a data hash with keys as strings (as
96
- # opposed to symbols) like the kind produced by JSON.parse or YAML.load.
97
- def parse(data)
98
- raise "needs implementation"
99
- end
100
-
101
- def schema_class
102
- raise "needs implementation"
103
- end
104
- end
105
-
106
- # Schema is a base class for driver schema implementations.
107
- class Schema
108
- # A link back to the derivative instace of Committee::Drivers::Driver
109
- # that create this schema.
110
- def driver
111
- raise "needs implementation"
112
- end
113
-
114
- def build_router(options)
115
- raise "needs implementation"
116
- end
117
-
118
- # Stubs are supported in JSON Hyper-Schema and OpenAPI 2, but not yet in OpenAPI 3
119
- def supports_stub?
120
- true
121
- end
122
- end
123
65
  end
124
- end
66
+ end
67
+
68
+ require_relative "drivers/driver"
69
+ require_relative "drivers/schema"
70
+ require_relative "drivers/hyper_schema"
71
+ require_relative "drivers/open_api_2"
72
+ require_relative "drivers/open_api_3"
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module Drivers
5
+ # Driver is a base class for driver implementations.
6
+ class Driver
7
+ # Whether parameters that were form-encoded will be coerced by default.
8
+ def default_coerce_form_params
9
+ raise "needs implementation"
10
+ end
11
+
12
+ # Use GET request body to request parameter (request body merge to parameter)
13
+ def default_allow_get_body
14
+ raise "needs implementation"
15
+ end
16
+
17
+ # Whether parameters in a request's path will be considered and coerced
18
+ # by default.
19
+ def default_path_params
20
+ raise "needs implementation"
21
+ end
22
+
23
+ # Whether parameters in a request's query string will be considered and
24
+ # coerced by default.
25
+ def default_query_params
26
+ raise "needs implementation"
27
+ end
28
+
29
+ def name
30
+ raise "needs implementation"
31
+ end
32
+
33
+ # Parses an API schema and builds a set of route definitions for use with
34
+ # Committee.
35
+ #
36
+ # The expected input format is a data hash with keys as strings (as
37
+ # opposed to symbols) like the kind produced by JSON.parse or YAML.load.
38
+ def parse(data)
39
+ raise "needs implementation"
40
+ end
41
+
42
+ def schema_class
43
+ raise "needs implementation"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,175 +1,12 @@
1
- module Committee::Drivers
2
- class HyperSchema < Committee::Drivers::Driver
3
- def default_coerce_date_times
4
- false
5
- end
6
-
7
- # Whether parameters that were form-encoded will be coerced by default.
8
- def default_coerce_form_params
9
- false
10
- end
11
-
12
- def default_allow_get_body
13
- true
14
- end
15
-
16
- # Whether parameters in a request's path will be considered and coerced by
17
- # default.
18
- def default_path_params
19
- false
20
- end
21
-
22
- # Whether parameters in a request's query string will be considered and
23
- # coerced by default.
24
- def default_query_params
25
- false
26
- end
27
-
28
- def default_validate_success_only
29
- true
30
- end
31
-
32
- def name
33
- :hyper_schema
34
- end
35
-
36
- # Parses an API schema and builds a set of route definitions for use with
37
- # Committee.
38
- #
39
- # The expected input format is a data hash with keys as strings (as opposed
40
- # to symbols) like the kind produced by JSON.parse or YAML.load.
41
- def parse(schema)
42
- # Really we'd like to only have data hashes passed into drivers these
43
- # days, but here we handle a JsonSchema::Schema for now to maintain
44
- # backward compatibility (this library used to be hyper-schema only).
45
- if schema.is_a?(JsonSchema::Schema)
46
- hyper_schema = schema
47
- else
48
- hyper_schema = JsonSchema.parse!(schema)
49
- hyper_schema.expand_references!
50
- end
51
-
52
- schema = Schema.new
53
- schema.driver = self
54
- schema.routes = build_routes(hyper_schema)
55
- schema
56
- end
1
+ # frozen_string_literal: true
57
2
 
58
- def schema_class
59
- Committee::Drivers::HyperSchema::Schema
60
- end
61
-
62
- # Link abstracts an API link specifically for JSON hyper-schema.
63
- #
64
- # For most operations, it's a simple pass through to a
65
- # JsonSchema::Schema::Link, but implements some exotic behavior in a few
66
- # places.
67
- class Link
68
- def initialize(hyper_schema_link)
69
- self.hyper_schema_link = hyper_schema_link
70
- end
71
-
72
- # The link's input media type. i.e. How requests should be encoded.
73
- def enc_type
74
- hyper_schema_link.enc_type
75
- end
76
-
77
- def href
78
- hyper_schema_link.href
79
- end
80
-
81
- # The link's output media type. i.e. How responses should be encoded.
82
- def media_type
83
- hyper_schema_link.media_type
84
- end
85
-
86
- def method
87
- hyper_schema_link.method
88
- end
89
-
90
- # Passes through a link's parent resource. Note that this is *not* part
91
- # of the Link interface and is here to support a legacy Heroku-ism
92
- # behavior that allowed a link tagged with rel=instances to imply that a
93
- # list will be returned.
94
- def parent
95
- hyper_schema_link.parent
96
- end
97
-
98
- def rel
99
- hyper_schema_link.rel
100
- end
101
-
102
- # The link's input schema. i.e. How we validate an endpoint's incoming
103
- # parameters.
104
- def schema
105
- hyper_schema_link.schema
106
- end
107
-
108
- def status_success
109
- hyper_schema_link.rel == "create" ? 201 : 200
110
- end
111
-
112
- # The link's output schema. i.e. How we validate an endpoint's response
113
- # data.
114
- def target_schema
115
- hyper_schema_link.target_schema
116
- end
117
-
118
- private
119
-
120
- attr_accessor :hyper_schema_link
121
- end
122
-
123
- class Schema < Committee::Drivers::Schema
124
- # A link back to the derivative instace of Committee::Drivers::Driver
125
- # that create this schema.
126
- attr_accessor :driver
127
-
128
- attr_accessor :routes
129
-
130
- attr_reader :validator_option
131
-
132
- def build_router(options)
133
- @validator_option = Committee::SchemaValidator::Option.new(options, self, :hyper_schema)
134
- Committee::SchemaValidator::HyperSchema::Router.new(self, @validator_option)
135
- end
136
- end
137
-
138
- private
139
-
140
- def build_routes(hyper_schema)
141
- routes = {}
142
-
143
- hyper_schema.links.each do |link|
144
- method, href = parse_link(link)
145
- next unless method
146
-
147
- rx = %r{^#{href}$}
148
- Committee.log_debug "Created route: #{method} #{href} (regex #{rx})"
149
-
150
- routes[method] ||= []
151
- routes[method] << [rx, Link.new(link)]
152
- end
153
-
154
- # recursively iterate through all `properties` subschemas to build a
155
- # complete routing table
156
- hyper_schema.properties.each do |_, subschema|
157
- routes.merge!(build_routes(subschema)) { |_, r1, r2| r1 + r2 }
158
- end
159
-
160
- routes
161
- end
162
-
163
- def href_to_regex(href)
164
- href.gsub(/\{(.*?)\}/, "[^/]+")
165
- end
166
-
167
- def parse_link(link)
168
- return nil, nil if !link.method || !link.href
169
- method = link.method.to_s.upcase
170
- # /apps/{id} --> /apps/([^/]+)
171
- href = href_to_regex(link.href)
172
- [method, href]
3
+ module Committee
4
+ module Drivers
5
+ module HyperSchema
173
6
  end
174
7
  end
175
8
  end
9
+
10
+ require_relative 'hyper_schema/driver'
11
+ require_relative 'hyper_schema/link'
12
+ require_relative 'hyper_schema/schema'
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module Drivers
5
+ module HyperSchema
6
+ class Driver < ::Committee::Drivers::Driver
7
+ def default_coerce_date_times
8
+ false
9
+ end
10
+
11
+ # Whether parameters that were form-encoded will be coerced by default.
12
+ def default_coerce_form_params
13
+ false
14
+ end
15
+
16
+ def default_allow_get_body
17
+ true
18
+ end
19
+
20
+ # Whether parameters in a request's path will be considered and coerced by
21
+ # default.
22
+ def default_path_params
23
+ false
24
+ end
25
+
26
+ # Whether parameters in a request's query string will be considered and
27
+ # coerced by default.
28
+ def default_query_params
29
+ false
30
+ end
31
+
32
+ def default_validate_success_only
33
+ true
34
+ end
35
+
36
+ def name
37
+ :hyper_schema
38
+ end
39
+
40
+ # Parses an API schema and builds a set of route definitions for use with
41
+ # Committee.
42
+ #
43
+ # The expected input format is a data hash with keys as strings (as opposed
44
+ # to symbols) like the kind produced by JSON.parse or YAML.load.
45
+ def parse(schema)
46
+ # Really we'd like to only have data hashes passed into drivers these
47
+ # days, but here we handle a JsonSchema::Schema for now to maintain
48
+ # backward compatibility (this library used to be hyper-schema only).
49
+ if schema.is_a?(JsonSchema::Schema)
50
+ hyper_schema = schema
51
+ else
52
+ hyper_schema = JsonSchema.parse!(schema)
53
+ hyper_schema.expand_references!
54
+ end
55
+
56
+ schema = Schema.new
57
+ schema.driver = self
58
+ schema.routes = build_routes(hyper_schema)
59
+ schema
60
+ end
61
+
62
+ def schema_class
63
+ Committee::Drivers::HyperSchema::Schema
64
+ end
65
+
66
+ private
67
+
68
+ def build_routes(hyper_schema)
69
+ routes = {}
70
+
71
+ hyper_schema.links.each do |link|
72
+ method, href = parse_link(link)
73
+ next unless method
74
+
75
+ rx = %r{^#{href}$}
76
+ Committee.log_debug "Created route: #{method} #{href} (regex #{rx})"
77
+
78
+ routes[method] ||= []
79
+ routes[method] << [rx, Link.new(link)]
80
+ end
81
+
82
+ # recursively iterate through all `properties` subschemas to build a
83
+ # complete routing table
84
+ hyper_schema.properties.each do |_, subschema|
85
+ routes.merge!(build_routes(subschema)) { |_, r1, r2| r1 + r2 }
86
+ end
87
+
88
+ routes
89
+ end
90
+
91
+ def href_to_regex(href)
92
+ href.gsub(/\{(.*?)\}/, "[^/]+")
93
+ end
94
+
95
+ def parse_link(link)
96
+ return nil, nil if !link.method || !link.href
97
+ method = link.method.to_s.upcase
98
+ # /apps/{id} --> /apps/([^/]+)
99
+ href = href_to_regex(link.href)
100
+ [method, href]
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end