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 +4 -4
- data/lib/committee/bin/committee_stub.rb +3 -4
- data/lib/committee/drivers/open_api_2.rb +81 -33
- data/test/drivers/open_api_2_test.rb +44 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c27dbbfbcb3d316bd61c7056fe0a8f7fec175ab6
|
4
|
+
data.tar.gz: c3ad5a80a63987ae2f94988ed12b1285e71ee760
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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"].
|
99
|
-
|
100
|
-
|
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
|
-
|
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
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
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
|
-
|
267
|
-
|
268
|
-
target_schemas =
|
269
|
-
|
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.
|
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-
|
12
|
+
date: 2016-10-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json_schema
|