rack-spec 0.0.5 → 0.1.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +6 -130
- data/lib/rack/spec.rb +6 -36
- data/lib/rack/spec/request_validation.rb +153 -0
- data/lib/rack/spec/schema.rb +55 -0
- data/lib/rack/spec/version.rb +2 -2
- data/rack-spec.gemspec +5 -7
- data/spec/fixtures/schema.json +115 -0
- data/spec/rack/spec/request_validation_spec.rb +117 -0
- data/spec/spec_helper.rb +1 -4
- metadata +31 -60
- data/lib/rack/spec/exception_handler.rb +0 -15
- data/lib/rack/spec/exceptions/base.rb +0 -8
- data/lib/rack/spec/exceptions/validation_error.rb +0 -43
- data/lib/rack/spec/restful.rb +0 -95
- data/lib/rack/spec/spec.rb +0 -30
- data/lib/rack/spec/validation.rb +0 -21
- data/lib/rack/spec/validator_factory.rb +0 -19
- data/lib/rack/spec/validators/base.rb +0 -44
- data/lib/rack/spec/validators/maximum_length_validator.rb +0 -13
- data/lib/rack/spec/validators/maximum_validator.rb +0 -13
- data/lib/rack/spec/validators/minimum_length_validator.rb +0 -13
- data/lib/rack/spec/validators/minimum_validator.rb +0 -13
- data/lib/rack/spec/validators/null_validator.rb +0 -11
- data/lib/rack/spec/validators/only_validator.rb +0 -13
- data/lib/rack/spec/validators/parameters_validator.rb +0 -26
- data/lib/rack/spec/validators/required_validator.rb +0 -13
- data/lib/rack/spec/validators/type_validator.rb +0 -36
- data/spec/fixtures/spec.yml +0 -36
- data/spec/rack/spec_spec.rb +0 -221
@@ -1,43 +0,0 @@
|
|
1
|
-
require "json"
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
class Spec
|
5
|
-
module Exceptions
|
6
|
-
class ValidationError < Base
|
7
|
-
def initialize(validator)
|
8
|
-
@validator = validator
|
9
|
-
end
|
10
|
-
|
11
|
-
def message
|
12
|
-
"Invalid #{key} on `#{constraint_name}` constraint"
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_rack_response
|
16
|
-
[status, header, body]
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def constraint_name
|
22
|
-
@validator.class.registered_name
|
23
|
-
end
|
24
|
-
|
25
|
-
def key
|
26
|
-
@validator.key
|
27
|
-
end
|
28
|
-
|
29
|
-
def status
|
30
|
-
400
|
31
|
-
end
|
32
|
-
|
33
|
-
def header
|
34
|
-
{ "Content-Type" => "application/json" }
|
35
|
-
end
|
36
|
-
|
37
|
-
def body
|
38
|
-
{ message: message }.to_json
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
data/lib/rack/spec/restful.rb
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
require "active_support/core_ext/object/try"
|
2
|
-
require "active_support/core_ext/string/inflections"
|
3
|
-
|
4
|
-
module Rack
|
5
|
-
class Spec
|
6
|
-
class Restful
|
7
|
-
def initialize(app, options = {})
|
8
|
-
@app = app
|
9
|
-
@options = options
|
10
|
-
end
|
11
|
-
|
12
|
-
def call(env)
|
13
|
-
Proxy.new(@app, spec, env).call
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def spec
|
19
|
-
Spec.new(@options[:spec])
|
20
|
-
end
|
21
|
-
|
22
|
-
class Proxy
|
23
|
-
def initialize(app, spec, env)
|
24
|
-
@app = app
|
25
|
-
@spec = spec
|
26
|
-
@env = env
|
27
|
-
end
|
28
|
-
|
29
|
-
def call
|
30
|
-
if endpoint
|
31
|
-
response = handler_class.send(handler_method_name, params)
|
32
|
-
[
|
33
|
-
response.try(:status) || default_status,
|
34
|
-
default_header.merge(response.try(:header) || {}),
|
35
|
-
[(response.try(:body) || response).to_json]
|
36
|
-
]
|
37
|
-
else
|
38
|
-
@app.call(@env)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def endpoint
|
45
|
-
@endpoint ||= @spec.find_endpoint(@env)
|
46
|
-
end
|
47
|
-
|
48
|
-
def handler_class
|
49
|
-
path_segments[1].singularize.camelize.constantize
|
50
|
-
end
|
51
|
-
|
52
|
-
def id
|
53
|
-
path_segments[2]
|
54
|
-
end
|
55
|
-
|
56
|
-
def path_segments
|
57
|
-
@path_segments ||= path.split("/")
|
58
|
-
end
|
59
|
-
|
60
|
-
def handler_method_name
|
61
|
-
request_method.downcase
|
62
|
-
end
|
63
|
-
|
64
|
-
def path
|
65
|
-
request.path
|
66
|
-
end
|
67
|
-
|
68
|
-
def request
|
69
|
-
@env["rack-spec.request"] ||= Rack::Request.new(@env)
|
70
|
-
end
|
71
|
-
|
72
|
-
def request_method
|
73
|
-
@env["REQUEST_METHOD"]
|
74
|
-
end
|
75
|
-
|
76
|
-
def params
|
77
|
-
request.params.merge(@env["rack-spec.uri_parameters"])
|
78
|
-
end
|
79
|
-
|
80
|
-
def default_status
|
81
|
-
{
|
82
|
-
"GET" => 200,
|
83
|
-
"POST" => 201,
|
84
|
-
"PUT" => 204,
|
85
|
-
"DELETE" => 204,
|
86
|
-
}[request_method]
|
87
|
-
end
|
88
|
-
|
89
|
-
def default_header
|
90
|
-
{ "Content-tYpe" => "application/json" }
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
data/lib/rack/spec/spec.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require "addressable/template"
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
class Spec
|
5
|
-
class Spec < Hash
|
6
|
-
def initialize(hash)
|
7
|
-
hash.each do |key, value|
|
8
|
-
self[key] = value
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def find_endpoint(env)
|
13
|
-
self["endpoints"].find do |path, source|
|
14
|
-
if parameters = Addressable::Template.new(path).extract(env["PATH_INFO"])
|
15
|
-
if endpoint = source[env["REQUEST_METHOD"]]
|
16
|
-
env["rack-spec.uri_parameters"] = parameters
|
17
|
-
break endpoint
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def reach(*keys)
|
24
|
-
keys.inject(self) do |hash, key|
|
25
|
-
hash[key] if hash.respond_to?(:[])
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/lib/rack/spec/validation.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Rack
|
2
|
-
class Spec
|
3
|
-
class Validation
|
4
|
-
def initialize(app, options = {})
|
5
|
-
@app = app
|
6
|
-
@options = options
|
7
|
-
end
|
8
|
-
|
9
|
-
def call(env)
|
10
|
-
Validators::ParametersValidator.new(spec, env).validate!
|
11
|
-
@app.call(env)
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def spec
|
17
|
-
Spec.new(@options[:spec])
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Rack
|
2
|
-
class Spec
|
3
|
-
class ValidatorFactory
|
4
|
-
class << self
|
5
|
-
def validator_classes
|
6
|
-
@validator_classes ||= Hash.new(Validators::NullValidator)
|
7
|
-
end
|
8
|
-
|
9
|
-
def register(name, klass)
|
10
|
-
validator_classes[name] = klass
|
11
|
-
end
|
12
|
-
|
13
|
-
def build(key, type, constraint, env)
|
14
|
-
validator_classes[type].new(key, constraint, env)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Rack
|
2
|
-
class Spec
|
3
|
-
module Validators
|
4
|
-
class Base
|
5
|
-
class << self
|
6
|
-
attr_accessor :registered_name
|
7
|
-
|
8
|
-
def register_as(name)
|
9
|
-
self.registered_name = name
|
10
|
-
ValidatorFactory.register(name, self)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_reader :constraint, :key, :env
|
15
|
-
|
16
|
-
def initialize(key, constraint, env)
|
17
|
-
@key = key
|
18
|
-
@constraint = constraint
|
19
|
-
@env = env
|
20
|
-
end
|
21
|
-
|
22
|
-
def validate!
|
23
|
-
unless valid?
|
24
|
-
raise Exceptions::ValidationError, self
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def valid?
|
29
|
-
raise NotImplementedError
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def value
|
35
|
-
@value ||= request.params[@key]
|
36
|
-
end
|
37
|
-
|
38
|
-
def request
|
39
|
-
env["rack-spec.request"] ||= Rack::Request.new(env)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Rack
|
2
|
-
class Spec
|
3
|
-
module Validators
|
4
|
-
class ParametersValidator
|
5
|
-
def initialize(spec, env)
|
6
|
-
@spec = spec
|
7
|
-
@env = env
|
8
|
-
end
|
9
|
-
|
10
|
-
def validate!
|
11
|
-
parameters.each do |key, hash|
|
12
|
-
hash.each do |type, constraint|
|
13
|
-
ValidatorFactory.build(key, type, constraint, @env).validate!
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def parameters
|
21
|
-
@spec.find_endpoint(@env).try(:[], "parameters") || []
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require "time"
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
class Spec
|
5
|
-
module Validators
|
6
|
-
class TypeValidator < Base
|
7
|
-
class << self
|
8
|
-
def patterns
|
9
|
-
@patterns ||= Hash.new(//)
|
10
|
-
end
|
11
|
-
|
12
|
-
def pattern(name, pattern)
|
13
|
-
patterns[name] = pattern
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
register_as "type"
|
18
|
-
|
19
|
-
pattern "boolean", /\A(?:true|false)\z/
|
20
|
-
pattern "float", /\A-?\d+(?:\.\d+)*\z/
|
21
|
-
pattern "integer", /\A-?\d+\z/
|
22
|
-
pattern "iso8601", ->(value) { Time.iso8601(value) rescue false }
|
23
|
-
|
24
|
-
def valid?
|
25
|
-
value.nil? || pattern === value
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def pattern
|
31
|
-
self.class.patterns[constraint]
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|