webmachine 1.4.0 → 1.5.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.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/CHANGELOG.md +7 -0
- data/Gemfile +10 -10
- data/README.md +2 -2
- data/RELEASING.md +21 -0
- data/Rakefile +5 -20
- data/bethtemp +3 -0
- data/documentation/examples.md +6 -3
- data/documentation/how-it-works.md +1 -1
- data/documentation/routes.md +16 -1
- data/lib/webmachine/adapters/reel.rb +1 -0
- data/lib/webmachine/configuration.rb +1 -1
- data/lib/webmachine/decision/flow.rb +11 -11
- data/lib/webmachine/decision/fsm.rb +5 -4
- data/lib/webmachine/decision/helpers.rb +1 -1
- data/lib/webmachine/dispatcher/route.rb +15 -1
- data/lib/webmachine/errors.rb +2 -2
- data/lib/webmachine/events.rb +2 -2
- data/lib/webmachine/headers.rb +1 -1
- data/lib/webmachine/rescueable_exception.rb +62 -0
- data/lib/webmachine/resource/callbacks.rb +5 -5
- data/lib/webmachine/response.rb +3 -5
- data/lib/webmachine/spec/adapter_lint.rb +39 -23
- data/lib/webmachine/streaming/io_encoder.rb +1 -1
- data/lib/webmachine/version.rb +1 -1
- data/spec/spec_helper.rb +8 -0
- data/spec/webmachine/adapters/reel_spec.rb +1 -1
- data/spec/webmachine/decision/conneg_spec.rb +1 -1
- data/spec/webmachine/decision/flow_spec.rb +1 -1
- data/spec/webmachine/decision/fsm_spec.rb +71 -9
- data/spec/webmachine/dispatcher/route_spec.rb +23 -1
- data/spec/webmachine/dispatcher_spec.rb +15 -0
- data/spec/webmachine/rescueable_exception_spec.rb +15 -0
- data/spec/webmachine/response_spec.rb +7 -1
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9309a2f44549ae1c912684fcdc7f60d31404bbf3
|
4
|
+
data.tar.gz: 9531f40a275a2bf5e2bda7ed4816ff2463e4c234
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f5e9419fadcf121f8e0e80ec41417bd5dd9f096933aaf06793dd18d9d6ac6f5e2d028f56e0bc105ff5a87f9b2aa7ebc72e1d61424cc8c88d76e7cb92b9655a0
|
7
|
+
data.tar.gz: d79442bba70911a7b704a26135a2fcadc4dbc1f0a0e12197d1ddbfb055498c54e164e972b03479d7428839ceef15bf32faa070b7ace58fc4b76704bdc5ec7bf8
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
### HEAD
|
2
2
|
|
3
|
+
### 1.5.0 September 8, 2017
|
4
|
+
* Removed Fixnum/Integer deprecation warnings in Ruby 2.4
|
5
|
+
* Fixed multiple cookie setting code
|
6
|
+
* Added support for named captures
|
7
|
+
* Improved logic for determining which errors are 'rescuable' by Webmachine,
|
8
|
+
and which are 'unhandlable'.
|
9
|
+
|
3
10
|
### 1.4.0 March 20, 2015
|
4
11
|
|
5
12
|
* Added RackMapped adapter which allows Webmachine apps to be mounted
|
data/Gemfile
CHANGED
@@ -3,15 +3,15 @@ source 'https://rubygems.org'
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
group :development do
|
6
|
-
gem "yard"
|
7
|
-
gem "rake"
|
6
|
+
gem "yard", "~> 0.9"
|
7
|
+
gem "rake", "~> 12.0"
|
8
8
|
end
|
9
9
|
|
10
10
|
group :test do
|
11
|
-
gem "rspec",
|
12
|
-
gem "rspec-its"
|
13
|
-
gem "rack"
|
14
|
-
gem "rack-test"
|
11
|
+
gem "rspec", "~> 3.0", ">= 3.6.0"
|
12
|
+
gem "rspec-its", "~> 1.2"
|
13
|
+
gem "rack", "~> 2.0"
|
14
|
+
gem "rack-test", "~> 0.7"
|
15
15
|
end
|
16
16
|
|
17
17
|
group :webservers do
|
@@ -21,12 +21,12 @@ group :webservers do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
group :guard do
|
24
|
-
gem 'guard-rspec'
|
24
|
+
gem 'guard-rspec', '~> 4.7'
|
25
25
|
case RbConfig::CONFIG['host_os']
|
26
26
|
when /darwin/
|
27
|
-
gem 'rb-fsevent'
|
27
|
+
gem 'rb-fsevent', '~> 0.10'
|
28
28
|
# gem 'growl_notify'
|
29
|
-
gem 'growl'
|
29
|
+
gem 'growl', '~> 1.0'
|
30
30
|
when /linux/
|
31
31
|
gem 'rb-inotify'
|
32
32
|
gem 'libnotify'
|
@@ -35,7 +35,7 @@ end
|
|
35
35
|
|
36
36
|
group :docs do
|
37
37
|
platform :mri_19, :mri_20 do
|
38
|
-
gem 'redcarpet'
|
38
|
+
gem 'redcarpet', '~> 3.4'
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# webmachine for Ruby [](https://travis-ci.org/webmachine/webmachine-ruby)
|
2
2
|
|
3
3
|
webmachine-ruby is a port of
|
4
4
|
[Webmachine](https://github.com/basho/webmachine), which is written in
|
@@ -163,7 +163,7 @@ the "visual debugger". Learn how to configure it [here][visual-debugger].
|
|
163
163
|
|
164
164
|
## Related libraries
|
165
165
|
|
166
|
-
* [irwebmachine](https://github.com/
|
166
|
+
* [irwebmachine](https://github.com/generalassembly/irwebmachine) - IRB/Pry debugging of Webmachine applications
|
167
167
|
* [webmachine-test](https://github.com/bernd/webmachine-test) - Helpers for testing Webmachine applications
|
168
168
|
* [webmachine-linking](https://github.com/petejohanson/webmachine-linking) - Helpers for linking between Resources, and Web Linking
|
169
169
|
* [webmachine-sprockets](https://github.com/lgierth/webmachine-sprockets) - Integration with Sprockets assets packaging system
|
data/RELEASING.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
1. Open `CHANGELOG.md` and summarize the changes made since the last release (hopefully better than the individual commit messages). The history can be grabbed with a simple git command (assuming the last version was 1.3.0:
|
2
|
+
|
3
|
+
$ git log --pretty=format:' * %s' v1.3.0..HEAD
|
4
|
+
|
5
|
+
2. Edit the version in `lib/webmachine/version.rb` according to semantic versioning rules.
|
6
|
+
3. Commit both files.
|
7
|
+
|
8
|
+
$ git add CHANGELOG.md lib/webmachine/version.rb
|
9
|
+
$ git commit -m "chore(release): version $(ruby -r ./lib/webmachine/version.rb -e "puts Webmachine::VERSION")" && git push
|
10
|
+
|
11
|
+
4. Release the gem.
|
12
|
+
|
13
|
+
$ bundle exec rake release
|
14
|
+
|
15
|
+
5. If this is a new major or minor release, push a new stable branch, otherwise merge the commit into the stable branch (or master, depending on where you made the commit).
|
16
|
+
|
17
|
+
$ git push origin HEAD:1.3-stable
|
18
|
+
# or
|
19
|
+
$ git checkout 1.3-stable; git merge master; git push origin; git checkout master
|
20
|
+
|
21
|
+
6. YOU'RE DONE!
|
data/Rakefile
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require
|
2
|
-
require 'rubygems/package_task'
|
1
|
+
require "bundler/gem_tasks"
|
3
2
|
|
4
3
|
begin
|
5
4
|
require 'yard'
|
@@ -11,26 +10,12 @@ begin
|
|
11
10
|
rescue LoadError
|
12
11
|
end
|
13
12
|
|
14
|
-
|
15
|
-
|
13
|
+
desc "Validate the gemspec file."
|
14
|
+
task :validate_gemspec do
|
15
|
+
Gem::Specification.load("webmachine.gemspec").validate
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
pkg.need_zip = false
|
20
|
-
pkg.need_tar = false
|
21
|
-
end
|
22
|
-
|
23
|
-
task :gem => :gemspec
|
24
|
-
|
25
|
-
desc %{Validate the gemspec file.}
|
26
|
-
task :gemspec do
|
27
|
-
gemspec.validate
|
28
|
-
end
|
29
|
-
|
30
|
-
desc %{Release the gem to RubyGems.org}
|
31
|
-
task :release => :gem do
|
32
|
-
system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
33
|
-
end
|
18
|
+
task :build => :validate_gemspec
|
34
19
|
|
35
20
|
desc "Cleans up white space in source files"
|
36
21
|
task :clean_whitespace do
|
data/bethtemp
ADDED
data/documentation/examples.md
CHANGED
@@ -137,6 +137,8 @@ class OrderResource < Webmachine::Resource
|
|
137
137
|
[["application/json", :from_json]]
|
138
138
|
end
|
139
139
|
|
140
|
+
# Note that returning falsey will NOT result in a 404 for PUT requests.
|
141
|
+
# See note below.
|
140
142
|
def resource_exists?
|
141
143
|
order
|
142
144
|
end
|
@@ -166,8 +168,10 @@ class OrderResource < Webmachine::Resource
|
|
166
168
|
end
|
167
169
|
```
|
168
170
|
|
171
|
+
If you wish to disallow PUT to a non-existent resource, read more [here](https://github.com/webmachine/webmachine-ruby/issues/207#issuecomment-132604379).
|
172
|
+
|
169
173
|
# PATCH
|
170
|
-
* Webmachine does not currently support PATCH requests. See https://github.com/
|
174
|
+
* Webmachine does not currently support PATCH requests. See https://github.com/webmachine/webmachine-ruby/issues/109 for more information and https://github.com/bethesque/pact_broker/blob/2918814e70bbda14df68598a6a41502a5eac4308/lib/pact_broker/api/resources/pacticipant.rb for a dirty hack to make it work if you need to.
|
171
175
|
|
172
176
|
# DELETE
|
173
177
|
* Override `resource_exists?` and `delete_resource`
|
@@ -208,8 +212,7 @@ Thanks to [oestrich][oestrich] for putting together the original example. You ca
|
|
208
212
|
[oestrich]: https://github.com/oestrich
|
209
213
|
[source]: https://gist.github.com/oestrich/3638605
|
210
214
|
|
211
|
-
<a name="callback-order">
|
215
|
+
<a name="callback-order"></a>
|
212
216
|
## What order are the callbacks invoked in?
|
213
|
-
</a>
|
214
217
|
|
215
218
|
This question is actually irrelevant if you write your code in a "stateless" way using lazy initialization as the examples do above. As much as possible, think about exposing "facts" about your resource, not writing procedural code that needs to be called in a certain order. See [How it works](/documentation/how-it-works.md) for more information on how the Webmachine state machine works.
|
@@ -71,6 +71,6 @@ end
|
|
71
71
|
* A collection resource (eg. /orders) should be implemented as a separate class to a single object resource (eg. /orders/1), as the routes represent different underlying objects with different "facts". For example, the orders _collection_ resource probably always exists (but may be empty), however the order with ID 1 may or may not exist.
|
72
72
|
|
73
73
|
[callbacks]: https://github.com/seancribbs/webmachine-ruby/blob/master/lib/webmachine/resource/callbacks.rb
|
74
|
-
[diagram]:
|
74
|
+
[diagram]: https://webmachine.github.io/images/http-headers-status-v3.png
|
75
75
|
[flow]: https://github.com/seancribbs/webmachine-ruby/blob/master/lib/webmachine/decision/flow.rb
|
76
76
|
[examples]: /documentation/examples.md
|
data/documentation/routes.md
CHANGED
@@ -20,6 +20,21 @@ App = Webmachine::Application.new do |app|
|
|
20
20
|
# but will not provide any path_info
|
21
21
|
add ["orders", :*], OrderResource
|
22
22
|
|
23
|
+
# Will map to any path that matches the given components and regular expression
|
24
|
+
# Any capture groups specified in the regex will be made available in
|
25
|
+
# request.path_info[:captures. In this case, you would get one or two
|
26
|
+
# values in :captures depending on whether your request looked like:
|
27
|
+
# /orders/1/cancel
|
28
|
+
# or
|
29
|
+
# /orders/1/cancel.json
|
30
|
+
add ["orders", :id, /([^.]*)\.?(.*)?/], OrderResource
|
31
|
+
|
32
|
+
# You can even use named captures with regular expressions. This will
|
33
|
+
# automatically put the captures into path_info. In the below example,
|
34
|
+
# you would get :id from the symbol, along with :action and :format
|
35
|
+
# from the regex. :format in this case would be optional.
|
36
|
+
add ["orders", :id, /(?<action>)[^.]*)\.?(?<format>.*)?/], OrderResource
|
37
|
+
|
23
38
|
# will map to any path
|
24
39
|
add [:*], DefaultResource
|
25
40
|
end
|
@@ -94,4 +109,4 @@ end
|
|
94
109
|
request.path_info[:foo]
|
95
110
|
=> "bar"
|
96
111
|
|
97
|
-
```
|
112
|
+
```
|
@@ -5,7 +5,7 @@ module Webmachine
|
|
5
5
|
# defaults will be filled in when {Webmachine::run} is called.
|
6
6
|
# @attr [String] ip the interface to bind to, defaults to "0.0.0.0"
|
7
7
|
# (all interfaces)
|
8
|
-
# @attr [
|
8
|
+
# @attr [Integer] port the port to bind to, defaults to 8080
|
9
9
|
# @attr [Symbol] adapter the adapter to use, defaults to :WEBrick
|
10
10
|
# @attr [Hash] adapter_options adapter-specific options, defaults to {}
|
11
11
|
Configuration = Struct.new(:ip, :port, :adapter, :adapter_options)
|
@@ -35,7 +35,7 @@ module Webmachine
|
|
35
35
|
# Handles standard decisions where halting is allowed
|
36
36
|
def decision_test(test, iftrue, iffalse)
|
37
37
|
case test
|
38
|
-
when
|
38
|
+
when Integer # Allows callbacks to "halt" with a given response code
|
39
39
|
test
|
40
40
|
when Falsey
|
41
41
|
iffalse
|
@@ -77,7 +77,7 @@ module Webmachine
|
|
77
77
|
# Content-MD5 valid?
|
78
78
|
def b9a
|
79
79
|
case valid = resource.validate_content_checksum
|
80
|
-
when
|
80
|
+
when Integer
|
81
81
|
valid
|
82
82
|
when true
|
83
83
|
:b9b
|
@@ -105,7 +105,7 @@ module Webmachine
|
|
105
105
|
case result
|
106
106
|
when true
|
107
107
|
:b7
|
108
|
-
when
|
108
|
+
when Integer
|
109
109
|
result
|
110
110
|
when String
|
111
111
|
response.headers['WWW-Authenticate'] = result
|
@@ -280,7 +280,7 @@ module Webmachine
|
|
280
280
|
when String, URI
|
281
281
|
response.headers[LOCATION] = uri.to_s
|
282
282
|
301
|
283
|
-
when
|
283
|
+
when Integer
|
284
284
|
uri
|
285
285
|
else
|
286
286
|
:p3
|
@@ -313,7 +313,7 @@ module Webmachine
|
|
313
313
|
when String, URI
|
314
314
|
response.headers[LOCATION] = uri.to_s
|
315
315
|
301
|
316
|
-
when
|
316
|
+
when Integer
|
317
317
|
uri
|
318
318
|
else
|
319
319
|
:l5
|
@@ -342,7 +342,7 @@ module Webmachine
|
|
342
342
|
when String, URI
|
343
343
|
response.headers[LOCATION] = uri.to_s
|
344
344
|
307
|
345
|
-
when
|
345
|
+
when Integer
|
346
346
|
uri
|
347
347
|
else
|
348
348
|
:m5
|
@@ -422,13 +422,13 @@ module Webmachine
|
|
422
422
|
request.disp_path = new_uri.path
|
423
423
|
response.headers[LOCATION] = new_uri.to_s
|
424
424
|
result = accept_helper
|
425
|
-
return result if
|
425
|
+
return result if Integer === result
|
426
426
|
end
|
427
427
|
else
|
428
428
|
case result = resource.process_post
|
429
429
|
when true
|
430
430
|
encode_body_if_set
|
431
|
-
when
|
431
|
+
when Integer
|
432
432
|
return result
|
433
433
|
else
|
434
434
|
raise InvalidResource, t('process_post_invalid', :result => result.inspect)
|
@@ -456,7 +456,7 @@ module Webmachine
|
|
456
456
|
409
|
457
457
|
else
|
458
458
|
res = accept_helper
|
459
|
-
(
|
459
|
+
(Integer === res) ? res : :p11
|
460
460
|
end
|
461
461
|
end
|
462
462
|
|
@@ -473,7 +473,7 @@ module Webmachine
|
|
473
473
|
content_type = metadata[CONTENT_TYPE]
|
474
474
|
handler = resource.content_types_provided.find {|ct, _| content_type.type_matches?(MediaType.parse(ct)) }.last
|
475
475
|
result = resource.send(handler)
|
476
|
-
if
|
476
|
+
if Integer === result
|
477
477
|
result
|
478
478
|
else
|
479
479
|
response.body = result
|
@@ -501,7 +501,7 @@ module Webmachine
|
|
501
501
|
409
|
502
502
|
else
|
503
503
|
res = accept_helper
|
504
|
-
(
|
504
|
+
(Integer === res) ? res : :p11
|
505
505
|
end
|
506
506
|
end
|
507
507
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'webmachine/trace'
|
3
3
|
require 'webmachine/translation'
|
4
4
|
require 'webmachine/constants'
|
5
|
+
require 'webmachine/rescueable_exception'
|
5
6
|
|
6
7
|
module Webmachine
|
7
8
|
module Decision
|
@@ -29,7 +30,7 @@ module Webmachine
|
|
29
30
|
trace_decision(state)
|
30
31
|
result = handle_exceptions { send(state) }
|
31
32
|
case result
|
32
|
-
when
|
33
|
+
when Integer # Response code
|
33
34
|
respond(result)
|
34
35
|
break
|
35
36
|
when Symbol # Next state
|
@@ -48,12 +49,12 @@ module Webmachine
|
|
48
49
|
|
49
50
|
def handle_exceptions
|
50
51
|
yield
|
52
|
+
rescue Webmachine::RescuableException => e
|
53
|
+
resource.handle_exception(e)
|
54
|
+
500
|
51
55
|
rescue MalformedRequest => e
|
52
56
|
Webmachine.render_error(400, request, response, :message => e.message)
|
53
57
|
400
|
54
|
-
rescue => e
|
55
|
-
resource.handle_exception(e)
|
56
|
-
500
|
57
58
|
end
|
58
59
|
|
59
60
|
def respond(code, headers={})
|
@@ -95,7 +95,7 @@ module Webmachine
|
|
95
95
|
# is a String or IO with known size.
|
96
96
|
def body_is_fixed_length?
|
97
97
|
response.body.respond_to?(:bytesize) &&
|
98
|
-
|
98
|
+
Integer === response.body.bytesize
|
99
99
|
end
|
100
100
|
end # module Helpers
|
101
101
|
end # module Decision
|
@@ -103,7 +103,7 @@ module Webmachine
|
|
103
103
|
# accumulating variable bindings.
|
104
104
|
# @param [Array<String>] tokens the list of path segments
|
105
105
|
# @param [Hash] bindings where path bindings will be stored
|
106
|
-
# @return [
|
106
|
+
# @return [Integer, Array<Integer, Array>, false] either the depth
|
107
107
|
# that the path matched at, the depth and tokens matched by
|
108
108
|
# {MATCH_ALL}, or false if it didn't match.
|
109
109
|
def bind(tokens, bindings)
|
@@ -119,6 +119,20 @@ module Webmachine
|
|
119
119
|
return [depth, tokens]
|
120
120
|
when tokens.empty?
|
121
121
|
return false
|
122
|
+
when Regexp === spec.first
|
123
|
+
matches = spec.first.match URI.decode(tokens.first)
|
124
|
+
if matches
|
125
|
+
if spec.first.named_captures.empty?
|
126
|
+
bindings[:captures] = (bindings[:captures] || []) + matches.captures
|
127
|
+
else
|
128
|
+
spec.first.named_captures.reduce(bindings) do |bindings, (name, idxs)|
|
129
|
+
bindings[name.to_sym] = matches.captures[idxs.first-1]
|
130
|
+
bindings
|
131
|
+
end
|
132
|
+
end
|
133
|
+
else
|
134
|
+
return false
|
135
|
+
end
|
122
136
|
when Symbol === spec.first
|
123
137
|
bindings[spec.first] = URI.decode(tokens.first)
|
124
138
|
when spec.first == tokens.first
|
data/lib/webmachine/errors.rb
CHANGED
@@ -9,7 +9,7 @@ module Webmachine
|
|
9
9
|
|
10
10
|
# Renders a standard error message body for the response. The
|
11
11
|
# standard messages are defined in localization files.
|
12
|
-
# @param [
|
12
|
+
# @param [Integer] code the response status code
|
13
13
|
# @param [Request] req the request object
|
14
14
|
# @param [Response] req the response object
|
15
15
|
# @param [Hash] options keys to override the defaults when rendering
|
@@ -39,6 +39,6 @@ module Webmachine
|
|
39
39
|
|
40
40
|
# Raised when the client has submitted an invalid request, e.g. in
|
41
41
|
# the case where a request header is improperly formed. Raising this
|
42
|
-
#
|
42
|
+
# error will result in a 400 response.
|
43
43
|
class MalformedRequest < Error; end
|
44
44
|
end # module Webmachine
|
data/lib/webmachine/events.rb
CHANGED
@@ -55,9 +55,9 @@ module Webmachine
|
|
55
55
|
# and publish it. Notice that events get sent even if an error occurs
|
56
56
|
# in the passed-in block.
|
57
57
|
#
|
58
|
-
# If an
|
58
|
+
# If an error happens during an instrumentation the payload will
|
59
59
|
# have a key `:exception` with an array of two elements as value:
|
60
|
-
# a string with the name of the
|
60
|
+
# a string with the name of the error class, and the error
|
61
61
|
# message. (when using the default
|
62
62
|
# [AS::Notifications](http://rubydoc.info/gems/as-notifications/AS/Notifications)
|
63
63
|
# backend)
|
data/lib/webmachine/headers.rb
CHANGED
@@ -48,7 +48,7 @@ module Webmachine
|
|
48
48
|
|
49
49
|
# Returns the value for the given key. If the key can't be found,
|
50
50
|
# there are several options:
|
51
|
-
# With no other arguments, it will raise a KeyError
|
51
|
+
# With no other arguments, it will raise a KeyError error;
|
52
52
|
# if default is given, then that will be returned;
|
53
53
|
# if the optional code block is specified, then that will be run and its
|
54
54
|
# result returned.
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Webmachine::RescuableException
|
2
|
+
require_relative 'errors'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
UNRESCUABLE_DEFAULTS = [
|
6
|
+
Webmachine::MalformedRequest,
|
7
|
+
NoMemoryError, SystemExit, SignalException
|
8
|
+
].freeze
|
9
|
+
|
10
|
+
UNRESCUABLE = Set.new UNRESCUABLE_DEFAULTS.dup
|
11
|
+
private_constant :UNRESCUABLE
|
12
|
+
|
13
|
+
def self.===(e)
|
14
|
+
case e
|
15
|
+
when *UNRESCUABLE then false
|
16
|
+
else true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Remove modifications to Webmachine::RescuableException.
|
22
|
+
# Restores default list of unrescue-able exceptions.
|
23
|
+
#
|
24
|
+
# @return [nil]
|
25
|
+
#
|
26
|
+
def self.default!
|
27
|
+
UNRESCUABLE.replace Set.new(UNRESCUABLE_DEFAULTS.dup)
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# @return [Array<Exception>]
|
33
|
+
# Returns an Array of exceptions that will not be
|
34
|
+
# rescued by {Webmachine::Resource#handle_exception}.
|
35
|
+
#
|
36
|
+
def self.UNRESCUABLEs
|
37
|
+
UNRESCUABLE.to_a
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Add a variable number of exceptions that should be rescued by
|
42
|
+
# {Webmachine::Resource#handle_exception}. See {UNRESCUABLE_DEFAULTS}
|
43
|
+
# for a list of exceptions that are not caught by default.
|
44
|
+
#
|
45
|
+
# @param (see #remove)
|
46
|
+
#
|
47
|
+
def self.add(*exceptions)
|
48
|
+
exceptions.each{|e| UNRESCUABLE.delete(e)}
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Remove a variable number of exceptions from being rescued by
|
53
|
+
# {Webmachine::Resource#handle_exception}. See {UNRESCUABLE_DEFAULTS}
|
54
|
+
# for a list of exceptions that are not caught by default.
|
55
|
+
#
|
56
|
+
# @param [Exception] *exceptions
|
57
|
+
# A subclass of Exception.
|
58
|
+
#
|
59
|
+
def self.remove(*exceptions)
|
60
|
+
exceptions.each{|e| UNRESCUABLE.add(e)}
|
61
|
+
end
|
62
|
+
end
|
@@ -103,7 +103,7 @@ module Webmachine
|
|
103
103
|
# If the entity length on PUT or POST is invalid, this should
|
104
104
|
# return false, which will result in a '413 Request Entity Too
|
105
105
|
# Large' response. Defaults to true.
|
106
|
-
# @param [
|
106
|
+
# @param [Integer] length the size of the request body (entity)
|
107
107
|
# @return [true,false] Whether the body is a valid length (not too
|
108
108
|
# large)
|
109
109
|
# @api callback
|
@@ -192,7 +192,7 @@ module Webmachine
|
|
192
192
|
|
193
193
|
# If post_is_create? returns false, then this will be called to
|
194
194
|
# process any POST request. If it succeeds, it should return true.
|
195
|
-
# @return [true,false,
|
195
|
+
# @return [true,false,Integer] Whether the POST was successfully
|
196
196
|
# processed, or an alternate response code
|
197
197
|
# @api callback
|
198
198
|
def process_post
|
@@ -363,11 +363,11 @@ module Webmachine
|
|
363
363
|
def finish_request; end
|
364
364
|
|
365
365
|
#
|
366
|
-
# This method is called when an
|
366
|
+
# This method is called when an error is raised within a subclass of
|
367
367
|
# {Webmachine::Resource}.
|
368
368
|
#
|
369
|
-
# @param [
|
370
|
-
# The
|
369
|
+
# @param [StandardError] e
|
370
|
+
# The error.
|
371
371
|
#
|
372
372
|
# @return [void]
|
373
373
|
#
|
data/lib/webmachine/response.rb
CHANGED
@@ -4,7 +4,7 @@ module Webmachine
|
|
4
4
|
# @return [HeaderHash] Response headers that will be sent to the client
|
5
5
|
attr_reader :headers
|
6
6
|
|
7
|
-
# @return [
|
7
|
+
# @return [Integer] The HTTP status code of the response
|
8
8
|
attr_accessor :code
|
9
9
|
|
10
10
|
# @return [String, #each] The response body
|
@@ -48,11 +48,9 @@ module Webmachine
|
|
48
48
|
cookie = Webmachine::Cookie.new(name, value, attributes).to_s
|
49
49
|
case headers['Set-Cookie']
|
50
50
|
when nil
|
51
|
-
headers['Set-Cookie'] = cookie
|
52
|
-
when String
|
53
|
-
headers['Set-Cookie'] = [headers['Set-Cookie'], cookie]
|
51
|
+
headers['Set-Cookie'] = [cookie]
|
54
52
|
when Array
|
55
|
-
headers['Set-Cookie']
|
53
|
+
headers['Set-Cookie'] << cookie
|
56
54
|
end
|
57
55
|
end
|
58
56
|
|
@@ -1,28 +1,42 @@
|
|
1
1
|
require "webmachine/spec/test_resource"
|
2
2
|
require "net/http"
|
3
3
|
|
4
|
+
ADDRESS = "127.0.0.1"
|
5
|
+
|
4
6
|
shared_examples_for :adapter_lint do
|
5
|
-
|
7
|
+
attr_reader :client
|
8
|
+
|
9
|
+
class TestApplicationNotResponsive < Timeout::Error; end
|
6
10
|
|
7
|
-
|
8
|
-
|
11
|
+
def find_free_port
|
12
|
+
temp_server = TCPServer.new(ADDRESS, 0)
|
13
|
+
port = temp_server.addr[1]
|
14
|
+
temp_server.close # only frees Ruby resource, socket is in TIME_WAIT at OS level
|
15
|
+
# so we can't have our adapter use it too quickly
|
9
16
|
|
10
|
-
|
11
|
-
|
12
|
-
|
17
|
+
sleep(0.1) # 'Wait' for temp_server to *really* close, not just TIME_WAIT
|
18
|
+
port
|
19
|
+
end
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
|
21
|
+
def create_test_application(port)
|
22
|
+
Webmachine::Application.new.tap do |application|
|
23
|
+
application.dispatcher.add_route ["test"], Test::Resource
|
24
|
+
|
25
|
+
application.configure do |c|
|
26
|
+
c.ip = ADDRESS
|
27
|
+
c.port = port
|
28
|
+
end
|
17
29
|
end
|
30
|
+
end
|
18
31
|
|
19
|
-
|
32
|
+
def run_application(adapter_class, application)
|
33
|
+
adapter = adapter_class.new(application)
|
34
|
+
Thread.abort_on_exception = true
|
35
|
+
Thread.new { adapter.run }
|
20
36
|
end
|
21
37
|
|
22
|
-
|
23
|
-
|
24
|
-
# Wait until the server is responsive
|
25
|
-
timeout(5) do
|
38
|
+
def wait_until_server_responds_to(client)
|
39
|
+
Timeout.timeout(5, TestApplicationNotResponsive) do
|
26
40
|
begin
|
27
41
|
client.start
|
28
42
|
rescue Errno::ECONNREFUSED
|
@@ -30,19 +44,21 @@ shared_examples_for :adapter_lint do
|
|
30
44
|
retry
|
31
45
|
end
|
32
46
|
end
|
33
|
-
client
|
34
47
|
end
|
35
48
|
|
36
|
-
before do
|
37
|
-
@
|
49
|
+
before(:all) do
|
50
|
+
@port = find_free_port
|
51
|
+
application = create_test_application(@port)
|
38
52
|
|
39
|
-
|
40
|
-
@server_thread =
|
41
|
-
|
53
|
+
adapter_class = described_class
|
54
|
+
@server_thread = run_application(adapter_class, application)
|
55
|
+
|
56
|
+
@client = Net::HTTP.new(application.configuration.ip, @port)
|
57
|
+
wait_until_server_responds_to(client)
|
42
58
|
end
|
43
59
|
|
44
|
-
after do
|
45
|
-
client.finish
|
60
|
+
after(:all) do
|
61
|
+
@client.finish
|
46
62
|
@server_thread.kill
|
47
63
|
end
|
48
64
|
|
@@ -50,7 +66,7 @@ shared_examples_for :adapter_lint do
|
|
50
66
|
request = Net::HTTP::Get.new("/test")
|
51
67
|
request["Accept"] = "test/response.request_uri"
|
52
68
|
response = client.request(request)
|
53
|
-
expect(response.body).to eq("http://#{
|
69
|
+
expect(response.body).to eq("http://#{ADDRESS}:#{@port}/test")
|
54
70
|
end
|
55
71
|
|
56
72
|
# context do
|
@@ -39,7 +39,7 @@ module Webmachine
|
|
39
39
|
# Returns the length of the IO stream, if known. Returns nil if
|
40
40
|
# the stream uses an encoder or charsetter that might modify the
|
41
41
|
# length of the stream, or the stream size is unknown.
|
42
|
-
# @return [
|
42
|
+
# @return [Integer] the size, in bytes, of the underlying IO, or
|
43
43
|
# nil if unsupported
|
44
44
|
def size
|
45
45
|
if is_unencoded?
|
data/lib/webmachine/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -18,6 +18,14 @@ RSpec.configure do |config|
|
|
18
18
|
config.order = :random
|
19
19
|
end
|
20
20
|
|
21
|
+
config.before :each do
|
22
|
+
Webmachine::RescuableException.remove(RSpec::Mocks::MockExpectationError)
|
23
|
+
end
|
24
|
+
|
25
|
+
config.after :each do
|
26
|
+
Webmachine::RescuableException.default!
|
27
|
+
end
|
28
|
+
|
21
29
|
config.before(:suite) do
|
22
30
|
options = {
|
23
31
|
:Logger => NullLogger.new(STDERR),
|
@@ -56,7 +56,7 @@ describe Webmachine::Adapters::Reel do
|
|
56
56
|
def reel_server(adptr = adapter)
|
57
57
|
thread = Thread.new { adptr.run }
|
58
58
|
begin
|
59
|
-
timeout(5) do
|
59
|
+
Timeout.timeout(5) do
|
60
60
|
begin
|
61
61
|
sock = TCPSocket.new(adptr.application.configuration.ip, adptr.application.configuration.port)
|
62
62
|
begin
|
@@ -41,7 +41,7 @@ describe Webmachine::Decision::Conneg do
|
|
41
41
|
|
42
42
|
end
|
43
43
|
|
44
|
-
it "should raise an
|
44
|
+
it "should raise an error when a media-type is improperly formatted" do
|
45
45
|
expect {
|
46
46
|
subject.choose_media_type(["text/html", "application/xml"],
|
47
47
|
"bah;")
|
@@ -5,15 +5,58 @@ describe Webmachine::Decision::FSM do
|
|
5
5
|
|
6
6
|
subject { described_class.new(resource, request, response) }
|
7
7
|
|
8
|
+
let(:run_with_exception) do
|
9
|
+
begin
|
10
|
+
subject.run
|
11
|
+
rescue Exception
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
8
15
|
describe 'handling of exceptions from decision methods' do
|
9
|
-
let(:
|
16
|
+
let(:UNRESCUABLE_exceptions) do
|
17
|
+
Webmachine::RescuableException::UNRESCUABLE
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "rescueable exceptions" do
|
21
|
+
it 'does rescue Exception' do
|
22
|
+
allow(subject).to receive(Webmachine::Decision::Flow::START) { raise(Exception) }
|
23
|
+
expect(resource).to receive(:handle_exception).with instance_of(Exception)
|
24
|
+
expect { subject.run }.to_not raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'does rescue a failed require' do
|
28
|
+
allow(subject).to receive(Webmachine::Decision::Flow::START) { require 'laterequire' }
|
29
|
+
expect(resource).to receive(:handle_exception).with instance_of(LoadError)
|
30
|
+
expect { subject.run }.to_not raise_error
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "UNRESCUABLE exceptions" do
|
35
|
+
shared_examples "UNRESCUABLE" do |e|
|
36
|
+
specify "#{e} is not rescued" do
|
37
|
+
allow(subject).to receive(Webmachine::Decision::Flow::START) {raise(e)}
|
38
|
+
expect(resource).to_not receive(:handle_exception).with instance_of(e)
|
39
|
+
expect { subject.run }.to raise_error(e)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
eary = Webmachine::RescuableException::UNRESCUABLE_DEFAULTS - [
|
43
|
+
Webmachine::MalformedRequest, # Webmachine rescues by default, so it won't re-raise.
|
44
|
+
SignalException # Requires raise in form 'raise SignalException, "SIGSOMESIGNAL"'.
|
45
|
+
# Haven't found a good no-op signal to use here.
|
46
|
+
]
|
47
|
+
eary.each{|e| include_examples "UNRESCUABLE", e}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'handling of errors from decision methods' do
|
52
|
+
let(:error) { RuntimeError.new }
|
10
53
|
|
11
54
|
before do
|
12
|
-
allow(subject).to receive(Webmachine::Decision::Flow::START) { raise
|
55
|
+
allow(subject).to receive(Webmachine::Decision::Flow::START) { raise error }
|
13
56
|
end
|
14
57
|
|
15
58
|
it 'calls resource.handle_exception' do
|
16
|
-
expect(resource).to receive(:handle_exception).with(
|
59
|
+
expect(resource).to receive(:handle_exception).with(error)
|
17
60
|
subject.run
|
18
61
|
end
|
19
62
|
|
@@ -23,12 +66,12 @@ describe Webmachine::Decision::FSM do
|
|
23
66
|
end
|
24
67
|
end
|
25
68
|
|
26
|
-
describe 'handling of
|
27
|
-
let(:
|
69
|
+
describe 'handling of errors from resource.handle_exception' do
|
70
|
+
let(:error) { RuntimeError.new('an error message') }
|
28
71
|
|
29
72
|
before do
|
30
73
|
allow(subject).to receive(Webmachine::Decision::Flow::START) { raise }
|
31
|
-
allow(resource).to receive(:handle_exception) { raise
|
74
|
+
allow(resource).to receive(:handle_exception) { raise error }
|
32
75
|
end
|
33
76
|
|
34
77
|
it 'does not call resource.handle_exception again' do
|
@@ -44,20 +87,39 @@ describe Webmachine::Decision::FSM do
|
|
44
87
|
it 'renders an error' do
|
45
88
|
expect(Webmachine).
|
46
89
|
to receive(:render_error).
|
47
|
-
with(500, request, response, { :message =>
|
90
|
+
with(500, request, response, { :message => error.message })
|
48
91
|
subject.run
|
49
92
|
end
|
50
93
|
end
|
51
94
|
|
52
95
|
describe 'handling of exceptions from resource.finish_request' do
|
53
|
-
let(:exception) {
|
96
|
+
let(:exception) { Class.new(Exception).new }
|
54
97
|
|
55
98
|
before do
|
99
|
+
Webmachine::RescuableException.remove(exception)
|
56
100
|
allow(resource).to receive(:finish_request) { raise exception }
|
57
101
|
end
|
58
102
|
|
103
|
+
it 'does not call resource.handle_exception' do
|
104
|
+
expect(resource).to_not receive(:handle_exception)
|
105
|
+
run_with_exception
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'does not call resource.finish_request again' do
|
109
|
+
expect(resource).to_not receive(:finish_request).once { raise }
|
110
|
+
run_with_exception
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe 'handling of errors from resource.finish_request' do
|
115
|
+
let(:error) { RuntimeError.new }
|
116
|
+
|
117
|
+
before do
|
118
|
+
allow(resource).to receive(:finish_request) { raise error }
|
119
|
+
end
|
120
|
+
|
59
121
|
it 'calls resource.handle_exception' do
|
60
|
-
expect(resource).to receive(:handle_exception).with(
|
122
|
+
expect(resource).to receive(:handle_exception).with(error)
|
61
123
|
subject.run
|
62
124
|
end
|
63
125
|
|
@@ -180,7 +180,6 @@ describe Webmachine::Dispatcher::Route do
|
|
180
180
|
end
|
181
181
|
end
|
182
182
|
end
|
183
|
-
|
184
183
|
context "on a deep path" do
|
185
184
|
subject { described_class.new(%w{foo bar baz}, resource) }
|
186
185
|
let(:uri) { URI.parse("http://localhost:8080/foo/bar/baz") }
|
@@ -205,6 +204,29 @@ describe Webmachine::Dispatcher::Route do
|
|
205
204
|
expect(request.path_info).to eq({:id => "bar"})
|
206
205
|
end
|
207
206
|
end
|
207
|
+
context "with regex" do
|
208
|
+
subject { described_class.new([/foo/, /(.*)/, 'baz'], resource) }
|
209
|
+
|
210
|
+
it "should assign the captures path variables" do
|
211
|
+
expect(request.path_info).to eq({:captures => ["bar"]})
|
212
|
+
end
|
213
|
+
end
|
214
|
+
context "with multi-capture regex" do
|
215
|
+
subject { described_class.new([/foo/, /(.*)/, /baz\.(.*)/], resource) }
|
216
|
+
let(:uri) { URI.parse("http://localhost:8080/foo/bar/baz.json") }
|
217
|
+
|
218
|
+
it "should assign the captures path variables" do
|
219
|
+
expect(request.path_info).to eq({:captures => ["bar", "json"]})
|
220
|
+
end
|
221
|
+
end
|
222
|
+
context "with named capture regex" do
|
223
|
+
subject { described_class.new(['foo', :bar, /(?<baz>[^.]+)\.(?<format>.*)/], resource) }
|
224
|
+
let(:uri) { URI.parse("http://localhost:8080/foo/bar/baz.json") }
|
225
|
+
|
226
|
+
it "should assign the captures path variables" do
|
227
|
+
expect(request.path_info).to eq({bar: 'bar', baz: 'baz', format: "json"})
|
228
|
+
end
|
229
|
+
end
|
208
230
|
|
209
231
|
context "with a splat" do
|
210
232
|
subject { described_class.new(['foo', :*], resource) }
|
@@ -3,6 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Webmachine::Dispatcher do
|
4
4
|
let(:dispatcher) { Webmachine.application.dispatcher }
|
5
5
|
let(:request) { Webmachine::Request.new("GET", URI.parse("http://localhost:8080/"), Webmachine::Headers["accept" => "*/*"], "") }
|
6
|
+
let(:request2) { Webmachine::Request.new("GET", URI.parse("http://localhost:8080/hello/bob.html"), Webmachine::Headers["accept" => "*/*"], "") }
|
6
7
|
let(:response) { Webmachine::Response.new }
|
7
8
|
let(:resource) do
|
8
9
|
Class.new(Webmachine::Resource) do
|
@@ -14,6 +15,14 @@ describe Webmachine::Dispatcher do
|
|
14
15
|
def to_html; "goodbye, cruel world"; end
|
15
16
|
end
|
16
17
|
end
|
18
|
+
let(:resource3) do
|
19
|
+
Class.new(Webmachine::Resource) do
|
20
|
+
def to_html
|
21
|
+
name, format = request.path_info[:captures]
|
22
|
+
"Hello #{name} with #{format}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
17
26
|
let(:fsm){ double }
|
18
27
|
|
19
28
|
before { dispatcher.reset }
|
@@ -44,6 +53,12 @@ describe Webmachine::Dispatcher do
|
|
44
53
|
expect(fsm).to receive(:run)
|
45
54
|
dispatcher.dispatch(request, response)
|
46
55
|
end
|
56
|
+
it "should handle regex path segments in route definition" do
|
57
|
+
dispatcher.add_route ["hello", /(.*)\.(.*)/], resource3
|
58
|
+
expect(Webmachine::Decision::FSM).to receive(:new).with(instance_of(resource3), request2, response).and_return(fsm)
|
59
|
+
expect(fsm).to receive(:run)
|
60
|
+
dispatcher.dispatch(request2, response)
|
61
|
+
end
|
47
62
|
|
48
63
|
it "should apply route to request before creating the resource" do
|
49
64
|
route = dispatcher.add_route [:*], resource
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
RSpec.describe Webmachine::RescuableException do
|
3
|
+
before { described_class.default! }
|
4
|
+
|
5
|
+
describe ".UNRESCUABLEs" do
|
6
|
+
specify "returns an array of UNRESCUABLE exceptions" do
|
7
|
+
expect(described_class.UNRESCUABLEs).to eq(described_class::UNRESCUABLE_DEFAULTS)
|
8
|
+
end
|
9
|
+
|
10
|
+
specify "returns an array of UNRESCUABLE exceptions, with custom exceptions added" do
|
11
|
+
described_class.remove(Exception)
|
12
|
+
expect(described_class.UNRESCUABLEs).to eq(described_class::UNRESCUABLE_DEFAULTS.dup.concat([Exception]))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -33,12 +33,18 @@ describe Webmachine::Response do
|
|
33
33
|
describe "setting multiple cookies" do
|
34
34
|
let(:cookie2) { "rodeo" }
|
35
35
|
let(:cookie2_value) { "clown" }
|
36
|
-
|
36
|
+
let(:cookie3) {"color"}
|
37
|
+
let(:cookie3_value) {"blue"}
|
38
|
+
before(:each) do
|
39
|
+
subject.set_cookie(cookie2, cookie2_value)
|
40
|
+
subject.set_cookie(cookie3, cookie3_value)
|
41
|
+
end
|
37
42
|
|
38
43
|
it "should have a proper Set-Cookie header" do
|
39
44
|
expect(subject.headers["Set-Cookie"]).to be_a Array
|
40
45
|
expect(subject.headers["Set-Cookie"]).to include "rodeo=clown"
|
41
46
|
expect(subject.headers["Set-Cookie"]).to include "monster=mash"
|
47
|
+
expect(subject.headers["Set-Cookie"]).to include "color=blue"
|
42
48
|
end
|
43
49
|
end
|
44
50
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webmachine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Cribbs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -68,7 +68,9 @@ files:
|
|
68
68
|
- Guardfile
|
69
69
|
- LICENSE
|
70
70
|
- README.md
|
71
|
+
- RELEASING.md
|
71
72
|
- Rakefile
|
73
|
+
- bethtemp
|
72
74
|
- documentation/adapters.md
|
73
75
|
- documentation/authentication-and-authorization.md
|
74
76
|
- documentation/configurator.md
|
@@ -115,6 +117,7 @@ files:
|
|
115
117
|
- lib/webmachine/media_type.rb
|
116
118
|
- lib/webmachine/quoted_string.rb
|
117
119
|
- lib/webmachine/request.rb
|
120
|
+
- lib/webmachine/rescueable_exception.rb
|
118
121
|
- lib/webmachine/resource.rb
|
119
122
|
- lib/webmachine/resource/authentication.rb
|
120
123
|
- lib/webmachine/resource/callbacks.rb
|
@@ -145,6 +148,7 @@ files:
|
|
145
148
|
- lib/webmachine/translation.rb
|
146
149
|
- lib/webmachine/version.rb
|
147
150
|
- memory_test.rb
|
151
|
+
- pkg/webmachine-1.5.0.gem
|
148
152
|
- spec/spec_helper.rb
|
149
153
|
- spec/webmachine/adapter_spec.rb
|
150
154
|
- spec/webmachine/adapters/httpkit_spec.rb
|
@@ -169,6 +173,7 @@ files:
|
|
169
173
|
- spec/webmachine/headers_spec.rb
|
170
174
|
- spec/webmachine/media_type_spec.rb
|
171
175
|
- spec/webmachine/request_spec.rb
|
176
|
+
- spec/webmachine/rescueable_exception_spec.rb
|
172
177
|
- spec/webmachine/resource/authentication_spec.rb
|
173
178
|
- spec/webmachine/response_spec.rb
|
174
179
|
- spec/webmachine/trace/fsm_spec.rb
|
@@ -196,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
201
|
version: '0'
|
197
202
|
requirements: []
|
198
203
|
rubyforge_project:
|
199
|
-
rubygems_version: 2.
|
204
|
+
rubygems_version: 2.6.11
|
200
205
|
signing_key:
|
201
206
|
specification_version: 4
|
202
207
|
summary: webmachine is a toolkit for building HTTP applications,
|
@@ -225,6 +230,7 @@ test_files:
|
|
225
230
|
- spec/webmachine/headers_spec.rb
|
226
231
|
- spec/webmachine/media_type_spec.rb
|
227
232
|
- spec/webmachine/request_spec.rb
|
233
|
+
- spec/webmachine/rescueable_exception_spec.rb
|
228
234
|
- spec/webmachine/resource/authentication_spec.rb
|
229
235
|
- spec/webmachine/response_spec.rb
|
230
236
|
- spec/webmachine/trace/fsm_spec.rb
|