webmachine 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://travis-ci.org/
|
1
|
+
# webmachine for Ruby [![Build Status](https://travis-ci.org/webmachine/webmachine-ruby.svg)](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
|