restfulness 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6461108ff8796134694c51592c8ccefc8053647e
4
- data.tar.gz: 22405556949ce5d69f7192f2c402038ca8b08802
3
+ metadata.gz: 5c7504fc661a80914cd4f3e3ad81918799de7b0b
4
+ data.tar.gz: a6b3d22e6fc9c30ba6010043550d37e3c651be0a
5
5
  SHA512:
6
- metadata.gz: 9bebef2fdf368de74cfb3f63e4acb15c087575fe76e34f24be3e62e47718f9f02c7b82b57993e81778483eaf3289244338620848e49027feb316504c0cffa743
7
- data.tar.gz: 867d7656b3e93b340ecd362ca7965b65741fb53af3a45e714eb770f9cef879214786bd472605d221a9258cc8d8d2d33305075dda37e410cc145d6c94e3f03af7
6
+ metadata.gz: d21da3dc7f1db2dd8b1259c36e710aa31698f31f5b39b37af0ecca2abc433fa15833941359efabcd9d74681b0570e63a1f4c651d0fb309b1b62c2fc656eb031f
7
+ data.tar.gz: e7fe0be99de3fcf1947e5fc75bfe2fce76bbd629e9b5cdf3b0370db2ae9e6a1f08a4353130392c3aa83770f37f0c00c0d67e67c4c024046eac142b6897b0ab68
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - jruby-19mode # JRuby in 1.9 mode
6
+ - rbx-19mode
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Because REST APIs are all about resources, not routes.
4
4
 
5
+ [![Build Status](https://travis-ci.org/samlown/restfulness.png)](https://travis-ci.org/samlown/restfulness)
6
+
5
7
  ## Introduction
6
8
 
7
9
  Restfulness is an attempt to create a Ruby library that helps create truly REST based APIs to your services. The focus is placed on performing HTTP actions on resources via specific routes, as opposed to the current convention of assigning routes and HTTP actions to methods or blocks of code. The difference is subtle, but makes for a much more natural approach to building APIs.
@@ -116,7 +118,6 @@ class MyAppAPI < Restfulness::Application
116
118
  add 'projects', ProjectsResource
117
119
  end
118
120
  end
119
-
120
121
  ```
121
122
 
122
123
  An application is designed to be included in your Rails, Sinatra, or other Rack project, simply include a new instance of your application in the `config.ru` file:
@@ -397,11 +398,12 @@ If you're adding Restfulness to a Rails project, you can take advantage of the `
397
398
  ```ruby
398
399
  class MyAPI < Restfulness::Application
399
400
  if Rails.env.development?
400
- middlewares << ActionDispatch::Relaoder
401
+ middlewares << ActionDispatch::Reloader
401
402
  end
402
403
  routes do
403
404
  # etc. etc.
404
405
  end
406
+ end
405
407
  ```
406
408
 
407
409
  We're still working on ways to improve this. If you have any ideas, please send me a pull request!
@@ -422,6 +424,11 @@ Restfulness was created by Sam Lown <me@samlown.com> as a solution for building
422
424
 
423
425
  ## History
424
426
 
427
+ ### 0.2.2 - October 31, 2013
428
+
429
+ * Refactoring logging support to not depend on Rack CommonLogger nor ShowExceptions.
430
+ * Using ActiveSupport::Logger instead of MonoLogger.
431
+
425
432
  ### 0.2.1 - October 22, 2013
426
433
 
427
434
  * Removing some unnecessary logging and using Rack::CommonLogger.
data/Rakefile CHANGED
@@ -1 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
data/example/README.md CHANGED
@@ -14,7 +14,7 @@ By default, bundler will expect to find the restfulness gem provided in the pare
14
14
 
15
15
  ## Running
16
16
 
17
- bundle exec runit
17
+ bundle exec rackup
18
18
 
19
19
  ## Testing
20
20
 
data/lib/restfulness.rb CHANGED
@@ -1,15 +1,14 @@
1
1
 
2
2
  require 'uri'
3
3
  require 'multi_json'
4
- require 'mono_logger'
5
4
  require 'active_support/core_ext'
6
5
  require 'active_support/dependencies'
6
+ require 'active_support/logger'
7
7
  require 'rack/utils'
8
8
  require 'rack/commonlogger'
9
9
  require 'rack/showexceptions'
10
10
  require 'rack/builder'
11
11
 
12
-
13
12
  require "restfulness/resources/events"
14
13
 
15
14
  require "restfulness/application"
@@ -26,15 +25,11 @@ require "restfulness/version"
26
25
 
27
26
  require "restfulness/dispatchers/rack"
28
27
 
29
- require "restfulness/log_formatters/quiet_formatter"
30
- require "restfulness/log_formatters/verbose_formatter"
31
-
32
28
  module Restfulness
33
29
  extend self
34
30
 
35
31
  attr_accessor :logger
36
32
  end
37
33
 
38
- Restfulness.logger = MonoLogger.new(STDOUT)
39
- Restfulness.logger.formatter = Restfulness::VerboseFormatter.new
34
+ Restfulness.logger = ActiveSupport::Logger.new(STDOUT)
40
35
 
@@ -62,10 +62,7 @@ module Restfulness
62
62
  # middlewares << ActiveDispatch::Reloader
63
63
  #
64
64
  def middlewares
65
- @middlewares ||= [
66
- Rack::CommonLogger,
67
- Rack::ShowExceptions
68
- ]
65
+ @middlewares ||= [ ]
69
66
  end
70
67
 
71
68
  # Quick access to the Restfulness logger.
@@ -20,12 +20,14 @@ module Restfulness
20
20
  def prepare_request(env)
21
21
  rack_req = ::Rack::Request.new(env)
22
22
  request = Request.new(app)
23
+
23
24
  request.uri = rack_req.url
24
25
  request.action = parse_action(rack_req.request_method)
25
26
  request.query = rack_req.GET
26
27
  request.body = rack_req.body
27
28
  request.headers = prepare_headers(env)
28
29
 
30
+ # Useful info
29
31
  request.remote_ip = rack_req.ip
30
32
  request.user_agent = rack_req.user_agent
31
33
 
@@ -6,18 +6,23 @@ module Restfulness
6
6
  # Incoming data
7
7
  attr_reader :request
8
8
 
9
+ # The generated resource object
10
+ attr_reader :resource
11
+
9
12
  # Outgoing data
10
13
  attr_reader :status, :headers, :payload
11
14
 
15
+
12
16
  def initialize(request)
13
17
  @request = request
14
18
  @headers = {}
15
19
  end
16
20
 
17
21
  def run
22
+ @log_begin_at = Time.now
18
23
  route = request.route
19
24
  if route
20
- resource = route.build_resource(request, self)
25
+ self.resource = route.build_resource(request, self)
21
26
 
22
27
  # run callbacks, if any fail, they'll raise an error
23
28
  resource.check_callbacks
@@ -33,10 +38,26 @@ module Restfulness
33
38
  rescue HTTPException => e # Deal with HTTP exceptions
34
39
  headers.update(e.headers)
35
40
  update_status_and_payload(e.status, e.payload)
41
+
42
+ rescue StandardError, LoadError, SyntaxError => e
43
+ # Useful coding error handling, with backtrace
44
+ log_exception(e)
45
+ update_status_and_payload(500, e.message + "\n")
46
+
47
+ ensure
48
+ log! if status
49
+ end
50
+
51
+ def content_length
52
+ payload.to_s.bytesize.to_s
36
53
  end
37
54
 
38
55
  protected
39
56
 
57
+ def resource=(obj)
58
+ @resource = obj
59
+ end
60
+
40
61
  def update_status_and_payload(status, payload = "")
41
62
  self.status = status
42
63
  self.payload = payload
@@ -63,9 +84,37 @@ module Restfulness
63
84
  else # Assume text
64
85
  headers['Content-Type'] = 'text/plain; charset=utf-8'
65
86
  end
66
- headers['Content-Length'] = payload.to_s.bytesize.to_s
87
+ headers['Content-Length'] = content_length
67
88
  end
68
89
 
69
- end
90
+ def log!
91
+ dur = @log_begin_at ? Time.now - @log_begin_at : 0.0
92
+ uri = request.uri
93
+
94
+ resource_name = resource ? resource.class.to_s : 'Error'
95
+ # We're only interested in parsed parameters.
96
+ params = request.instance_variable_get(:@params)
97
+
98
+ msg = %{%s "%s %s%s" %s %d %s %s %0.4fs %s} % [
99
+ request.remote_ip,
100
+ request.action.to_s.upcase,
101
+ uri.path,
102
+ uri.query ? "?#{uri.query}" : '',
103
+ resource_name,
104
+ status.to_s[0..3],
105
+ STATUSES[status],
106
+ content_length,
107
+ dur,
108
+ params ? params.inspect : ''
109
+ ]
110
+ Restfulness.logger.info(msg)
111
+ end
70
112
 
113
+ def log_exception(e)
114
+ string = "#{e.class}: #{e.message}\n"
115
+ string << e.backtrace.map { |l| "\t#{l}" }.join("\n")
116
+ Restfulness.logger.error(string)
117
+ end
118
+
119
+ end
71
120
  end
@@ -1,3 +1,3 @@
1
1
  module Restfulness
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
data/restfulness.gemspec CHANGED
@@ -21,7 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "rack", "~> 1.4"
22
22
  spec.add_dependency "multi_json", "~> 1.8"
23
23
  spec.add_dependency "activesupport", ">= 3.1"
24
- spec.add_dependency "mono_logger", "~> 1.0"
25
24
 
26
25
  spec.add_development_dependency "bundler", "~> 1.3"
27
26
  spec.add_development_dependency "rake"
@@ -32,6 +32,7 @@ describe Restfulness::Application do
32
32
  describe "#build_rack_app (protected)" do
33
33
  it "should build a new rack app with middlewares" do
34
34
  obj = klass.new
35
+ obj.class.middlewares << Rack::ShowExceptions
35
36
  app = obj.send(:build_rack_app)
36
37
  app.should be_a(Rack::Builder)
37
38
  # Note, this might brake if Rack changes!
@@ -65,9 +66,9 @@ describe Restfulness::Application do
65
66
  end
66
67
 
67
68
  describe ".middlewares" do
68
- it "should provide simple array of middlewares" do
69
+ it "should provide empty array of middlewares" do
69
70
  klass.middlewares.should be_a(Array)
70
- klass.middlewares.should include(Rack::ShowExceptions)
71
+ klass.middlewares.should be_empty
71
72
  end
72
73
  end
73
74
 
@@ -50,7 +50,10 @@ describe Restfulness::Resource do
50
50
  it "should return list of supported methods" do
51
51
  obj = resource.new(request, response)
52
52
  obj.options.should be_nil
53
- response.headers['Allow'].should eql('GET, POST, OPTIONS')
53
+ acts = response.headers['Allow'].split(/, /)
54
+ ['GET', 'POST', 'OPTIONS'].each do |act|
55
+ acts.should include(act)
56
+ end
54
57
  end
55
58
  end
56
59
 
@@ -36,6 +36,7 @@ describe Restfulness::Response do
36
36
  context "without route" do
37
37
  it "should not do anything" do
38
38
  request.stub(:route).and_return(nil)
39
+ request.stub(:uri).and_return(URI('http://test.com/test'))
39
40
  obj.run
40
41
  obj.status.should eql(404)
41
42
  obj.payload.should be_empty
@@ -51,6 +52,7 @@ describe Restfulness::Response do
51
52
  it "should try to build resource and run it" do
52
53
  request.stub(:route).and_return(route)
53
54
  request.action = :get
55
+ request.stub(:uri).and_return(URI('http://test.com/test'))
54
56
  resource = double(:Resource)
55
57
  resource.should_receive(:check_callbacks)
56
58
  resource.should_receive(:call).and_return({:foo => 'bar'})
@@ -66,6 +68,7 @@ describe Restfulness::Response do
66
68
  it "should call resource and set 204 result if no content" do
67
69
  request.stub(:route).and_return(route)
68
70
  request.action = :get
71
+ request.stub(:uri).and_return(URI('http://test.com/test'))
69
72
  resource = double(:Resource)
70
73
  resource.should_receive(:check_callbacks)
71
74
  resource.should_receive(:call).and_return(nil)
@@ -78,6 +81,7 @@ describe Restfulness::Response do
78
81
  it "should set string content type if payload is a string" do
79
82
  request.stub(:route).and_return(route)
80
83
  request.action = :get
84
+ request.stub(:uri).and_return(URI('http://test.com/test'))
81
85
  resource = double(:Resource)
82
86
  resource.should_receive(:check_callbacks)
83
87
  resource.should_receive(:call).and_return("This is a text message")
@@ -96,6 +100,7 @@ describe Restfulness::Response do
96
100
  it "should update the status and payload" do
97
101
  request.stub(:route).and_return(route)
98
102
  request.action = :get
103
+ request.stub(:uri).and_return(URI('http://test.com/test'))
99
104
  resource = double(:Resource)
100
105
  txt = "This is a text error"
101
106
  resource.stub(:check_callbacks) do
@@ -111,6 +116,7 @@ describe Restfulness::Response do
111
116
  it "should update the status and provide JSON payload" do
112
117
  request.stub(:route).and_return(route)
113
118
  request.action = :get
119
+ request.stub(:uri).and_return(URI('http://test.com/test'))
114
120
  resource = double(:Resource)
115
121
  err = {:error => "This is a text error"}
116
122
  resource.stub(:check_callbacks) do
@@ -123,6 +129,22 @@ describe Restfulness::Response do
123
129
  obj.payload.should eql(err.to_json)
124
130
  end
125
131
 
132
+ context "for non http errors" do
133
+
134
+ it "should catch error and provide result" do
135
+ request.stub(:route).and_return(route)
136
+ request.action = :get
137
+ request.stub(:uri).and_return(URI('http://test.com/test'))
138
+ resource = double(:Resource)
139
+ resource.stub(:check_callbacks) do
140
+ raise SyntaxError, 'Bad writing'
141
+ end
142
+ route.stub(:build_resource).and_return(resource)
143
+ obj.run
144
+ obj.status.should eql(500)
145
+ end
146
+
147
+ end
126
148
 
127
149
  end
128
150
 
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.1
4
+ version: 0.2.2
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-22 00:00:00.000000000 Z
11
+ date: 2013-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.1'
55
- - !ruby/object:Gem::Dependency
56
- name: mono_logger
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ~>
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: bundler
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -116,6 +102,7 @@ extensions: []
116
102
  extra_rdoc_files: []
117
103
  files:
118
104
  - .gitignore
105
+ - .travis.yml
119
106
  - Gemfile
120
107
  - LICENSE.txt
121
108
  - README.md
@@ -129,8 +116,6 @@ files:
129
116
  - lib/restfulness/dispatcher.rb
130
117
  - lib/restfulness/dispatchers/rack.rb
131
118
  - lib/restfulness/exceptions.rb
132
- - lib/restfulness/log_formatters/quiet_formatter.rb
133
- - lib/restfulness/log_formatters/verbose_formatter.rb
134
119
  - lib/restfulness/path.rb
135
120
  - lib/restfulness/request.rb
136
121
  - lib/restfulness/resource.rb
@@ -1,7 +0,0 @@
1
- module Restfulness
2
- class QuietFormatter
3
- def call(serverity, datetime, progname, msg)
4
- ""
5
- end
6
- end
7
- end
@@ -1,16 +0,0 @@
1
- module Restfulness
2
- class VerboseFormatter
3
- def call(serverity, datetime, progname, msg)
4
- time = Time.now.strftime('%Y-%m-%d %H:%M:%S.%L')
5
- sym = case serverity
6
- when 'ERROR'
7
- 'EE'
8
- when 'INFO'
9
- '--'
10
- else
11
- '**'
12
- end
13
- "#{sym} #{time}: #{msg}\n"
14
- end
15
- end
16
- end