rack-api 0.2.2 → 0.3.0
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/Gemfile.lock +1 -1
- data/examples/helpers.rb +25 -0
- data/examples/rescue_from.rb +33 -0
- data/lib/rack/api/app.rb +22 -0
- data/lib/rack/api/runner.rb +21 -5
- data/lib/rack/api/version.rb +2 -2
- data/spec/rack-api/method_delegation_spec.rb +1 -0
- data/spec/rack-api/rescue_from_spec.rb +103 -0
- data/spec/rack-api/runner_spec.rb +1 -1
- metadata +6 -2
data/Gemfile.lock
CHANGED
data/examples/helpers.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
$:.push(File.dirname(__FILE__) + "/../lib")
|
2
|
+
|
3
|
+
# Just run `ruby examples/basic_auth.rb` and then use something like
|
4
|
+
# `curl http://localhost:2345/api/v1/` or
|
5
|
+
# `curl http://localhost:2345/api/v1/This%20is%20so%20cool`.
|
6
|
+
|
7
|
+
require "rack/api"
|
8
|
+
|
9
|
+
Rack::API.app do
|
10
|
+
prefix "api"
|
11
|
+
|
12
|
+
helper do
|
13
|
+
def default_message
|
14
|
+
"Hello from Rack API"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
version :v1 do
|
19
|
+
get "/(:message)" do
|
20
|
+
{:message => params.fetch(:message, default_message)}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Rack::Handler::Thin.run Rack::API, :Port => 2345
|
@@ -0,0 +1,33 @@
|
|
1
|
+
$:.push(File.dirname(__FILE__) + "/../lib")
|
2
|
+
|
3
|
+
# Just run `ruby examples/simple.rb` and then use something like
|
4
|
+
# `curl http://localhost:2345/api/v1/`.
|
5
|
+
|
6
|
+
require "rack/api"
|
7
|
+
require "logger"
|
8
|
+
|
9
|
+
$logger = Logger.new(STDOUT)
|
10
|
+
|
11
|
+
# Simulate ActiveRecord's exception.
|
12
|
+
module ActiveRecord
|
13
|
+
class RecordNotFound < StandardError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Rack::API.app do
|
18
|
+
prefix "api"
|
19
|
+
|
20
|
+
rescue_from ActiveRecord::RecordNotFound, :status => 404
|
21
|
+
rescue_from Exception do |error|
|
22
|
+
$logger.error error.message
|
23
|
+
[500, {"Content-Type" => "text/plain"}, []]
|
24
|
+
end
|
25
|
+
|
26
|
+
version :v1 do
|
27
|
+
get "/" do
|
28
|
+
raise "Oh no! Something is really wrong!"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Rack::Handler::Thin.run Rack::API, :Port => 2345
|
data/lib/rack/api/app.rb
CHANGED
@@ -48,6 +48,11 @@ module Rack
|
|
48
48
|
#
|
49
49
|
attr_accessor :url_options
|
50
50
|
|
51
|
+
# Hold handlers, that will wrap exceptions
|
52
|
+
# into a normalized response.
|
53
|
+
#
|
54
|
+
attr_accessor :rescuers
|
55
|
+
|
51
56
|
def initialize(options)
|
52
57
|
options.each do |name, value|
|
53
58
|
instance_variable_set("@#{name}", value)
|
@@ -158,6 +163,8 @@ module Rack
|
|
158
163
|
end
|
159
164
|
|
160
165
|
response.respond_to?(:to_rack) ? response.to_rack : response
|
166
|
+
rescue Exception => exception
|
167
|
+
handle_exception exception
|
161
168
|
end
|
162
169
|
|
163
170
|
# Return response content type based on extension.
|
@@ -229,6 +236,21 @@ module Rack
|
|
229
236
|
throw :error, Response.new(:status => 406, :message => "Unknown format")
|
230
237
|
end
|
231
238
|
end
|
239
|
+
|
240
|
+
def handle_exception(error) # :nodoc:
|
241
|
+
rescuer = rescuers.find do |r|
|
242
|
+
error_class = eval("::#{r[:class_name]}") rescue nil
|
243
|
+
error_class && error.kind_of?(error_class)
|
244
|
+
end
|
245
|
+
|
246
|
+
raise error unless rescuer
|
247
|
+
|
248
|
+
if rescuer[:block]
|
249
|
+
instance_exec(error, &rescuer[:block])
|
250
|
+
else
|
251
|
+
[rescuer[:options].fetch(:status, 500), {"Content-Type" => "text/plain"}, []]
|
252
|
+
end
|
253
|
+
end
|
232
254
|
end
|
233
255
|
end
|
234
256
|
end
|
data/lib/rack/api/runner.rb
CHANGED
@@ -4,7 +4,7 @@ module Rack
|
|
4
4
|
HTTP_METHODS = %w[get post put delete head]
|
5
5
|
|
6
6
|
DELEGATE_METHODS = %w[
|
7
|
-
version use prefix basic_auth
|
7
|
+
version use prefix basic_auth rescue_from
|
8
8
|
helper respond_to default_url_options
|
9
9
|
]
|
10
10
|
|
@@ -14,11 +14,13 @@ module Rack
|
|
14
14
|
@settings = {
|
15
15
|
:middlewares => [],
|
16
16
|
:helpers => [],
|
17
|
+
:rescuers => [],
|
17
18
|
:global => {
|
18
|
-
:prefix
|
19
|
-
:formats
|
19
|
+
:prefix => "/",
|
20
|
+
:formats => %w[json jsonp],
|
20
21
|
:middlewares => [],
|
21
|
-
:helpers
|
22
|
+
:helpers => [],
|
23
|
+
:rescuers => []
|
22
24
|
}
|
23
25
|
}
|
24
26
|
end
|
@@ -234,6 +236,19 @@ module Rack
|
|
234
236
|
RUBY
|
235
237
|
end
|
236
238
|
|
239
|
+
# Rescue from the specified exception.
|
240
|
+
#
|
241
|
+
# rescue_from ActiveRecord::RecordNotFound, :status => 404
|
242
|
+
# rescue_from Exception, :status => 500
|
243
|
+
# rescue_from Exception do
|
244
|
+
# $logger.error error.inspect
|
245
|
+
# [500, {"Content-Type" => "text/plain"}, []]
|
246
|
+
# end
|
247
|
+
#
|
248
|
+
def rescue_from(exception, options = {}, &block)
|
249
|
+
set :rescuers, {:class_name => exception.name, :options => options, :block => block}, :append
|
250
|
+
end
|
251
|
+
|
237
252
|
private
|
238
253
|
def mount_path(path) # :nodoc:
|
239
254
|
Rack::Mount::Utils.normalize_path([option(:prefix), settings[:version], path].join("/"))
|
@@ -249,7 +264,8 @@ module Rack
|
|
249
264
|
:default_format => default_format,
|
250
265
|
:version => option(:version),
|
251
266
|
:prefix => option(:prefix),
|
252
|
-
:url_options => option(:url_options)
|
267
|
+
:url_options => option(:url_options),
|
268
|
+
:rescuers => option(:rescuers, :merge).reverse
|
253
269
|
})
|
254
270
|
|
255
271
|
builder = Rack::Builder.new
|
data/lib/rack/api/version.rb
CHANGED
@@ -0,0 +1,103 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rack::API, "Rescue from exceptions" do
|
4
|
+
class NotFound < StandardError; end
|
5
|
+
|
6
|
+
it "rescues from NotFound exception" do
|
7
|
+
Rack::API.app do
|
8
|
+
rescue_from NotFound, :status => 404
|
9
|
+
|
10
|
+
version :v1 do
|
11
|
+
get("/404") { raise NotFound }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
get "/v1/404"
|
16
|
+
last_response.headers["Content-Type"].should == "text/plain"
|
17
|
+
last_response.body.should == ""
|
18
|
+
last_response.status.should == 404
|
19
|
+
end
|
20
|
+
|
21
|
+
it "rescues from all exceptions" do
|
22
|
+
Rack::API.app do
|
23
|
+
rescue_from Exception
|
24
|
+
|
25
|
+
version :v1 do
|
26
|
+
get("/500") { raise "Oops!" }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
get "/v1/500"
|
31
|
+
last_response.headers["Content-Type"].should == "text/plain"
|
32
|
+
last_response.body.should == ""
|
33
|
+
last_response.status.should == 500
|
34
|
+
end
|
35
|
+
|
36
|
+
it "rescues from exception by using a block" do
|
37
|
+
Rack::API.app do
|
38
|
+
rescue_from Exception do
|
39
|
+
[501, {"Content-Type" => "application/json"}, [{:error => true}.to_json]]
|
40
|
+
end
|
41
|
+
|
42
|
+
version :v1 do
|
43
|
+
get("/501") { raise "Oops!" }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
get "/v1/501"
|
48
|
+
last_response.headers["Content-Type"].should == "application/json"
|
49
|
+
last_response.body.should == {:error => true}.to_json
|
50
|
+
last_response.status.should == 501
|
51
|
+
end
|
52
|
+
|
53
|
+
it "rescues from exception by using inner handler" do
|
54
|
+
Rack::API.app do
|
55
|
+
rescue_from Exception
|
56
|
+
|
57
|
+
version :v1 do
|
58
|
+
rescue_from Exception do
|
59
|
+
[500, {"Content-Type" => "text/plain"}, ["inner handler"]]
|
60
|
+
end
|
61
|
+
|
62
|
+
get("/500") { raise "Oops!" }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
get "/v1/500"
|
67
|
+
last_response.body.should == "inner handler"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "rescues from exception in app's context" do
|
71
|
+
Rack::API.app do
|
72
|
+
rescue_from Exception
|
73
|
+
|
74
|
+
version :v1 do
|
75
|
+
rescue_from Exception do
|
76
|
+
[500, {"Content-Type" => "text/plain"}, [self.class.name]]
|
77
|
+
end
|
78
|
+
|
79
|
+
get("/500") { raise "Oops!" }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
get "/v1/500"
|
84
|
+
last_response.body.should == "Rack::API::App"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "yields the exception object" do
|
88
|
+
Rack::API.app do
|
89
|
+
rescue_from Exception
|
90
|
+
|
91
|
+
version :v1 do
|
92
|
+
rescue_from Exception do |error|
|
93
|
+
[500, {"Content-Type" => "text/plain"}, [error.message]]
|
94
|
+
end
|
95
|
+
|
96
|
+
get("/500") { raise "Oops!" }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
get "/v1/500"
|
101
|
+
last_response.body.should == "Oops!"
|
102
|
+
end
|
103
|
+
end
|
@@ -3,7 +3,7 @@ require "spec_helper"
|
|
3
3
|
describe Rack::API::Runner do
|
4
4
|
specify "sanity check for delegate methods" do
|
5
5
|
# remember to update spec/method_delegation_spec.rb
|
6
|
-
Rack::API::Runner::DELEGATE_METHODS.size.should ==
|
6
|
+
Rack::API::Runner::DELEGATE_METHODS.size.should == 8
|
7
7
|
end
|
8
8
|
|
9
9
|
it "responds to http methods" do
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: rack-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.3.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Nando Vieira
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
13
|
+
date: 2011-06-09 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -110,9 +110,11 @@ files:
|
|
110
110
|
- examples/custom_format.rb
|
111
111
|
- examples/custom_headers.rb
|
112
112
|
- examples/formats.rb
|
113
|
+
- examples/helpers.rb
|
113
114
|
- examples/middleware.rb
|
114
115
|
- examples/multiple_versions.rb
|
115
116
|
- examples/params.rb
|
117
|
+
- examples/rescue_from.rb
|
116
118
|
- examples/simple.rb
|
117
119
|
- lib/rack/api.rb
|
118
120
|
- lib/rack/api/app.rb
|
@@ -138,6 +140,7 @@ files:
|
|
138
140
|
- spec/rack-api/middlewares_spec.rb
|
139
141
|
- spec/rack-api/params_spec.rb
|
140
142
|
- spec/rack-api/paths_spec.rb
|
143
|
+
- spec/rack-api/rescue_from_spec.rb
|
141
144
|
- spec/rack-api/runner_spec.rb
|
142
145
|
- spec/rack-api/settings_spec.rb
|
143
146
|
- spec/rack-api/short_circuit_spec.rb
|
@@ -188,6 +191,7 @@ test_files:
|
|
188
191
|
- spec/rack-api/middlewares_spec.rb
|
189
192
|
- spec/rack-api/params_spec.rb
|
190
193
|
- spec/rack-api/paths_spec.rb
|
194
|
+
- spec/rack-api/rescue_from_spec.rb
|
191
195
|
- spec/rack-api/runner_spec.rb
|
192
196
|
- spec/rack-api/settings_spec.rb
|
193
197
|
- spec/rack-api/short_circuit_spec.rb
|