webmachine 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +9 -0
- data/README.md +65 -2
- data/lib/webmachine.rb +1 -0
- data/lib/webmachine/adapters.rb +4 -1
- data/lib/webmachine/adapters/hatetepe.rb +104 -0
- data/lib/webmachine/adapters/lazy_request_body.rb +32 -0
- data/lib/webmachine/adapters/rack.rb +2 -1
- data/lib/webmachine/adapters/reel.rb +45 -0
- data/lib/webmachine/adapters/webrick.rb +1 -30
- data/lib/webmachine/decision/falsey.rb +10 -0
- data/lib/webmachine/decision/flow.rb +28 -26
- data/lib/webmachine/decision/fsm.rb +22 -12
- data/lib/webmachine/decision/helpers.rb +17 -23
- data/lib/webmachine/etags.rb +69 -0
- data/lib/webmachine/headers.rb +42 -0
- data/lib/webmachine/quoted_string.rb +39 -0
- data/lib/webmachine/resource.rb +17 -0
- data/lib/webmachine/resource/callbacks.rb +1 -1
- data/lib/webmachine/resource/entity_tags.rb +17 -0
- data/lib/webmachine/streaming.rb +9 -61
- data/lib/webmachine/streaming/callable_encoder.rb +21 -0
- data/lib/webmachine/streaming/encoder.rb +24 -0
- data/lib/webmachine/streaming/enumerable_encoder.rb +20 -0
- data/lib/webmachine/streaming/fiber_encoder.rb +25 -0
- data/lib/webmachine/streaming/io_encoder.rb +65 -0
- data/lib/webmachine/trace/fsm.rb +9 -4
- data/lib/webmachine/trace/resource_proxy.rb +2 -4
- data/lib/webmachine/trace/static/tracelist.erb +2 -2
- data/lib/webmachine/trace/trace_resource.rb +3 -2
- data/lib/webmachine/version.rb +1 -1
- data/spec/webmachine/adapters/hatetepe_spec.rb +64 -0
- data/spec/webmachine/adapters/rack_spec.rb +18 -8
- data/spec/webmachine/adapters/reel_spec.rb +23 -0
- data/spec/webmachine/decision/falsey_spec.rb +8 -0
- data/spec/webmachine/decision/flow_spec.rb +12 -0
- data/spec/webmachine/decision/fsm_spec.rb +101 -0
- data/spec/webmachine/decision/helpers_spec.rb +68 -8
- data/spec/webmachine/dispatcher/route_spec.rb +1 -1
- data/spec/webmachine/dispatcher_spec.rb +1 -1
- data/spec/webmachine/errors_spec.rb +1 -1
- data/spec/webmachine/etags_spec.rb +75 -0
- data/spec/webmachine/headers_spec.rb +72 -0
- data/spec/webmachine/trace/fsm_spec.rb +5 -0
- data/spec/webmachine/trace/resource_proxy_spec.rb +1 -3
- data/webmachine.gemspec +1 -2
- metadata +49 -20
data/Gemfile
CHANGED
@@ -6,6 +6,15 @@ gemspec
|
|
6
6
|
|
7
7
|
gem 'bundler'
|
8
8
|
|
9
|
+
group :webservers do
|
10
|
+
gem 'mongrel', '~> 1.2.beta', :platform => [:mri, :rbx]
|
11
|
+
if RUBY_VERSION >= '1.9'
|
12
|
+
gem 'reel', '>= 0.1.0', :platform => [:ruby_19, :jruby]
|
13
|
+
gem 'nio4r'
|
14
|
+
end
|
15
|
+
gem 'hatetepe', '~> 0.5'
|
16
|
+
end
|
17
|
+
|
9
18
|
group :guard do
|
10
19
|
gem 'guard-rspec'
|
11
20
|
case RbConfig::CONFIG['host_os']
|
data/README.md
CHANGED
@@ -100,6 +100,19 @@ end
|
|
100
100
|
Webmachine.application.run
|
101
101
|
```
|
102
102
|
|
103
|
+
Webmachine includes adapters for [Webrick][webrick], [Mongrel][mongrel],
|
104
|
+
[Reel][reel], and [Hatetepe]. Additionally, the [Rack][rack] adapter lets it
|
105
|
+
run on any webserver that provides a Rack interface. It also lets it run on
|
106
|
+
[Shotgun][shotgun] ([example][shotgun_example]).
|
107
|
+
|
108
|
+
[webrick]: http://rubydoc.info/stdlib/webrick
|
109
|
+
[mongrel]: https://github.com/evan/mongrel
|
110
|
+
[reel]: https://github.com/celluloid/reel
|
111
|
+
[hatetepe]: https://github.com/lgierth/hatetepe
|
112
|
+
[rack]: https://github.com/rack/rack
|
113
|
+
[shotgun]: https://github.com/rtomayko/shotgun
|
114
|
+
[shotgun_example]: https://gist.github.com/4389220
|
115
|
+
|
103
116
|
### Visual debugger
|
104
117
|
|
105
118
|
It can be hard to understand all of the decisions that Webmachine
|
@@ -156,9 +169,24 @@ for an example of how to enable the debugger.
|
|
156
169
|
* Includes the visual debugger so you can look through the decision
|
157
170
|
graph to determine how your resources are behaving.
|
158
171
|
|
159
|
-
##
|
172
|
+
## Caveats
|
173
|
+
|
174
|
+
* The [Reel](https://github.com/celluloid/reel) adapter might fail with a
|
175
|
+
`SystemStackError` on MRI (< 2.0) due to its limited fiber stack size.
|
176
|
+
The only known solution is to switch to JRuby, Rubinius or MRI 2.0.
|
177
|
+
|
178
|
+
|
179
|
+
## Documentation & Finding Help
|
160
180
|
|
161
|
-
*
|
181
|
+
* [API documentation](http://rubydoc.info/gems/webmachine/frames/file/README.md)
|
182
|
+
* IRC channel #webmachine on freenode
|
183
|
+
|
184
|
+
## Related libraries
|
185
|
+
|
186
|
+
* [irwebmachine](https://github.com/robgleeson/irwebmachine) - IRB/Pry debugging of Webmachine applications
|
187
|
+
* [webmachine-test](https://github.com/bernd/webmachine-test) - Helpers for testing Webmachine applications
|
188
|
+
- [webmachine-linking](https://github.com/petejohanson/webmachine-linking) - Helpers for linking between Resources, and Web Linking
|
189
|
+
- [webmachine-sprockets](https://github.com/lgierth/webmachine-sprockets) - Integration with Sprockets assets packaging system
|
162
190
|
|
163
191
|
## LICENSE
|
164
192
|
|
@@ -168,6 +196,41 @@ LICENSE for details.
|
|
168
196
|
|
169
197
|
## Changelog
|
170
198
|
|
199
|
+
### 1.1.0 January 12, 2013
|
200
|
+
|
201
|
+
1.1.0 is a major feature release that adds the Reel and Hatetepe
|
202
|
+
adapters, support for "weak" entity tags, streaming IO response
|
203
|
+
bodies, better error handling, a shortcut for spinning up specific
|
204
|
+
resources, and a bunch of bugfixes. Added Tony Arcieri, Sebastian
|
205
|
+
Edwards, Russell Garner, Justin McPherson, Paweł Pacana, and Nicholas
|
206
|
+
Young as contributors. Thank you for your contributions!
|
207
|
+
|
208
|
+
* Added Reel adapter.
|
209
|
+
* The trace resource now opens static files in binary mode to ensure
|
210
|
+
compatibility on Windows.
|
211
|
+
* The trace resource uses absolute URIs for its traces.
|
212
|
+
* Added Hatetepe adapter.
|
213
|
+
* Added direct weak entity tag support.
|
214
|
+
* Related libraries are linked from the README.
|
215
|
+
* Removed some circular requires.
|
216
|
+
* Fixed documentation for the `valid_content_headers?` callback.
|
217
|
+
* Fixed `Headers` initialization by downcasing incoming header names.
|
218
|
+
* Added a `Headers#fetch` method.
|
219
|
+
* Conventionally "truthy" and "falsey" values (non-nil, non-false) can
|
220
|
+
now be returned from callbacks that expect a boolean return value.
|
221
|
+
* Updated to the latest RSpec.
|
222
|
+
* Added support for IO response bodies (minimal).
|
223
|
+
* Moved streaming encoders to their own module for clarity.
|
224
|
+
* Added `Resource#run` that starts up a web server with default
|
225
|
+
configuration options and the catch-all route to the resource.
|
226
|
+
* The exception handling flow was improved, clarifying the
|
227
|
+
`handle_exception` and `finish_request` callbacks.
|
228
|
+
* Fix incompatibilities with Rack.
|
229
|
+
* The request URI will not be initialized with parts that are not
|
230
|
+
present in the HTTP request.
|
231
|
+
* The tracing will now commit to storage after the response has been
|
232
|
+
traced.
|
233
|
+
|
171
234
|
### 1.0.0 July 7, 2012
|
172
235
|
|
173
236
|
1.0.0 is a major feature release that finally includes the visual
|
data/lib/webmachine.rb
CHANGED
data/lib/webmachine/adapters.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
require 'webmachine/adapters/lazy_request_body'
|
1
2
|
require 'webmachine/adapters/webrick'
|
2
3
|
|
3
4
|
module Webmachine
|
4
5
|
# Contains classes and modules that connect Webmachine to Ruby
|
5
6
|
# application servers.
|
6
7
|
module Adapters
|
7
|
-
autoload :Mongrel,
|
8
|
+
autoload :Mongrel, 'webmachine/adapters/mongrel'
|
9
|
+
autoload :Reel, 'webmachine/adapters/reel'
|
10
|
+
autoload :Hatetepe, 'webmachine/adapters/hatetepe'
|
8
11
|
end
|
9
12
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'hatetepe/server'
|
2
|
+
|
3
|
+
unless Hatetepe::VERSION >= '0.5.0'
|
4
|
+
raise LoadError, 'webmachine only supports hatetepe >= 0.5.0'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'webmachine/version'
|
8
|
+
require 'webmachine/headers'
|
9
|
+
require 'webmachine/request'
|
10
|
+
require 'webmachine/response'
|
11
|
+
require 'webmachine/dispatcher'
|
12
|
+
require 'webmachine/chunked_body'
|
13
|
+
|
14
|
+
module Webmachine
|
15
|
+
module Adapters
|
16
|
+
class Hatetepe < Adapter
|
17
|
+
def options
|
18
|
+
{
|
19
|
+
:host => configuration.ip,
|
20
|
+
:port => configuration.port,
|
21
|
+
:app => [
|
22
|
+
::Hatetepe::Server::Pipeline,
|
23
|
+
::Hatetepe::Server::KeepAlive,
|
24
|
+
method(:call)
|
25
|
+
]
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
EM.epoll
|
31
|
+
EM.synchrony do
|
32
|
+
::Hatetepe::Server.start(options)
|
33
|
+
trap("INT") { EM.stop }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(request, &respond)
|
38
|
+
response = Webmachine::Response.new
|
39
|
+
dispatcher.dispatch(convert_request(request), response)
|
40
|
+
|
41
|
+
respond.call(convert_response(response))
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def convert_request(request)
|
47
|
+
args = [
|
48
|
+
request.verb,
|
49
|
+
build_request_uri(request),
|
50
|
+
Webmachine::Headers[request.headers.dup],
|
51
|
+
Body.new(request.body)
|
52
|
+
]
|
53
|
+
Webmachine::Request.new(*args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def convert_response(response)
|
57
|
+
response.headers["Server"] = [
|
58
|
+
Webmachine::SERVER_STRING,
|
59
|
+
"hatetepe/#{::Hatetepe::VERSION}"
|
60
|
+
].join(" ")
|
61
|
+
|
62
|
+
args = [
|
63
|
+
response.code.to_i,
|
64
|
+
response.headers,
|
65
|
+
convert_body(response.body)
|
66
|
+
]
|
67
|
+
::Hatetepe::Response.new(*args)
|
68
|
+
end
|
69
|
+
|
70
|
+
def convert_body(body)
|
71
|
+
if body.respond_to?(:call)
|
72
|
+
[ body.call ]
|
73
|
+
elsif body.respond_to?(:to_s)
|
74
|
+
[ body.to_s ]
|
75
|
+
else
|
76
|
+
body
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def build_request_uri(request)
|
81
|
+
uri = URI.parse(request.uri)
|
82
|
+
uri.scheme = "http"
|
83
|
+
|
84
|
+
host = request.headers.fetch("Host", "").split(":")
|
85
|
+
uri.host = host[0] || configuration.ip
|
86
|
+
uri.port = host[1].to_i || configuration.port
|
87
|
+
|
88
|
+
URI.parse(uri.to_s)
|
89
|
+
end
|
90
|
+
|
91
|
+
class Body < Struct.new(:body)
|
92
|
+
def each(&block)
|
93
|
+
body.rewind
|
94
|
+
body.each(&block)
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_s
|
98
|
+
body.rewind
|
99
|
+
body.read.to_s
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
module Webmachine
|
3
|
+
module Adapters
|
4
|
+
# Wraps a request body so that it can be passed to
|
5
|
+
# {Request} while still lazily evaluating the body.
|
6
|
+
class LazyRequestBody
|
7
|
+
def initialize(request)
|
8
|
+
@request = request
|
9
|
+
end
|
10
|
+
|
11
|
+
# Converts the body to a String so you can work with the entire
|
12
|
+
# thing.
|
13
|
+
def to_s
|
14
|
+
@value ? @value.join : @request.body
|
15
|
+
end
|
16
|
+
|
17
|
+
# Iterates over the body in chunks. If the body has previously
|
18
|
+
# been read, this method can be called again and get the same
|
19
|
+
# sequence of chunks.
|
20
|
+
# @yield [chunk]
|
21
|
+
# @yieldparam [String] chunk a chunk of the request body
|
22
|
+
def each
|
23
|
+
if @value
|
24
|
+
@value.each {|chunk| yield chunk }
|
25
|
+
else
|
26
|
+
@value = []
|
27
|
+
@request.body {|chunk| @value << chunk; yield chunk }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end # class RequestBody
|
31
|
+
end # module Adapters
|
32
|
+
end # module Webmachine
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'reel'
|
2
|
+
require 'webmachine/version'
|
3
|
+
require 'webmachine/headers'
|
4
|
+
require 'webmachine/request'
|
5
|
+
require 'webmachine/response'
|
6
|
+
require 'webmachine/dispatcher'
|
7
|
+
require 'webmachine/chunked_body'
|
8
|
+
|
9
|
+
module Webmachine
|
10
|
+
module Adapters
|
11
|
+
class Reel < Adapter
|
12
|
+
def run
|
13
|
+
options = {
|
14
|
+
:port => configuration.port,
|
15
|
+
:host => configuration.ip
|
16
|
+
}.merge(configuration.adapter_options)
|
17
|
+
server = ::Reel::Server.supervise(options[:host], options[:port], &method(:process))
|
18
|
+
trap("INT"){ server.terminate; exit 0 }
|
19
|
+
sleep
|
20
|
+
end
|
21
|
+
|
22
|
+
def process(connection)
|
23
|
+
while wreq = connection.request
|
24
|
+
header = Webmachine::Headers[wreq.headers.dup]
|
25
|
+
host_parts = header.fetch('Host').split(':')
|
26
|
+
path_parts = wreq.url.split('?')
|
27
|
+
requri = URI::HTTP.build({}.tap do |h|
|
28
|
+
h[:host] = host_parts.first
|
29
|
+
h[:port] = host_parts.last.to_i if host_parts.length == 2
|
30
|
+
h[:path] = path_parts.first
|
31
|
+
h[:query] = path_parts.last if path_parts.length == 2
|
32
|
+
end)
|
33
|
+
request = Webmachine::Request.new(wreq.method.to_s.upcase,
|
34
|
+
requri,
|
35
|
+
header,
|
36
|
+
LazyRequestBody.new(wreq))
|
37
|
+
response = Webmachine::Response.new
|
38
|
+
@dispatcher.dispatch(request,response)
|
39
|
+
|
40
|
+
connection.respond ::Reel::Response.new(response.code, response.headers, response.body)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -35,7 +35,7 @@ module Webmachine
|
|
35
35
|
request = Webmachine::Request.new(wreq.request_method,
|
36
36
|
wreq.request_uri,
|
37
37
|
header,
|
38
|
-
|
38
|
+
LazyRequestBody.new(wreq))
|
39
39
|
response = Webmachine::Response.new
|
40
40
|
@dispatcher.dispatch(request, response)
|
41
41
|
wres.status = response.code.to_i
|
@@ -61,35 +61,6 @@ module Webmachine
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end # class Server
|
64
|
-
|
65
|
-
# Wraps the WEBrick request body so that it can be passed to
|
66
|
-
# {Request} while still lazily evaluating the body.
|
67
|
-
class RequestBody
|
68
|
-
def initialize(request)
|
69
|
-
@request = request
|
70
|
-
end
|
71
|
-
|
72
|
-
# Converts the body to a String so you can work with the entire
|
73
|
-
# thing.
|
74
|
-
def to_s
|
75
|
-
@value ? @value.join : @request.body
|
76
|
-
end
|
77
|
-
|
78
|
-
# Iterates over the body in chunks. If the body has previously
|
79
|
-
# been read, this method can be called again and get the same
|
80
|
-
# sequence of chunks.
|
81
|
-
# @yield [chunk]
|
82
|
-
# @yieldparam [String] chunk a chunk of the request body
|
83
|
-
def each
|
84
|
-
if @value
|
85
|
-
@value.each {|chunk| yield chunk }
|
86
|
-
else
|
87
|
-
@value = []
|
88
|
-
@request.body {|chunk| @value << chunk; yield chunk }
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end # class RequestBody
|
92
|
-
|
93
64
|
end # module WEBrick
|
94
65
|
end # module Adapters
|
95
66
|
end # module Webmachine
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'time'
|
2
2
|
require 'digest/md5'
|
3
3
|
require 'webmachine/decision/conneg'
|
4
|
+
require 'webmachine/decision/falsey'
|
4
5
|
require 'webmachine/translation'
|
6
|
+
require 'webmachine/etags'
|
5
7
|
|
6
8
|
module Webmachine
|
7
9
|
module Decision
|
@@ -27,30 +29,30 @@ module Webmachine
|
|
27
29
|
include Translation
|
28
30
|
|
29
31
|
# Handles standard decisions where halting is allowed
|
30
|
-
def decision_test(test,
|
32
|
+
def decision_test(test, iftrue, iffalse)
|
31
33
|
case test
|
32
|
-
when value
|
33
|
-
iftrue
|
34
34
|
when Fixnum # Allows callbacks to "halt" with a given response code
|
35
35
|
test
|
36
|
-
|
36
|
+
when Falsey
|
37
37
|
iffalse
|
38
|
+
else
|
39
|
+
iftrue
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
# Service available?
|
42
44
|
def b13
|
43
|
-
decision_test(resource.service_available?,
|
45
|
+
decision_test(resource.service_available?, :b12, 503)
|
44
46
|
end
|
45
47
|
|
46
48
|
# Known method?
|
47
49
|
def b12
|
48
|
-
decision_test(resource.known_methods.include?(request.method),
|
50
|
+
decision_test(resource.known_methods.include?(request.method), :b11, 501)
|
49
51
|
end
|
50
52
|
|
51
53
|
# URI too long?
|
52
54
|
def b11
|
53
|
-
decision_test(resource.uri_too_long?(request.uri),
|
55
|
+
decision_test(resource.uri_too_long?(request.uri), 414, :b10)
|
54
56
|
end
|
55
57
|
|
56
58
|
# Method allowed?
|
@@ -90,7 +92,7 @@ module Webmachine
|
|
90
92
|
|
91
93
|
# Malformed?
|
92
94
|
def b9b
|
93
|
-
decision_test(resource.malformed_request?,
|
95
|
+
decision_test(resource.malformed_request?, 400, :b8)
|
94
96
|
end
|
95
97
|
|
96
98
|
# Authorized?
|
@@ -111,22 +113,22 @@ module Webmachine
|
|
111
113
|
|
112
114
|
# Forbidden?
|
113
115
|
def b7
|
114
|
-
decision_test(resource.forbidden?,
|
116
|
+
decision_test(resource.forbidden?, 403, :b6)
|
115
117
|
end
|
116
118
|
|
117
119
|
# Okay Content-* Headers?
|
118
120
|
def b6
|
119
|
-
decision_test(resource.valid_content_headers?(request.headers.grep(/content-/)),
|
121
|
+
decision_test(resource.valid_content_headers?(request.headers.grep(/content-/)), :b5, 501)
|
120
122
|
end
|
121
123
|
|
122
124
|
# Known Content-Type?
|
123
125
|
def b5
|
124
|
-
decision_test(resource.known_content_type?(request.content_type),
|
126
|
+
decision_test(resource.known_content_type?(request.content_type), :b4, 415)
|
125
127
|
end
|
126
128
|
|
127
129
|
# Req Entity Too Large?
|
128
130
|
def b4
|
129
|
-
decision_test(resource.valid_entity_length?(request.content_length),
|
131
|
+
decision_test(resource.valid_entity_length?(request.content_length), :b3, 413)
|
130
132
|
end
|
131
133
|
|
132
134
|
# OPTIONS?
|
@@ -223,7 +225,7 @@ module Webmachine
|
|
223
225
|
def g7
|
224
226
|
# This is the first place after all conneg, so set Vary here
|
225
227
|
response.headers['Vary'] = variances.join(", ") if variances.any?
|
226
|
-
decision_test(resource.resource_exists?,
|
228
|
+
decision_test(resource.resource_exists?, :g8, :h7)
|
227
229
|
end
|
228
230
|
|
229
231
|
# If-Match exists?
|
@@ -233,18 +235,18 @@ module Webmachine
|
|
233
235
|
|
234
236
|
# If-Match: * exists?
|
235
237
|
def g9
|
236
|
-
request.if_match == "*" ? :h10 : :g11
|
238
|
+
quote(request.if_match) == '"*"' ? :h10 : :g11
|
237
239
|
end
|
238
240
|
|
239
241
|
# ETag in If-Match
|
240
242
|
def g11
|
241
|
-
request_etags = request.if_match.split(/\s*,\s*/).map {|etag|
|
242
|
-
request_etags.include?(resource.generate_etag) ? :h10 : 412
|
243
|
+
request_etags = request.if_match.split(/\s*,\s*/).map {|etag| ETag.new(etag) }
|
244
|
+
request_etags.include?(ETag.new(resource.generate_etag)) ? :h10 : 412
|
243
245
|
end
|
244
246
|
|
245
247
|
# If-Match exists?
|
246
248
|
def h7
|
247
|
-
(request.if_match &&
|
249
|
+
(request.if_match && unquote(request.if_match) == '*') ? 412 : :i7
|
248
250
|
end
|
249
251
|
|
250
252
|
# If-Unmodified-Since exists?
|
@@ -292,7 +294,7 @@ module Webmachine
|
|
292
294
|
|
293
295
|
# If-none-match: * exists?
|
294
296
|
def i13
|
295
|
-
request.if_none_match == "*" ? :j18 : :k13
|
297
|
+
quote(request.if_none_match) == '"*"' ? :j18 : :k13
|
296
298
|
end
|
297
299
|
|
298
300
|
# GET or HEAD?
|
@@ -315,13 +317,13 @@ module Webmachine
|
|
315
317
|
|
316
318
|
# Previously existed?
|
317
319
|
def k7
|
318
|
-
decision_test(resource.previously_existed?,
|
320
|
+
decision_test(resource.previously_existed?, :k5, :l7)
|
319
321
|
end
|
320
322
|
|
321
323
|
# Etag in if-none-match?
|
322
324
|
def k13
|
323
|
-
request_etags = request.if_none_match.split(/\s*,\s*/).map {|etag|
|
324
|
-
request_etags.include?(resource.generate_etag) ? :j18 : :l13
|
325
|
+
request_etags = request.if_none_match.split(/\s*,\s*/).map {|etag| ETag.new(etag) }
|
326
|
+
request_etags.include?(ETag.new(resource.generate_etag)) ? :j18 : :l13
|
325
327
|
end
|
326
328
|
|
327
329
|
# Moved temporarily?
|
@@ -374,7 +376,7 @@ module Webmachine
|
|
374
376
|
|
375
377
|
# Server allows POST to missing resource?
|
376
378
|
def m7
|
377
|
-
decision_test(resource.allow_missing_post?,
|
379
|
+
decision_test(resource.allow_missing_post?, :n11, 404)
|
378
380
|
end
|
379
381
|
|
380
382
|
# DELETE?
|
@@ -384,17 +386,17 @@ module Webmachine
|
|
384
386
|
|
385
387
|
# DELETE enacted immediately? (Also where DELETE is forced.)
|
386
388
|
def m20
|
387
|
-
decision_test(resource.delete_resource,
|
389
|
+
decision_test(resource.delete_resource, :m20b, 500)
|
388
390
|
end
|
389
391
|
|
390
392
|
# Did the DELETE complete?
|
391
393
|
def m20b
|
392
|
-
decision_test(resource.delete_completed?,
|
394
|
+
decision_test(resource.delete_completed?, :o20, 202)
|
393
395
|
end
|
394
396
|
|
395
397
|
# Server allows POST to missing resource?
|
396
398
|
def n5
|
397
|
-
decision_test(resource.allow_missing_post?,
|
399
|
+
decision_test(resource.allow_missing_post?, :n11, 410)
|
398
400
|
end
|
399
401
|
|
400
402
|
# Redirect?
|
@@ -475,7 +477,7 @@ module Webmachine
|
|
475
477
|
|
476
478
|
# Multiple choices?
|
477
479
|
def o18b
|
478
|
-
decision_test(resource.multiple_choices?,
|
480
|
+
decision_test(resource.multiple_choices?, 300, 200)
|
479
481
|
end
|
480
482
|
|
481
483
|
# Response includes an entity?
|