restfulness 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +6 -5
- data/README.md +98 -80
- data/lib/restfulness.rb +3 -0
- data/lib/restfulness/dispatchers/rack.rb +1 -0
- data/lib/restfulness/headers/accept.rb +66 -0
- data/lib/restfulness/headers/media_type.rb +127 -0
- data/lib/restfulness/request.rb +43 -15
- data/lib/restfulness/version.rb +1 -1
- data/restfulness.gemspec +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/application_spec.rb +14 -14
- data/spec/unit/dispatcher_spec.rb +1 -1
- data/spec/unit/dispatchers/rack_spec.rb +21 -20
- data/spec/unit/exceptions_spec.rb +5 -5
- data/spec/unit/headers/accept_spec.rb +70 -0
- data/spec/unit/headers/media_type_spec.rb +262 -0
- data/spec/unit/http_authentication/basic_spec.rb +7 -7
- data/spec/unit/path_spec.rb +19 -19
- data/spec/unit/request_spec.rb +96 -44
- data/spec/unit/requests/authorization_header_spec.rb +8 -8
- data/spec/unit/requests/authorization_spec.rb +3 -3
- data/spec/unit/resource_spec.rb +28 -28
- data/spec/unit/resources/authentication_spec.rb +2 -2
- data/spec/unit/resources/events_spec.rb +1 -1
- data/spec/unit/response_spec.rb +53 -53
- data/spec/unit/route_spec.rb +24 -24
- data/spec/unit/router_spec.rb +29 -29
- data/spec/unit/sanitizer_spec.rb +9 -9
- metadata +13 -7
@@ -28,8 +28,8 @@ describe Restfulness::Resources::Authentication do
|
|
28
28
|
obj = AuthResource.new(request, response)
|
29
29
|
expect { |b| obj.authenticate_with_http_basic(&b) }.to yield_control
|
30
30
|
obj.authenticate_with_http_basic do |username, password|
|
31
|
-
username.
|
32
|
-
password.
|
31
|
+
expect(username).to eql('Aladdin')
|
32
|
+
expect(password).to eql('open sesame')
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -54,7 +54,7 @@ describe Restfulness::Resources::Events do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
it "should support bad_request! with paramters" do
|
57
|
-
obj.
|
57
|
+
expect(obj).to receive(:error!).with(400, {:pay => 'load'}, {})
|
58
58
|
obj.instance_eval do
|
59
59
|
bad_request!({:pay => 'load'}, {})
|
60
60
|
end
|
data/spec/unit/response_spec.rb
CHANGED
@@ -25,23 +25,23 @@ describe Restfulness::Response do
|
|
25
25
|
|
26
26
|
describe "#initialize" do
|
27
27
|
it "should assign request and headers" do
|
28
|
-
obj.request.
|
29
|
-
obj.headers.
|
30
|
-
obj.status.
|
31
|
-
obj.payload.
|
28
|
+
expect(obj.request).to eql(request)
|
29
|
+
expect(obj.headers).to eql({})
|
30
|
+
expect(obj.status).to be_nil
|
31
|
+
expect(obj.payload).to be_nil
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
describe "#run" do
|
36
36
|
context "without route" do
|
37
37
|
it "should not do anything" do
|
38
|
-
request.
|
39
|
-
request.
|
38
|
+
allow(request).to receive(:route).and_return(nil)
|
39
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
40
40
|
obj.run
|
41
|
-
obj.status.
|
42
|
-
obj.payload.
|
43
|
-
obj.headers['Content-Type'].
|
44
|
-
obj.headers['Content-Length'].
|
41
|
+
expect(obj.status).to eql(404)
|
42
|
+
expect(obj.payload).to be_empty
|
43
|
+
expect(obj.headers['Content-Type']).to be_nil
|
44
|
+
expect(obj.headers['Content-Length']).to be_nil
|
45
45
|
end
|
46
46
|
end
|
47
47
|
context "with route" do
|
@@ -50,46 +50,46 @@ describe Restfulness::Response do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should try to build resource and run it" do
|
53
|
-
request.
|
53
|
+
allow(request).to receive(:route).and_return(route)
|
54
54
|
request.action = :get
|
55
|
-
request.
|
55
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
56
56
|
resource = double(:Resource)
|
57
|
-
resource.
|
58
|
-
resource.
|
59
|
-
route.
|
57
|
+
expect(resource).to receive(:check_callbacks)
|
58
|
+
expect(resource).to receive(:call).and_return({:foo => 'bar'})
|
59
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
60
60
|
obj.run
|
61
|
-
obj.status.
|
61
|
+
expect(obj.status).to eql(200)
|
62
62
|
str = "{\"foo\":\"bar\"}"
|
63
|
-
obj.payload.
|
64
|
-
obj.headers['Content-Type'].
|
65
|
-
obj.headers['Content-Length'].
|
63
|
+
expect(obj.payload).to eql(str)
|
64
|
+
expect(obj.headers['Content-Type']).to match(/application\/json/)
|
65
|
+
expect(obj.headers['Content-Length']).to eql(str.bytesize.to_s)
|
66
66
|
end
|
67
67
|
|
68
68
|
it "should call resource and set 204 result if no content" do
|
69
|
-
request.
|
69
|
+
allow(request).to receive(:route).and_return(route)
|
70
70
|
request.action = :get
|
71
|
-
request.
|
71
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
72
72
|
resource = double(:Resource)
|
73
|
-
resource.
|
74
|
-
resource.
|
75
|
-
route.
|
73
|
+
expect(resource).to receive(:check_callbacks)
|
74
|
+
expect(resource).to receive(:call).and_return(nil)
|
75
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
76
76
|
obj.run
|
77
|
-
obj.status.
|
78
|
-
obj.headers['Content-Type'].
|
79
|
-
obj.headers['Content-Length'].
|
77
|
+
expect(obj.status).to eql(204)
|
78
|
+
expect(obj.headers['Content-Type']).to be_nil
|
79
|
+
expect(obj.headers['Content-Length']).to be_nil
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should set string content type if payload is a string" do
|
83
|
-
request.
|
83
|
+
allow(request).to receive(:route).and_return(route)
|
84
84
|
request.action = :get
|
85
|
-
request.
|
85
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
86
86
|
resource = double(:Resource)
|
87
|
-
resource.
|
88
|
-
resource.
|
89
|
-
route.
|
87
|
+
expect(resource).to receive(:check_callbacks)
|
88
|
+
expect(resource).to receive(:call).and_return("This is a text message")
|
89
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
90
90
|
obj.run
|
91
|
-
obj.status.
|
92
|
-
obj.headers['Content-Type'].
|
91
|
+
expect(obj.status).to eql(200)
|
92
|
+
expect(obj.headers['Content-Type']).to match(/text\/plain/)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -99,50 +99,50 @@ describe Restfulness::Response do
|
|
99
99
|
end
|
100
100
|
|
101
101
|
it "should update the status and payload" do
|
102
|
-
request.
|
102
|
+
allow(request).to receive(:route).and_return(route)
|
103
103
|
request.action = :get
|
104
|
-
request.
|
104
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
105
105
|
resource = double(:Resource)
|
106
106
|
txt = "This is a text error"
|
107
|
-
resource.
|
107
|
+
allow(resource).to receive(:check_callbacks) do
|
108
108
|
raise Restfulness::HTTPException.new(418, txt)
|
109
109
|
end
|
110
|
-
route.
|
110
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
111
111
|
obj.run
|
112
|
-
obj.status.
|
113
|
-
obj.headers['Content-Type'].
|
114
|
-
obj.payload.
|
112
|
+
expect(obj.status).to eql(418)
|
113
|
+
expect(obj.headers['Content-Type']).to match(/text\/plain/)
|
114
|
+
expect(obj.payload).to eql(txt)
|
115
115
|
end
|
116
116
|
|
117
117
|
it "should update the status and provide JSON payload" do
|
118
|
-
request.
|
118
|
+
allow(request).to receive(:route).and_return(route)
|
119
119
|
request.action = :get
|
120
|
-
request.
|
120
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
121
121
|
resource = double(:Resource)
|
122
122
|
err = {:error => "This is a text error"}
|
123
|
-
resource.
|
123
|
+
allow(resource).to receive(:check_callbacks) do
|
124
124
|
raise Restfulness::HTTPException.new(418, err)
|
125
125
|
end
|
126
|
-
route.
|
126
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
127
127
|
obj.run
|
128
|
-
obj.status.
|
129
|
-
obj.headers['Content-Type'].
|
130
|
-
obj.payload.
|
128
|
+
expect(obj.status).to eql(418)
|
129
|
+
expect(obj.headers['Content-Type']).to match(/application\/json/)
|
130
|
+
expect(obj.payload).to eql(err.to_json)
|
131
131
|
end
|
132
132
|
|
133
133
|
context "for non http errors" do
|
134
134
|
|
135
135
|
it "should catch error and provide result" do
|
136
|
-
request.
|
136
|
+
allow(request).to receive(:route).and_return(route)
|
137
137
|
request.action = :get
|
138
|
-
request.
|
138
|
+
allow(request).to receive(:uri).and_return(URI('http://test.com/test'))
|
139
139
|
resource = double(:Resource)
|
140
|
-
resource.
|
140
|
+
allow(resource).to receive(:check_callbacks) do
|
141
141
|
raise SyntaxError, 'Bad writing'
|
142
142
|
end
|
143
|
-
route.
|
143
|
+
allow(route).to receive(:build_resource).and_return(resource)
|
144
144
|
obj.run
|
145
|
-
obj.status.
|
145
|
+
expect(obj.status).to eql(500)
|
146
146
|
end
|
147
147
|
|
148
148
|
end
|
data/spec/unit/route_spec.rb
CHANGED
@@ -18,23 +18,23 @@ describe Restfulness::Route do
|
|
18
18
|
|
19
19
|
it "should assign basic path and resource" do
|
20
20
|
obj = klass.new('project', resource)
|
21
|
-
obj.path.
|
22
|
-
obj.resource_name.
|
21
|
+
expect(obj.path).to eql(['project'])
|
22
|
+
expect(obj.resource_name).to eql(resource.to_s)
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should assign path with symbols" do
|
26
26
|
obj = klass.new('project', :project_id, 'states', resource)
|
27
|
-
obj.path.
|
27
|
+
expect(obj.path).to eql(['project', :project_id, 'states'])
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should remove :id from end" do
|
31
31
|
obj = klass.new('project', :project_id, 'states', :id, resource)
|
32
|
-
obj.path.
|
32
|
+
expect(obj.path).to eql(['project', :project_id, 'states'])
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should handle numbers in path" do
|
36
36
|
obj = klass.new('project', 120, resource)
|
37
|
-
obj.path.
|
37
|
+
expect(obj.path).to eql(['project', 120])
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should accept classes as strings" do
|
@@ -60,7 +60,7 @@ describe Restfulness::Route do
|
|
60
60
|
describe "#resource" do
|
61
61
|
it "should provide constant to class" do
|
62
62
|
obj = klass.new('project', resource)
|
63
|
-
obj.resource.
|
63
|
+
expect(obj.resource).to eql(resource)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -68,8 +68,8 @@ describe Restfulness::Route do
|
|
68
68
|
it "should build a new path object including self" do
|
69
69
|
obj = klass.new('project', resource)
|
70
70
|
path = obj.build_path("/project/12345")
|
71
|
-
path.
|
72
|
-
path.route.
|
71
|
+
expect(path).to be_a(Restfulness::Path)
|
72
|
+
expect(path.route).to eql(obj)
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -80,16 +80,16 @@ describe Restfulness::Route do
|
|
80
80
|
klass.new('project', resource)
|
81
81
|
end
|
82
82
|
it "should return true for match" do
|
83
|
-
obj.handles?(['project']).
|
83
|
+
expect(obj.handles?(['project'])).to be true
|
84
84
|
end
|
85
85
|
it "should return true for match with id" do
|
86
|
-
obj.handles?(['project', '12345']).
|
86
|
+
expect(obj.handles?(['project', '12345'])).to be true
|
87
87
|
end
|
88
88
|
it "should return false for different name" do
|
89
|
-
obj.handles?(['projects']).
|
89
|
+
expect(obj.handles?(['projects'])).to be false
|
90
90
|
end
|
91
91
|
it "should return false for matching start" do
|
92
|
-
obj.handles?(['project', '12345', 'status']).
|
92
|
+
expect(obj.handles?(['project', '12345', 'status'])).to be false
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -98,13 +98,13 @@ describe Restfulness::Route do
|
|
98
98
|
klass.new(resource)
|
99
99
|
end
|
100
100
|
it "should matching empty path" do
|
101
|
-
obj.handles?([]).
|
101
|
+
expect(obj.handles?([])).to be true
|
102
102
|
end
|
103
103
|
it "should matching empty path with id" do
|
104
|
-
obj.handles?(['12345']).
|
104
|
+
expect(obj.handles?(['12345'])).to be true
|
105
105
|
end
|
106
106
|
it "shold not match extended URL" do
|
107
|
-
obj.handles?(['foobar', '12345']).
|
107
|
+
expect(obj.handles?(['foobar', '12345'])).to be false
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
@@ -113,13 +113,13 @@ describe Restfulness::Route do
|
|
113
113
|
klass.new(:project_id, resource)
|
114
114
|
end
|
115
115
|
it "should matching anything" do
|
116
|
-
obj.handles?(['foobar']).
|
116
|
+
expect(obj.handles?(['foobar'])).to be true
|
117
117
|
end
|
118
118
|
it "should matching anything, with id" do
|
119
|
-
obj.handles?(['foobar', '12345']).
|
119
|
+
expect(obj.handles?(['foobar', '12345'])).to be true
|
120
120
|
end
|
121
121
|
it "shold not match extended URL" do
|
122
|
-
obj.handles?(['foobar', 'status', '12345']).
|
122
|
+
expect(obj.handles?(['foobar', 'status', '12345'])).to be false
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
@@ -128,19 +128,19 @@ describe Restfulness::Route do
|
|
128
128
|
klass.new('project', :project_id, 'status', resource)
|
129
129
|
end
|
130
130
|
it "should return true for match" do
|
131
|
-
obj.handles?(['project', '1234', 'status']).
|
131
|
+
expect(obj.handles?(['project', '1234', 'status'])).to be true
|
132
132
|
end
|
133
133
|
it "should return true for match with id" do
|
134
|
-
obj.handles?(['project', '1234', 'status', '12345']).
|
134
|
+
expect(obj.handles?(['project', '1234', 'status', '12345'])).to be true
|
135
135
|
end
|
136
136
|
it "should not match short path" do
|
137
|
-
obj.handles?(['project']).
|
137
|
+
expect(obj.handles?(['project'])).to be false
|
138
138
|
end
|
139
139
|
it "should not match path with different name" do
|
140
|
-
obj.handles?(['project', '12345', 'statuses']).
|
140
|
+
expect(obj.handles?(['project', '12345', 'statuses'])).to be false
|
141
141
|
end
|
142
142
|
it "should not match extended path" do
|
143
|
-
obj.handles?(['project', '12345', 'status', '1234', 'test']).
|
143
|
+
expect(obj.handles?(['project', '12345', 'status', '1234', 'test'])).to be false
|
144
144
|
end
|
145
145
|
|
146
146
|
end
|
@@ -151,7 +151,7 @@ describe Restfulness::Route do
|
|
151
151
|
|
152
152
|
it "should request a new resource" do
|
153
153
|
obj = klass.new('project', resource)
|
154
|
-
resource.
|
154
|
+
expect(resource).to receive(:new).with({}, {}).and_return(nil)
|
155
155
|
obj.build_resource({}, {})
|
156
156
|
end
|
157
157
|
|
data/spec/unit/router_spec.rb
CHANGED
@@ -21,14 +21,14 @@ describe Restfulness::Router do
|
|
21
21
|
|
22
22
|
it "should prepare routes" do
|
23
23
|
obj = klass.new
|
24
|
-
obj.routes.
|
24
|
+
expect(obj.routes).to eql([])
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should prepare routes with instance eval block" do
|
28
28
|
obj = klass.new do
|
29
29
|
@foo = 'bar'
|
30
30
|
end
|
31
|
-
obj.instance_variable_get(:@foo).
|
31
|
+
expect(obj.instance_variable_get(:@foo)).to eql('bar')
|
32
32
|
end
|
33
33
|
|
34
34
|
end
|
@@ -37,10 +37,10 @@ describe Restfulness::Router do
|
|
37
37
|
it "should add route to object" do
|
38
38
|
obj = klass.new
|
39
39
|
obj.add 'projects', resource
|
40
|
-
obj.routes.length.
|
40
|
+
expect(obj.routes.length).to eql(1)
|
41
41
|
route = obj.routes.first
|
42
|
-
route.
|
43
|
-
route.path.
|
42
|
+
expect(route).to be_a(Restfulness::Route)
|
43
|
+
expect(route.path).to eql(['projects'])
|
44
44
|
end
|
45
45
|
it "should accept block as scope" do
|
46
46
|
obj = klass.new
|
@@ -48,11 +48,11 @@ describe Restfulness::Router do
|
|
48
48
|
add 'examples', SecondRouterResource
|
49
49
|
end
|
50
50
|
route = obj.routes.first
|
51
|
-
route.resource.
|
52
|
-
route.path.
|
51
|
+
expect(route.resource).to eql(SecondRouterResource)
|
52
|
+
expect(route.path).to eql(['project', 'examples'])
|
53
53
|
route = obj.routes.last
|
54
|
-
route.resource.
|
55
|
-
route.path.
|
54
|
+
expect(route.resource).to eql(RouterResource)
|
55
|
+
expect(route.path).to eql(['project'])
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -63,8 +63,8 @@ describe Restfulness::Router do
|
|
63
63
|
obj.scope 'api' do
|
64
64
|
subscope = current_scope
|
65
65
|
end
|
66
|
-
subscope.
|
67
|
-
obj.current_scope.
|
66
|
+
expect(subscope).to eql(['api'])
|
67
|
+
expect(obj.current_scope).to eql([])
|
68
68
|
end
|
69
69
|
|
70
70
|
it "should add scope properties to add call" do
|
@@ -74,7 +74,7 @@ describe Restfulness::Router do
|
|
74
74
|
add 'projects', res
|
75
75
|
end
|
76
76
|
route = obj.routes.first
|
77
|
-
route.path.
|
77
|
+
expect(route.path).to eql(['api', 'projects'])
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should allow for scopes within scopes" do
|
@@ -89,11 +89,11 @@ describe Restfulness::Router do
|
|
89
89
|
end
|
90
90
|
subscope = current_scope
|
91
91
|
end
|
92
|
-
subsubscope.
|
93
|
-
subscope.
|
94
|
-
obj.current_scope.
|
92
|
+
expect(subsubscope).to eql(['api', 'projects'])
|
93
|
+
expect(subscope).to eql(['api'])
|
94
|
+
expect(obj.current_scope).to eql([])
|
95
95
|
route = obj.routes.first
|
96
|
-
route.path.
|
96
|
+
expect(route.path).to eql(['api', 'projects', 'active'])
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
@@ -110,47 +110,47 @@ describe Restfulness::Router do
|
|
110
110
|
|
111
111
|
it "should determine the route for a simple path" do
|
112
112
|
route = obj.route_for("/projects")
|
113
|
-
route.
|
114
|
-
route.path.
|
113
|
+
expect(route).not_to be_nil
|
114
|
+
expect(route.path).to eql(['projects'])
|
115
115
|
end
|
116
116
|
|
117
117
|
it "should determine the route for a simple path with id" do
|
118
118
|
route = obj.route_for("/projects")
|
119
|
-
route.
|
120
|
-
route.path.
|
119
|
+
expect(route).not_to be_nil
|
120
|
+
expect(route.path).to eql(['projects'])
|
121
121
|
end
|
122
122
|
|
123
123
|
it "should determine the route for a simple path with id and end /" do
|
124
124
|
route = obj.route_for("/projects/12345/")
|
125
|
-
route.
|
126
|
-
route.path.
|
125
|
+
expect(route).not_to be_nil
|
126
|
+
expect(route.path).to eql(['projects'])
|
127
127
|
end
|
128
128
|
|
129
129
|
it "should determine the route for a simple path with end /" do
|
130
130
|
route = obj.route_for("/projects/")
|
131
|
-
route.
|
132
|
-
route.path.
|
131
|
+
expect(route).not_to be_nil
|
132
|
+
expect(route.path).to eql(['projects'])
|
133
133
|
end
|
134
134
|
|
135
135
|
it "should determine route for more complex path" do
|
136
136
|
route = obj.route_for("/project/1235/status/1234")
|
137
|
-
route.
|
138
|
-
route.path.
|
137
|
+
expect(route).not_to be_nil
|
138
|
+
expect(route.path).to eql(['project', :project_id, 'status'])
|
139
139
|
end
|
140
140
|
|
141
141
|
it "should return nil if not matched" do
|
142
142
|
route = obj.route_for("/projects/1235/statuses/")
|
143
|
-
route.
|
143
|
+
expect(route).to be_nil
|
144
144
|
end
|
145
145
|
|
146
146
|
it "should match empty path" do
|
147
147
|
route = obj.route_for("/")
|
148
|
-
route.path.
|
148
|
+
expect(route.path).to eql([])
|
149
149
|
end
|
150
150
|
|
151
151
|
it "should match path with single parameter" do
|
152
152
|
route = obj.route_for("/something")
|
153
|
-
route.path.
|
153
|
+
expect(route.path).to eql([:page])
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|