committee 2.0.0.pre → 2.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5911eb64b8a07bb45eaf264399bebeb95ea2395b
4
- data.tar.gz: 35d800d2dd5cd0c3d402b26813d7b156f0809006
3
+ metadata.gz: c27dbbfbcb3d316bd61c7056fe0a8f7fec175ab6
4
+ data.tar.gz: c3ad5a80a63987ae2f94988ed12b1285e71ee760
5
5
  SHA512:
6
- metadata.gz: 86c361cc0bd1f4d0e340335402ab452b99a0c0d0eae814aa3296794ed0a076177f9dc3ebc772ae95a66afbe45efcbeccc77e2851ef3a0e385171fc549e31092c
7
- data.tar.gz: 306a67c72463d3879dd7fb4e9aff88a17d34e54d83c209a439cabc47b912027178c5d23fc9b5270cc6b0f9d65d4957f152ec630c7e3484931bba1bda46ed4bd0
6
+ metadata.gz: 86f1c3e718e6dee210e3c42ba2d1a5ba0b029137adc1be572d5dac9d6048dc7c84cf4274a652360473b9e263662912f5a7a94fc27b2666daf054530f0b44c40f
7
+ data.tar.gz: 6dd6d2dc9165ea38e3df05a0d35915809a82447a5708728c192d22ee632692448f6e4996733c165c8f0d6f4895dff7bfa18b952c070b2a8bb1e01d21073ad7c7
@@ -6,13 +6,15 @@ module Committee
6
6
  class CommitteeStub
7
7
  # Gets a Rack app suitable for use as a stub.
8
8
  def get_app(schema, options)
9
+ cache = {}
10
+
9
11
  Rack::Builder.new {
10
12
  unless options[:tolerant]
11
13
  use Committee::Middleware::RequestValidation, schema: schema
12
14
  use Committee::Middleware::ResponseValidation, schema: schema
13
15
  end
14
16
 
15
- use Committee::Middleware::Stub, schema: schema
17
+ use Committee::Middleware::Stub, cache: cache, schema: schema
16
18
 
17
19
  run lambda { |_|
18
20
  [404, {}, ["Not found"]]
@@ -53,9 +55,6 @@ module Committee
53
55
  end
54
56
  [options, parser]
55
57
  end
56
-
57
- def get_schema(driver_name, data)
58
- end
59
58
  end
60
59
  end
61
60
  end
@@ -89,43 +89,54 @@ module Committee::Drivers
89
89
  self.link_data = link_data
90
90
  end
91
91
 
92
+ # Returns a tuple of (schema, schema_data) where only one of the two
93
+ # values is present. This is either a full schema that's ready to go _or_
94
+ # a hash of unparsed schema data.
92
95
  def call
93
- link_schema = JsonSchema::Schema.new
94
- link_schema.properties = {}
95
- link_schema.required = []
96
-
97
96
  if link_data["parameters"]
98
- link_data["parameters"].each do |param_data|
99
- LINK_REQUIRED_FIELDS.each do |field|
100
- if !param_data[field]
101
- raise ArgumentError,
102
- "Committee: no #{field} section in link data."
103
- end
104
- end
97
+ body_param = link_data["parameters"].detect { |p| p["in"] == "body" }
98
+ if body_param
99
+ check_required_fields!(body_param)
105
100
 
106
- param_schema = JsonSchema::Schema.new
101
+ if link_data["parameters"].detect { |p| p["in"] == "form" } != nil
102
+ raise ArgumentError, "Committee: can't mix body parameter " \
103
+ "with form parameters."
104
+ end
107
105
 
108
- # We could probably use more validation here, but the formats of
109
- # OpenAPI 2 are based off of what's available in JSON schema, and
110
- # therefore this should map over quite well.
111
- param_schema.type = [param_data["type"]]
106
+ schema_data = body_param["schema"]
107
+ [nil, schema_data]
108
+ else
109
+ link_schema = JsonSchema::Schema.new
110
+ link_schema.properties = {}
111
+ link_schema.required = []
112
+
113
+ link_data["parameters"].each do |param_data|
114
+ check_required_fields!(param_data)
115
+
116
+ param_schema = JsonSchema::Schema.new
117
+
118
+ # We could probably use more validation here, but the formats of
119
+ # OpenAPI 2 are based off of what's available in JSON schema, and
120
+ # therefore this should map over quite well.
121
+ param_schema.type = [param_data["type"]]
122
+
123
+ # And same idea: despite parameters not being schemas, the items
124
+ # key (if preset) is actually a schema that defines each item of an
125
+ # array type, so we can just reflect that directly onto our
126
+ # artifical schema.
127
+ if param_data["type"] == "array" && param_data["items"]
128
+ param_schema.items = param_data["items"]
129
+ end
112
130
 
113
- # And same idea: despite parameters not being schemas, the items
114
- # key (if preset) is actually a schema that defines each item of an
115
- # array type, so we can just reflect that directly onto our
116
- # artifical schema.
117
- if param_data["type"] == "array" && param_data["items"]
118
- param_schema.items = param_data["items"]
131
+ link_schema.properties[param_data["name"]] = param_schema
132
+ if param_data["required"] == true
133
+ link_schema.required << param_data["name"]
134
+ end
119
135
  end
120
136
 
121
- link_schema.properties[param_data["name"]] = param_schema
122
- if param_data["required"] == true
123
- link_schema.required << param_data["name"]
124
- end
137
+ [link_schema, nil]
125
138
  end
126
139
  end
127
-
128
- link_schema
129
140
  end
130
141
 
131
142
  private
@@ -135,6 +146,15 @@ module Committee::Drivers
135
146
  ].map(&:to_s).freeze
136
147
 
137
148
  attr_accessor :link_data
149
+
150
+ def check_required_fields!(param_data)
151
+ LINK_REQUIRED_FIELDS.each do |field|
152
+ if !param_data[field]
153
+ raise ArgumentError,
154
+ "Committee: no #{field} section in link data."
155
+ end
156
+ end
157
+ end
138
158
  end
139
159
 
140
160
  class Schema < Committee::Drivers::Schema
@@ -219,10 +239,14 @@ module Committee::Drivers
219
239
  # all schemas into one big hash and then parse it all at the end. After
220
240
  # we parse it, go through each link and assign a proper schema object. In
221
241
  # practice this comes out to somewhere on the order of 50x faster.
242
+ schemas_data = { "properties" => {} }
243
+
244
+ # Exactly the same idea, but for response schemas.
222
245
  target_schemas_data = { "properties" => {} }
223
246
 
224
247
  data['paths'].each do |path, methods|
225
248
  href = schema.base_path + path
249
+ schemas_data["properties"][href] = { "properties" => {} }
226
250
  target_schemas_data["properties"][href] = { "properties" => {} }
227
251
 
228
252
  methods.each do |method, link_data|
@@ -236,7 +260,14 @@ module Committee::Drivers
236
260
 
237
261
  # Convert the spec's parameter pseudo-schemas into JSON schemas that
238
262
  # we can use for some basic request validation.
239
- link.schema = ParameterSchemaBuilder.new(link_data).call
263
+ link.schema, schema_data = ParameterSchemaBuilder.new(link_data).call
264
+
265
+ # If data came back instead of a schema (this occurs when a route has
266
+ # a single `body` parameter instead of a collection of URL/query/form
267
+ # parameters), store it for later parsing.
268
+ if schema_data
269
+ schemas_data["properties"][href]["properties"][method] = schema_data
270
+ end
240
271
 
241
272
  # Arbitrarily pick one response for the time being. Prefers in order:
242
273
  # a 200, 201, any 3-digit numerical response, then anything at all.
@@ -263,15 +294,25 @@ module Committee::Drivers
263
294
  # #parse_definitions!, but what we're doing here is prefixing references
264
295
  # with a specialized internal URI so that they can reference definitions
265
296
  # from another document in the store.
266
- target_schemas = rewrite_references(target_schemas_data)
267
-
268
- target_schemas = JsonSchema.parse!(target_schemas)
269
- target_schemas.expand_references!(store: store)
297
+ schemas =
298
+ rewrite_references_and_parse(schemas_data, store)
299
+ target_schemas =
300
+ rewrite_references_and_parse(target_schemas_data, store)
270
301
 
271
302
  # As noted above, now that we've parsed our aggregate response schema, go
272
303
  # back through each link and them their response schema.
273
304
  routes.each do |method, method_routes|
274
305
  method_routes.each do |(_, link)|
306
+ # request
307
+ #
308
+ # Differs slightly from responses in that the schema may already have
309
+ # been set for endpoints with non-body parameters, so check for nil
310
+ # before we set it.
311
+ if schema = schemas.properties[link.href].properties[method]
312
+ link.schema = schema
313
+ end
314
+
315
+ # response
275
316
  link.target_schema =
276
317
  target_schemas.properties[link.href].properties[method]
277
318
  end
@@ -280,6 +321,13 @@ module Committee::Drivers
280
321
  routes
281
322
  end
282
323
 
324
+ def rewrite_references_and_parse(schemas_data, store)
325
+ schemas = rewrite_references(schemas_data)
326
+ schemas = JsonSchema.parse!(schemas_data)
327
+ schemas.expand_references!(:store => store)
328
+ schemas
329
+ end
330
+
283
331
  def rewrite_references(schema)
284
332
  if schema.is_a?(Hash)
285
333
  ref = schema["$ref"]
@@ -197,8 +197,9 @@ describe Committee::Drivers::OpenAPI2::ParameterSchemaBuilder do
197
197
  }
198
198
  ]
199
199
  }
200
- schema = call(data)
200
+ schema, schema_data = call(data)
201
201
 
202
+ assert_equal nil, schema_data
202
203
  assert_equal ["limit"], schema.properties.keys
203
204
  assert_equal [], schema.required
204
205
  assert_equal ["integer"], schema.properties["limit"].type
@@ -213,8 +214,9 @@ describe Committee::Drivers::OpenAPI2::ParameterSchemaBuilder do
213
214
  }
214
215
  ]
215
216
  }
216
- schema = call(data)
217
+ schema, schema_data = call(data)
217
218
 
219
+ assert_equal nil, schema_data
218
220
  assert_equal ["limit"], schema.required
219
221
  end
220
222
 
@@ -230,12 +232,31 @@ describe Committee::Drivers::OpenAPI2::ParameterSchemaBuilder do
230
232
  }
231
233
  ]
232
234
  }
233
- schema = call(data)
235
+ schema, schema_data = call(data)
234
236
 
237
+ assert_equal nil, schema_data
235
238
  assert_equal ["array"], schema.properties["tags"].type
236
239
  assert_equal({ "type" => "string" }, schema.properties["tags"].items)
237
240
  end
238
241
 
242
+ it "returns schema data for a body parameter" do
243
+ data = {
244
+ "parameters" => [
245
+ {
246
+ "name" => "payload",
247
+ "in" => "body",
248
+ "schema" => {
249
+ "$ref" => "#/definitions/foo",
250
+ }
251
+ }
252
+ ]
253
+ }
254
+ schema, schema_data = call(data)
255
+
256
+ assert_equal nil, schema
257
+ assert_equal({ "$ref" => "#/definitions/foo" }, schema_data)
258
+ end
259
+
239
260
  it "requires that certain fields are present" do
240
261
  data = {
241
262
  "parameters" => [
@@ -249,6 +270,26 @@ describe Committee::Drivers::OpenAPI2::ParameterSchemaBuilder do
249
270
  assert_equal "Committee: no name section in link data.", e.message
250
271
  end
251
272
 
273
+ it "requires that body parameters not be mixed with form parameters" do
274
+ data = {
275
+ "parameters" => [
276
+ {
277
+ "name" => "payload",
278
+ "in" => "body",
279
+ },
280
+ {
281
+ "name" => "limit",
282
+ "in" => "form",
283
+ },
284
+ ]
285
+ }
286
+ e = assert_raises ArgumentError do
287
+ call(data)
288
+ end
289
+ assert_equal "Committee: can't mix body parameter with form parameters.",
290
+ e.message
291
+ end
292
+
252
293
  def call(data)
253
294
  Committee::Drivers::OpenAPI2::ParameterSchemaBuilder.new(data).call
254
295
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: committee
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre
4
+ version: 2.0.0.pre2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandur
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-10-10 00:00:00.000000000 Z
12
+ date: 2016-10-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json_schema