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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 656fc9b27618b6b00f0cdc31dff51fc59081881b
4
- data.tar.gz: eed7ea6153eb14c67d0888643287ed911bfb477a
3
+ metadata.gz: 6461108ff8796134694c51592c8ccefc8053647e
4
+ data.tar.gz: 22405556949ce5d69f7192f2c402038ca8b08802
5
5
  SHA512:
6
- metadata.gz: d06a2ee69944bfd705f22516c246ec49293488e69bc7bc5f7357cbe3830ac1b283e5e5046063c4e22e427d5ddf2541811c2d49b0e285eb742c63c0f132b64564
7
- data.tar.gz: b297d63290e7df33142641c2c8d072d97bb4494ece946b8ec6f2ddb4c44e10ac6cd997729689ede5fefb299f492c77b74e82b9646f04793ca49f77c473a99e70
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
@@ -5,6 +5,7 @@ require 'mono_logger'
5
5
  require 'active_support/core_ext'
6
6
  require 'active_support/dependencies'
7
7
  require 'rack/utils'
8
+ require 'rack/commonlogger'
8
9
  require 'rack/showexceptions'
9
10
  require 'rack/builder'
10
11
 
@@ -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 = Request.new(app)
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, rack_req, request)
25
- request.uri = rack_req.url
26
- request.action = parse_action(rack_req.request_method)
27
- request.query = rack_req.GET
28
- request.body = rack_req.body
29
- request.remote_ip = rack_req.ip
30
- request.headers = prepare_headers(env)
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
- :delete
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
@@ -30,8 +30,8 @@ module Restfulness
30
30
  # Raw HTTP body, for POST and PUT requests.
31
31
  attr_accessor :body
32
32
 
33
- # IP address of requester
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
@@ -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)
@@ -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 = "")
@@ -1,3 +1,3 @@
1
1
  module Restfulness
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -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).new
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' => 'GET',
21
- 'SCRIPT_NAME' => 'projects',
22
- 'PATH_INFO' => 'projects',
23
- 'QUERY_STRING' => '',
24
- 'SERVER_NAME' => 'localhost',
25
- 'SERVER_PORT' => '3000',
26
- 'HTTP_CONTENT_TYPE' => 'application/json'
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.0
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-17 00:00:00.000000000 Z
11
+ date: 2013-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack