restfulness 0.2.0 → 0.2.1
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/README.md +8 -1
- data/lib/restfulness.rb +1 -0
- data/lib/restfulness/application.rb +2 -1
- data/lib/restfulness/dispatchers/rack.rb +16 -34
- data/lib/restfulness/request.rb +2 -2
- data/lib/restfulness/resource.rb +1 -2
- data/lib/restfulness/response.rb +0 -8
- data/lib/restfulness/version.rb +1 -1
- data/spec/unit/dispatchers/rack_spec.rb +77 -9
- 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: 6461108ff8796134694c51592c8ccefc8053647e
|
4
|
+
data.tar.gz: 22405556949ce5d69f7192f2c402038ca8b08802
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bebef2fdf368de74cfb3f63e4acb15c087575fe76e34f24be3e62e47718f9f02c7b82b57993e81778483eaf3289244338620848e49027feb316504c0cffa743
|
7
|
+
data.tar.gz: 867d7656b3e93b340ecd362ca7965b65741fb53af3a45e714eb770f9cef879214786bd472605d221a9258cc8d8d2d33305075dda37e410cc145d6c94e3f03af7
|
data/README.md
CHANGED
@@ -422,9 +422,16 @@ Restfulness was created by Sam Lown <me@samlown.com> as a solution for building
|
|
422
422
|
|
423
423
|
## History
|
424
424
|
|
425
|
+
### 0.2.1 - October 22, 2013
|
426
|
+
|
427
|
+
* Removing some unnecessary logging and using Rack::CommonLogger.
|
428
|
+
* Improving some test coverage.
|
429
|
+
* Supporting user agent in requests.
|
430
|
+
* Supporting PATCH method in resources.
|
431
|
+
|
425
432
|
### 0.2.0 - October 17, 2013
|
426
433
|
|
427
|
-
Refactoring error handling and reporting so that it is easier to use and simpler.
|
434
|
+
* Refactoring error handling and reporting so that it is easier to use and simpler.
|
428
435
|
|
429
436
|
### 0.1.0 - October 16, 2013
|
430
437
|
|
data/lib/restfulness.rb
CHANGED
@@ -10,7 +10,7 @@ module Restfulness
|
|
10
10
|
# class MyApp < Restfulness::Application
|
11
11
|
#
|
12
12
|
# routes do
|
13
|
-
# scope 'api' do
|
13
|
+
# scope 'api' do # scope not supported yet!
|
14
14
|
# add 'journey', JourneyResource
|
15
15
|
# add 'journeys', JourneyCollectionResource
|
16
16
|
# end
|
@@ -63,6 +63,7 @@ module Restfulness
|
|
63
63
|
#
|
64
64
|
def middlewares
|
65
65
|
@middlewares ||= [
|
66
|
+
Rack::CommonLogger,
|
66
67
|
Rack::ShowExceptions
|
67
68
|
]
|
68
69
|
end
|
@@ -5,59 +5,45 @@ module Restfulness
|
|
5
5
|
class Rack < Dispatcher
|
6
6
|
|
7
7
|
def call(env)
|
8
|
-
rack_req = ::Rack::Request.new(env)
|
9
|
-
|
10
8
|
# Make sure we understand the request
|
11
|
-
request =
|
12
|
-
prepare_request(env, rack_req, request)
|
9
|
+
request = prepare_request(env)
|
13
10
|
|
14
11
|
# Prepare a suitable response
|
15
12
|
response = Response.new(request)
|
16
13
|
response.run
|
17
14
|
|
18
|
-
log_response(response.status)
|
19
15
|
[response.status, response.headers, [response.payload || ""]]
|
20
16
|
end
|
21
17
|
|
22
18
|
protected
|
23
19
|
|
24
|
-
def prepare_request(env
|
25
|
-
|
26
|
-
request
|
27
|
-
request.
|
28
|
-
request.
|
29
|
-
request.
|
30
|
-
request.
|
20
|
+
def prepare_request(env)
|
21
|
+
rack_req = ::Rack::Request.new(env)
|
22
|
+
request = Request.new(app)
|
23
|
+
request.uri = rack_req.url
|
24
|
+
request.action = parse_action(rack_req.request_method)
|
25
|
+
request.query = rack_req.GET
|
26
|
+
request.body = rack_req.body
|
27
|
+
request.headers = prepare_headers(env)
|
28
|
+
|
29
|
+
request.remote_ip = rack_req.ip
|
30
|
+
request.user_agent = rack_req.user_agent
|
31
31
|
|
32
32
|
# Sometimes rack removes content type from headers
|
33
33
|
request.headers[:content_type] ||= rack_req.content_type
|
34
|
+
|
35
|
+
request
|
34
36
|
end
|
35
37
|
|
36
38
|
def parse_action(action)
|
37
39
|
case action
|
38
|
-
when 'DELETE'
|
39
|
-
|
40
|
-
when 'GET'
|
41
|
-
:get
|
42
|
-
when 'HEAD'
|
43
|
-
:head
|
44
|
-
when 'POST'
|
45
|
-
:post
|
46
|
-
when 'PUT'
|
47
|
-
:put
|
48
|
-
when 'PATCH'
|
49
|
-
:patch
|
50
|
-
when 'OPTIONS'
|
51
|
-
:options
|
40
|
+
when 'DELETE', 'GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'OPTIONS'
|
41
|
+
action.downcase.to_sym
|
52
42
|
else
|
53
43
|
raise HTTPException.new(501)
|
54
44
|
end
|
55
45
|
end
|
56
46
|
|
57
|
-
def log_response(status)
|
58
|
-
logger.info("Completed #{status} #{STATUSES[status]}")
|
59
|
-
end
|
60
|
-
|
61
47
|
def prepare_headers(env)
|
62
48
|
res = {}
|
63
49
|
env.each do |k,v|
|
@@ -67,10 +53,6 @@ module Restfulness
|
|
67
53
|
res
|
68
54
|
end
|
69
55
|
|
70
|
-
def logger
|
71
|
-
Restfulness.logger
|
72
|
-
end
|
73
|
-
|
74
56
|
end
|
75
57
|
|
76
58
|
end
|
data/lib/restfulness/request.rb
CHANGED
@@ -30,8 +30,8 @@ module Restfulness
|
|
30
30
|
# Raw HTTP body, for POST and PUT requests.
|
31
31
|
attr_accessor :body
|
32
32
|
|
33
|
-
#
|
34
|
-
attr_accessor :remote_ip
|
33
|
+
# Additional useful fields
|
34
|
+
attr_accessor :remote_ip, :user_agent
|
35
35
|
|
36
36
|
def initialize(app)
|
37
37
|
@app = app
|
data/lib/restfulness/resource.rb
CHANGED
@@ -57,8 +57,7 @@ module Restfulness
|
|
57
57
|
forbidden! unless allowed?
|
58
58
|
|
59
59
|
# The following callbacks only make sense for certain methods
|
60
|
-
if [:head, :get, :put, :delete].include?(request.action)
|
61
|
-
|
60
|
+
if [:head, :get, :put, :patch, :delete].include?(request.action)
|
62
61
|
resource_not_found! unless exists?
|
63
62
|
|
64
63
|
if [:get, :head].include?(request.action)
|
data/lib/restfulness/response.rb
CHANGED
@@ -15,11 +15,8 @@ module Restfulness
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def run
|
18
|
-
logger.info("Responding to #{request.action.to_s.upcase} #{request.uri.to_s} from #{request.remote_ip}")
|
19
|
-
|
20
18
|
route = request.route
|
21
19
|
if route
|
22
|
-
logger.info("Using resource: #{route.resource_name}")
|
23
20
|
resource = route.build_resource(request, self)
|
24
21
|
|
25
22
|
# run callbacks, if any fail, they'll raise an error
|
@@ -34,15 +31,10 @@ module Restfulness
|
|
34
31
|
end
|
35
32
|
|
36
33
|
rescue HTTPException => e # Deal with HTTP exceptions
|
37
|
-
logger.error(e.message)
|
38
34
|
headers.update(e.headers)
|
39
35
|
update_status_and_payload(e.status, e.payload)
|
40
36
|
end
|
41
37
|
|
42
|
-
def logger
|
43
|
-
Restfulness.logger
|
44
|
-
end
|
45
|
-
|
46
38
|
protected
|
47
39
|
|
48
40
|
def update_status_and_payload(status, payload = "")
|
data/lib/restfulness/version.rb
CHANGED
@@ -3,12 +3,22 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
describe Restfulness::Dispatchers::Rack do
|
5
5
|
|
6
|
+
class RackExampleResource < Restfulness::Resource
|
7
|
+
def get
|
8
|
+
'rack_example_result'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
6
12
|
let :klass do
|
7
13
|
Restfulness::Dispatchers::Rack
|
8
14
|
end
|
9
15
|
|
10
16
|
let :app do
|
11
|
-
Class.new(Restfulness::Application)
|
17
|
+
Class.new(Restfulness::Application) {
|
18
|
+
routes do
|
19
|
+
add 'projects', RackExampleResource
|
20
|
+
end
|
21
|
+
}.new
|
12
22
|
end
|
13
23
|
|
14
24
|
let :obj do
|
@@ -17,17 +27,75 @@ describe Restfulness::Dispatchers::Rack do
|
|
17
27
|
|
18
28
|
let :env do
|
19
29
|
{
|
20
|
-
'REQUEST_METHOD'
|
21
|
-
'SCRIPT_NAME'
|
22
|
-
'PATH_INFO'
|
23
|
-
'QUERY_STRING'
|
24
|
-
'SERVER_NAME'
|
25
|
-
'SERVER_PORT'
|
26
|
-
'
|
30
|
+
'REQUEST_METHOD' => 'GET',
|
31
|
+
'SCRIPT_NAME' => '',
|
32
|
+
'PATH_INFO' => '/projects',
|
33
|
+
'QUERY_STRING' => '',
|
34
|
+
'SERVER_NAME' => 'localhost',
|
35
|
+
'SERVER_PORT' => '3000',
|
36
|
+
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
37
|
+
'rack.url_scheme' => 'http',
|
38
|
+
'REMOTE_ADDR' => '192.168.1.23',
|
39
|
+
'HTTP_CONTENT_TYPE' => 'application/json',
|
40
|
+
'HTTP_X_AUTH_TOKEN' => 'foobartoken',
|
41
|
+
'HTTP_USER_AGENT' => 'Some Navigator',
|
27
42
|
}
|
28
43
|
end
|
29
44
|
|
30
|
-
describe "#" do
|
45
|
+
describe "#call" do
|
46
|
+
|
47
|
+
it "should handle basic call and return response" do
|
48
|
+
res = obj.call(env)
|
49
|
+
res[0].should eql(200)
|
50
|
+
res[1].should be_a(Hash)
|
51
|
+
res[2].first.should eql('rack_example_result')
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#parse_action (protected)" do
|
58
|
+
|
59
|
+
it "should convert main actions to symbols" do
|
60
|
+
actions = ['DELETE', 'GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'OPTIONS']
|
61
|
+
actions.each do |action|
|
62
|
+
val = obj.send(:parse_action, action)
|
63
|
+
val.should eql(action.downcase.to_sym)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should raise error if action unrecognised" do
|
68
|
+
expect {
|
69
|
+
obj.send(:parse_action, 'FOOO')
|
70
|
+
}.to raise_error(Restfulness::HTTPException)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#prepare_headers (protected)" do
|
76
|
+
|
77
|
+
it "should parse headers from environment" do
|
78
|
+
res = obj.send(:prepare_headers, env)
|
79
|
+
res[:content_type].should eql('application/json')
|
80
|
+
res[:x_auth_token].should eql('foobartoken')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#prepare_request (protected)" do
|
85
|
+
|
86
|
+
it "should prepare request object with main fields" do
|
87
|
+
req = obj.send(:prepare_request, env)
|
88
|
+
|
89
|
+
req.uri.should be_a(URI)
|
90
|
+
req.action.should eql(:get)
|
91
|
+
req.query.should be_empty
|
92
|
+
req.body.should be_nil
|
93
|
+
req.headers.keys.should include(:x_auth_token)
|
94
|
+
req.remote_ip.should eql('192.168.1.23')
|
95
|
+
req.user_agent.should eql('Some Navigator')
|
96
|
+
|
97
|
+
req.headers[:content_type].should eql('application/json')
|
98
|
+
end
|
31
99
|
|
32
100
|
end
|
33
101
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restfulness
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Lown
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|