yodatra 0.1.7 → 0.1.8
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.
- data/lib/yodatra/api_formatter.rb +1 -1
- data/lib/yodatra/models_controller.rb +20 -8
- data/lib/yodatra/throttling.rb +26 -0
- data/lib/yodatra/version.rb +1 -1
- data/spec/unit/models_controller_spec.rb +10 -10
- metadata +3 -2
@@ -15,7 +15,7 @@ module Yodatra
|
|
15
15
|
|
16
16
|
status, headers, response = @block.yield(status, headers, response) unless @block.nil?
|
17
17
|
|
18
|
-
headers['Content-Length'] = response.first.length.to_s unless response.nil? || response.first.nil?
|
18
|
+
headers['Content-Length'] = response.first.length.to_s unless response.nil? || !response.respond_to?(:first) || response.first.nil?
|
19
19
|
|
20
20
|
[status, headers, response]
|
21
21
|
end
|
@@ -6,13 +6,15 @@ module Yodatra
|
|
6
6
|
end
|
7
7
|
|
8
8
|
READ_ALL = :read_all
|
9
|
-
get "/*
|
9
|
+
get "/*" do
|
10
|
+
pass unless involved?
|
10
11
|
no_route if disabled? READ_ALL
|
11
12
|
model_name.constantize.all.as_json(read_scope).to_json
|
12
13
|
end
|
13
14
|
|
14
15
|
READ_ONE = :read
|
15
|
-
get "
|
16
|
+
get "/*/:id" do
|
17
|
+
pass unless involved?
|
16
18
|
no_route if disabled? READ_ONE
|
17
19
|
|
18
20
|
@one = model_name.constantize.find params[:id]
|
@@ -20,10 +22,12 @@ module Yodatra
|
|
20
22
|
end
|
21
23
|
|
22
24
|
CREATE_ONE = :create
|
23
|
-
post "/*
|
25
|
+
post "/*" do
|
26
|
+
pass unless involved?
|
24
27
|
no_route if disabled? CREATE_ONE
|
25
28
|
|
26
|
-
|
29
|
+
hash = self.send("#{model_name.underscore}_params".to_sym)
|
30
|
+
@one = model_name.constantize.new hash
|
27
31
|
|
28
32
|
if @one.save
|
29
33
|
@one.as_json(read_scope).to_json
|
@@ -34,7 +38,8 @@ module Yodatra
|
|
34
38
|
end
|
35
39
|
|
36
40
|
UPDATE_ONE = :update
|
37
|
-
put "
|
41
|
+
put "/*/:id" do
|
42
|
+
pass unless involved?
|
38
43
|
no_route if disabled? UPDATE_ONE
|
39
44
|
|
40
45
|
@one = model_name.constantize.find params[:id]
|
@@ -52,7 +57,8 @@ module Yodatra
|
|
52
57
|
end
|
53
58
|
|
54
59
|
DELETE_ONE = :delete
|
55
|
-
delete "
|
60
|
+
delete "/*/:id" do
|
61
|
+
pass unless involved?
|
56
62
|
no_route if disabled? DELETE_ONE
|
57
63
|
|
58
64
|
@one = model_name.constantize.find params[:id]
|
@@ -77,14 +83,20 @@ module Yodatra
|
|
77
83
|
|
78
84
|
private
|
79
85
|
|
86
|
+
def involved?
|
87
|
+
params[:splat].first == model_name.downcase
|
88
|
+
end
|
89
|
+
|
80
90
|
# read_scope defaults to all attrs of the model
|
81
91
|
def read_scope
|
82
92
|
{}
|
83
93
|
end
|
84
94
|
|
85
95
|
# create/update scope defaults to all data given in the POST/PUT
|
86
|
-
|
87
|
-
|
96
|
+
def method_missing(name, *args)
|
97
|
+
if name.to_s == "#{model_name.underscore}_params"
|
98
|
+
return params.reject{|k,v| %w(splat captures).include? k}
|
99
|
+
end
|
88
100
|
end
|
89
101
|
|
90
102
|
def model_name
|
@@ -0,0 +1,26 @@
|
|
1
|
+
begin
|
2
|
+
require 'redis'
|
3
|
+
|
4
|
+
module Yodatra
|
5
|
+
class Throttle
|
6
|
+
def initialize(app, opts)
|
7
|
+
@app = app
|
8
|
+
@redis = Redis.new opts[:redis_conf]
|
9
|
+
@rpm = opts[:rpm] || 100
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
req = Rack::Request.new(env)
|
14
|
+
key = "throttle:#{req.ip}"
|
15
|
+
@redis.incr(key) == 1 && @redis.expire(key, 60)
|
16
|
+
if @redis.get(key).to_i > @rpm
|
17
|
+
Rack::Response.new('Too many API calls', 403)
|
18
|
+
else
|
19
|
+
@app.call(env)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
rescue LoadError
|
25
|
+
raise "Error: in order to use Yodatra's throttling middleware you will need Redis. Add 'redis' to your Gemfile or simply gem install 'redis'"
|
26
|
+
end
|
data/lib/yodatra/version.rb
CHANGED
@@ -37,7 +37,7 @@ describe 'Model controller' do
|
|
37
37
|
describe 'Getting a collection of the Model' do
|
38
38
|
context 'default' do
|
39
39
|
it 'should have a GET all route' do
|
40
|
-
get '/
|
40
|
+
get '/model'
|
41
41
|
|
42
42
|
last_response.should be_ok
|
43
43
|
expect(last_response.body).to eq(Model::ALL.map{|e| {:data => e} }.to_json)
|
@@ -50,7 +50,7 @@ describe 'Model controller' do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
it 'should fail with no route available' do
|
53
|
-
get '/
|
53
|
+
get '/model'
|
54
54
|
|
55
55
|
last_response.should_not be_ok
|
56
56
|
end
|
@@ -58,7 +58,7 @@ describe 'Model controller' do
|
|
58
58
|
end
|
59
59
|
describe 'getting an specific Model instance' do
|
60
60
|
it 'should have a GET one route' do
|
61
|
-
get '/
|
61
|
+
get '/model/2'
|
62
62
|
|
63
63
|
last_response.should be_ok
|
64
64
|
expect(last_response.body).to eq({ :data => 'c'}.to_json)
|
@@ -70,7 +70,7 @@ describe 'Model controller' do
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
it 'should fail with no route available' do
|
73
|
-
get '/
|
73
|
+
get '/model/1'
|
74
74
|
|
75
75
|
last_response.should_not be_ok
|
76
76
|
end
|
@@ -80,7 +80,7 @@ describe 'Model controller' do
|
|
80
80
|
context 'with correct model params' do
|
81
81
|
it 'adds creates an instance, saves it and succeed' do
|
82
82
|
expect{
|
83
|
-
post '/
|
83
|
+
post '/model', {:data => 'd'}
|
84
84
|
}.to change(Model::ALL, :length).by(1)
|
85
85
|
|
86
86
|
last_response.should be_ok
|
@@ -89,7 +89,7 @@ describe 'Model controller' do
|
|
89
89
|
context 'with incorrect params' do
|
90
90
|
it 'doesn t create an instance and fails' do
|
91
91
|
expect{
|
92
|
-
post '/
|
92
|
+
post '/model', {}
|
93
93
|
}.to change(Model::ALL, :length).by(0)
|
94
94
|
|
95
95
|
last_response.should_not be_ok
|
@@ -103,7 +103,7 @@ describe 'Model controller' do
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
it 'should fail with no route available' do
|
106
|
-
post '/
|
106
|
+
post '/model', {:data => 'd'}
|
107
107
|
|
108
108
|
last_response.should_not be_ok
|
109
109
|
end
|
@@ -113,7 +113,7 @@ describe 'Model controller' do
|
|
113
113
|
context 'targeting an existing instance' do
|
114
114
|
it 'deletes the instance and succeed' do
|
115
115
|
expect{
|
116
|
-
delete '/
|
116
|
+
delete '/model/1'
|
117
117
|
}.to change(Model::ALL, :length).by(-1)
|
118
118
|
|
119
119
|
last_response.should be_ok
|
@@ -122,7 +122,7 @@ describe 'Model controller' do
|
|
122
122
|
context 'targeting a not existing instance' do
|
123
123
|
it 'does not delete any instance and fails' do
|
124
124
|
expect{
|
125
|
-
delete '/
|
125
|
+
delete '/model/6'
|
126
126
|
}.to change(Model::ALL, :length).by(0)
|
127
127
|
|
128
128
|
last_response.should_not be_ok
|
@@ -135,7 +135,7 @@ describe 'Model controller' do
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
it 'should fail with no route available' do
|
138
|
-
delete '/
|
138
|
+
delete '/model/2'
|
139
139
|
|
140
140
|
last_response.should_not be_ok
|
141
141
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yodatra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-03-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -139,6 +139,7 @@ files:
|
|
139
139
|
- lib/yodatra/initializers.rb
|
140
140
|
- lib/yodatra/logger.rb
|
141
141
|
- lib/yodatra/models_controller.rb
|
142
|
+
- lib/yodatra/throttling.rb
|
142
143
|
- lib/yodatra/utils.rb
|
143
144
|
- lib/yodatra/version.rb
|
144
145
|
- spec/spec_helper.rb
|