webmachine 1.2.2 → 1.6.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 +7 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +57 -0
- data/Gemfile +20 -15
- data/README.md +89 -91
- data/RELEASING.md +21 -0
- data/Rakefile +5 -21
- data/documentation/adapters.md +41 -0
- data/documentation/authentication-and-authorization.md +37 -0
- data/documentation/configurator.md +19 -0
- data/documentation/error-handling.md +86 -0
- data/documentation/examples.md +224 -0
- data/documentation/how-it-works.md +76 -0
- data/documentation/routes.md +112 -0
- data/documentation/validation.md +159 -0
- data/documentation/versioning-apis.md +74 -0
- data/documentation/visual-debugger.md +38 -0
- data/examples/application.rb +2 -2
- data/examples/debugger.rb +1 -1
- data/lib/webmachine.rb +3 -1
- data/lib/webmachine/adapter.rb +7 -13
- data/lib/webmachine/adapters.rb +1 -2
- data/lib/webmachine/adapters/httpkit.rb +74 -0
- data/lib/webmachine/adapters/lazy_request_body.rb +1 -2
- data/lib/webmachine/adapters/rack.rb +70 -25
- data/lib/webmachine/adapters/rack_mapped.rb +42 -0
- data/lib/webmachine/adapters/reel.rb +22 -23
- data/lib/webmachine/adapters/webrick.rb +16 -16
- data/lib/webmachine/application.rb +2 -2
- data/lib/webmachine/chunked_body.rb +3 -4
- data/lib/webmachine/configuration.rb +1 -1
- data/lib/webmachine/constants.rb +75 -0
- data/lib/webmachine/decision/conneg.rb +12 -10
- data/lib/webmachine/decision/flow.rb +42 -32
- data/lib/webmachine/decision/fsm.rb +14 -21
- data/lib/webmachine/decision/helpers.rb +10 -38
- data/lib/webmachine/dispatcher.rb +13 -10
- data/lib/webmachine/dispatcher/route.rb +45 -9
- data/lib/webmachine/errors.rb +9 -3
- data/lib/webmachine/events.rb +2 -2
- data/lib/webmachine/header_negotiation.rb +25 -0
- data/lib/webmachine/headers.rb +8 -3
- data/lib/webmachine/locale/en.yml +7 -5
- data/lib/webmachine/media_type.rb +10 -8
- data/lib/webmachine/request.rb +67 -26
- data/lib/webmachine/rescueable_exception.rb +62 -0
- data/lib/webmachine/resource.rb +1 -1
- data/lib/webmachine/resource/callbacks.rb +11 -9
- data/lib/webmachine/response.rb +3 -5
- data/lib/webmachine/spec/IO_response.body +1 -0
- data/lib/webmachine/spec/adapter_lint.rb +83 -37
- data/lib/webmachine/spec/test_resource.rb +15 -4
- data/lib/webmachine/streaming/fiber_encoder.rb +1 -5
- data/lib/webmachine/streaming/io_encoder.rb +7 -1
- data/lib/webmachine/trace.rb +1 -0
- data/lib/webmachine/trace/fsm.rb +20 -10
- data/lib/webmachine/trace/resource_proxy.rb +2 -0
- data/lib/webmachine/translation.rb +2 -1
- data/lib/webmachine/version.rb +3 -3
- data/memory_test.rb +37 -0
- data/spec/spec_helper.rb +17 -9
- data/spec/webmachine/adapter_spec.rb +14 -15
- data/spec/webmachine/adapters/httpkit_spec.rb +10 -0
- data/spec/webmachine/adapters/rack_mapped_spec.rb +71 -0
- data/spec/webmachine/adapters/rack_spec.rb +32 -6
- data/spec/webmachine/adapters/reel_spec.rb +16 -12
- data/spec/webmachine/adapters/webrick_spec.rb +2 -2
- data/spec/webmachine/application_spec.rb +18 -17
- data/spec/webmachine/chunked_body_spec.rb +3 -3
- data/spec/webmachine/configuration_spec.rb +5 -5
- data/spec/webmachine/cookie_spec.rb +13 -13
- data/spec/webmachine/decision/conneg_spec.rb +49 -43
- data/spec/webmachine/decision/falsey_spec.rb +4 -4
- data/spec/webmachine/decision/flow_spec.rb +195 -145
- data/spec/webmachine/decision/fsm_spec.rb +81 -19
- data/spec/webmachine/decision/helpers_spec.rb +20 -20
- data/spec/webmachine/dispatcher/rfc3986_percent_decode_spec.rb +22 -0
- data/spec/webmachine/dispatcher/route_spec.rb +114 -32
- data/spec/webmachine/dispatcher_spec.rb +49 -24
- data/spec/webmachine/errors_spec.rb +1 -1
- data/spec/webmachine/etags_spec.rb +19 -19
- data/spec/webmachine/events_spec.rb +6 -6
- data/spec/webmachine/headers_spec.rb +14 -14
- data/spec/webmachine/media_type_spec.rb +36 -36
- data/spec/webmachine/request_spec.rb +70 -39
- data/spec/webmachine/rescueable_exception_spec.rb +15 -0
- data/spec/webmachine/resource/authentication_spec.rb +6 -6
- data/spec/webmachine/response_spec.rb +18 -12
- data/spec/webmachine/trace/fsm_spec.rb +8 -8
- data/spec/webmachine/trace/resource_proxy_spec.rb +9 -9
- data/spec/webmachine/trace/trace_store_spec.rb +5 -5
- data/spec/webmachine/trace_spec.rb +3 -3
- data/webmachine.gemspec +2 -6
- metadata +78 -228
- data/lib/webmachine/adapters/hatetepe.rb +0 -108
- data/lib/webmachine/adapters/mongrel.rb +0 -127
- data/lib/webmachine/dispatcher/not_found_resource.rb +0 -5
- data/lib/webmachine/fiber18.rb +0 -88
- data/spec/webmachine/adapters/hatetepe_spec.rb +0 -60
- data/spec/webmachine/adapters/mongrel_spec.rb +0 -16
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Routes
|
|
2
|
+
|
|
3
|
+
## Paths
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
App = Webmachine::Application.new do |app|
|
|
7
|
+
app.routes do
|
|
8
|
+
# Will map to /orders
|
|
9
|
+
add ["orders"], OrdersResource
|
|
10
|
+
|
|
11
|
+
# Will map to /orders/:id
|
|
12
|
+
# request.path_info[:id] will contain the matched token value
|
|
13
|
+
add ["orders", :id], OrderResource
|
|
14
|
+
|
|
15
|
+
# Will map to /person/:person_id/orders/:order_id and
|
|
16
|
+
# provide :person_id and :order_id in request.path_info
|
|
17
|
+
add ["person", :person_id, "orders", :order_id], OrderResource
|
|
18
|
+
|
|
19
|
+
# Will map to any path starting with /orders,
|
|
20
|
+
# but will not provide any path_info
|
|
21
|
+
add ["orders", :*], OrderResource
|
|
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
|
+
|
|
38
|
+
# will map to any path
|
|
39
|
+
add [:*], DefaultResource
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Guards
|
|
45
|
+
|
|
46
|
+
Guards prevent a request being sent to a Resource with a matching route unless its conditions are met.
|
|
47
|
+
|
|
48
|
+
##### Lambda
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
App = Webmachine::Application.new do |app|
|
|
52
|
+
app.routes do
|
|
53
|
+
add ["orders"], lambda { |request| request.headers['X-My-App-Version'] == "1" }, OrdersResourceV1
|
|
54
|
+
add ["orders"], lambda { |request| request.headers['X-My-App-Version'] == "2" }, OrdersResourceV2
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
##### Block
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
App = Webmachine::Application.new do |app|
|
|
64
|
+
app.routes do
|
|
65
|
+
add ["orders"], OrdersResourceV1 do | request |
|
|
66
|
+
request.headers['X-My-App-Version'] == "1"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
##### Callable class
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
class VersionGuard
|
|
77
|
+
|
|
78
|
+
def initialize version
|
|
79
|
+
@version = version
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def call(request)
|
|
83
|
+
request.headers['X-My-App-Version'] == @version
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
App = Webmachine::Application.new do |app|
|
|
89
|
+
app.routes do
|
|
90
|
+
add ["orders"], VersionGuard.new("1"), OrdersResourceV1
|
|
91
|
+
add ["orders"], VersionGuard.new("2"), OrdersResourceV2
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## User defined bindings
|
|
98
|
+
|
|
99
|
+
User defined bindings specified for a route will be made available through `request.path_info`.
|
|
100
|
+
|
|
101
|
+
```ruby
|
|
102
|
+
|
|
103
|
+
App = Webmachine::Application.new do |app|
|
|
104
|
+
app.routes do
|
|
105
|
+
add ["orders"], OrdersResource, :foo => "bar"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
request.path_info[:foo]
|
|
110
|
+
=> "bar"
|
|
111
|
+
|
|
112
|
+
```
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Validation
|
|
2
|
+
|
|
3
|
+
There are a couple of callbacks that are the most appropriate for doing validation in. The first is the `malformed_request?` which runs early in the Finite State Machine, and the second is inside the content type handler, for example `from_json`.
|
|
4
|
+
|
|
5
|
+
## malformed_request
|
|
6
|
+
|
|
7
|
+
If `malformed_request?` returns a truthy value, then a 400 Bad Request will be returned. Unfortunately, at this early stage in the flow, we don't know what the `method` or the `Content-Type` are without inspecting the request, and this leads to some very Iffy code.
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
class OrdersResource < Webmachine::Resource
|
|
11
|
+
|
|
12
|
+
def allowed_methods
|
|
13
|
+
["POST", "GET"]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Iffy! What method? GET doesn't require any validation.
|
|
17
|
+
def malformed_request?
|
|
18
|
+
if request.post?
|
|
19
|
+
# What Content-Type? Very Iffy!
|
|
20
|
+
if request.headers['Content-Type'] == "application/json"
|
|
21
|
+
....
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def content_types_accepted
|
|
29
|
+
[
|
|
30
|
+
["application/json", :from_json],
|
|
31
|
+
["application/xml", :from_xml]
|
|
32
|
+
]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def content_types_provided
|
|
36
|
+
[
|
|
37
|
+
["application/json", :to_json],
|
|
38
|
+
["application/xml", :to_xml]
|
|
39
|
+
]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def post_is_create?
|
|
43
|
+
true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def create_path
|
|
47
|
+
"/orders/#{next_id}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def from_json
|
|
51
|
+
order = Order.from_json(request.body.to_s)
|
|
52
|
+
response.body = order.save(next_id).to_json
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def from_xml
|
|
56
|
+
order = Order.from_xml(request.body.to_s)
|
|
57
|
+
response.body = order.save(next_id).to_xml
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def to_json
|
|
61
|
+
Order.all.to_json
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def to_xml
|
|
65
|
+
Order.all.to_xml
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def next_id
|
|
71
|
+
@next_id ||= Order.next_id
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Content-Type handler
|
|
78
|
+
|
|
79
|
+
A more elegant way to handle validation is to do it in a callback where we already know the `method` and the `Content-Type` - that is, the handler for the given Content-Type (eg. `from_json` and `from_xml`). By returning a `400` from the handler, we stop the state machine flow.
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
class OrdersResource < Webmachine::Resource
|
|
83
|
+
|
|
84
|
+
def allowed_methods
|
|
85
|
+
["POST", "GET"]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Iffy! What method? GET doesn't require any validation.
|
|
89
|
+
def malformed_request?
|
|
90
|
+
if request.post?
|
|
91
|
+
invalid_create_order_request?
|
|
92
|
+
else
|
|
93
|
+
false
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def content_types_accepted
|
|
98
|
+
[
|
|
99
|
+
["application/json", :from_json],
|
|
100
|
+
["application/xml", :from_xml]
|
|
101
|
+
]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def content_types_provided
|
|
105
|
+
[
|
|
106
|
+
["application/json", :to_json],
|
|
107
|
+
["application/xml", :to_xml]
|
|
108
|
+
]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def post_is_create?
|
|
112
|
+
true
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def create_path
|
|
116
|
+
"/orders/#{next_id}"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def from_json
|
|
120
|
+
order = Order.from_json(request.body.to_s)
|
|
121
|
+
# A bit less Iffy!
|
|
122
|
+
return json_validation_errors(order) unless order.valid?
|
|
123
|
+
response.body = order.save(next_id).to_json
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# This could use some DRYing up, but you get the point.
|
|
127
|
+
def from_xml
|
|
128
|
+
order = Order.from_xml(request.body.to_s)
|
|
129
|
+
# A bit less Iffy!
|
|
130
|
+
return xml_validation_errors(order) unless order.valid?
|
|
131
|
+
response.body = order.save(next_id).to_xml
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def to_json
|
|
135
|
+
Order.all.to_json
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def to_xml
|
|
139
|
+
Order.all.to_xml
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
private
|
|
143
|
+
|
|
144
|
+
def json_validation_errors(order)
|
|
145
|
+
response.body = order.validation_errors.to_json
|
|
146
|
+
400
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def xml_validation_errors(order)
|
|
150
|
+
response.body = order.validation_errors.to_xml
|
|
151
|
+
400
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def next_id
|
|
155
|
+
@next_id ||= Order.next_id
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end
|
|
159
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Versioning APIs
|
|
2
|
+
|
|
3
|
+
## By URL
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
|
|
7
|
+
class MyResourceV1 < Webmachine::Resource
|
|
8
|
+
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class MyResourceV2 < Webmachine::Resource
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
App = Webmachine::Application.new do |app|
|
|
16
|
+
app.routes do
|
|
17
|
+
add ["api", "v1", "myresource"], MyResourceV1
|
|
18
|
+
add ["api", "v2", "myresource"], MyResourceV2
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## By Content-Type
|
|
25
|
+
|
|
26
|
+
Note: if no Accept header is specified, then the first content type in the list will be chosen.
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
|
|
30
|
+
class MyResource < Webmachine::Resource
|
|
31
|
+
|
|
32
|
+
def content_types_provided
|
|
33
|
+
[
|
|
34
|
+
["application/myapp.v2+json", :to_json_v2],
|
|
35
|
+
["application/myapp.v1+json", :to_json_v1]
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## By Header value
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
|
|
47
|
+
class MyResourceV1 < Webmachine::Resource
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class MyResourceV2 < Webmachine::Resource
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class VersionGuard
|
|
56
|
+
|
|
57
|
+
def initialize version
|
|
58
|
+
@version = version
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def call(request)
|
|
62
|
+
request.headers['X-My-App-Version'] == @version
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
App = Webmachine::Application.new do |app|
|
|
68
|
+
app.routes do
|
|
69
|
+
add ["api", "myresource"], VersionGuard.new("1"), MyResourceV1
|
|
70
|
+
add ["api", "myresource"], VersionGuard.new("2"), MyResourceV2
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
### Visual debugger
|
|
2
|
+
|
|
3
|
+
In development, you can turn on tracing of the
|
|
4
|
+
decision graph for a resource by implementing the `#trace?` callback
|
|
5
|
+
so that it returns true:
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
class MyTracedResource < Webmachine::Resource
|
|
9
|
+
def trace?
|
|
10
|
+
true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# The rest of your callbacks...
|
|
14
|
+
end
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then enable the visual debugger resource by adding a route to your
|
|
18
|
+
configuration:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
Webmachine.application.routes do
|
|
22
|
+
# This can be any path as long as it ends with :*
|
|
23
|
+
add ['trace', :*], Webmachine::Trace::TraceResource
|
|
24
|
+
# The rest of your routes...
|
|
25
|
+
end
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Now when you visit your traced resource, a trace of the request
|
|
29
|
+
process will be recorded in memory. Open your browser to `/trace` to
|
|
30
|
+
list the recorded traces and inspect the result. The response from your
|
|
31
|
+
traced resource will also include the `X-Webmachine-Trace-Id` that you
|
|
32
|
+
can use to lookup the trace. It might look something like this:
|
|
33
|
+
|
|
34
|
+

|
|
35
|
+
|
|
36
|
+
Refer to
|
|
37
|
+
[examples/debugger.rb](/examples/debugger.rb)
|
|
38
|
+
for an example of how to enable the debugger.
|
data/examples/application.rb
CHANGED
|
@@ -25,10 +25,10 @@ MyApp = Webmachine::Application.new do |app|
|
|
|
25
25
|
config.adapter = :WEBrick
|
|
26
26
|
end
|
|
27
27
|
# And add routes like this:
|
|
28
|
-
app.add_route ['fizz', :buzz,
|
|
28
|
+
app.add_route ['fizz', :buzz, :*], RouteDebugResource
|
|
29
29
|
# OR add routes this way:
|
|
30
30
|
app.routes do
|
|
31
|
-
add [:test, :foo,
|
|
31
|
+
add [:test, :foo, :*], RouteDebugResource
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
data/examples/debugger.rb
CHANGED
data/lib/webmachine.rb
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
require 'webmachine/configuration'
|
|
1
|
+
require 'webmachine/configuration'
|
|
2
|
+
require 'webmachine/constants'
|
|
2
3
|
require 'webmachine/cookie'
|
|
3
4
|
require 'webmachine/headers'
|
|
4
5
|
require 'webmachine/request'
|
|
5
6
|
require 'webmachine/response'
|
|
6
7
|
require 'webmachine/etags'
|
|
7
8
|
require 'webmachine/errors'
|
|
9
|
+
require 'webmachine/header_negotiation'
|
|
8
10
|
require 'webmachine/decision'
|
|
9
11
|
require 'webmachine/streaming'
|
|
10
12
|
require 'webmachine/adapter'
|
data/lib/webmachine/adapter.rb
CHANGED
|
@@ -5,23 +5,17 @@ module Webmachine
|
|
|
5
5
|
# @abstract Subclass and override {#run} to implement a custom adapter.
|
|
6
6
|
class Adapter
|
|
7
7
|
|
|
8
|
-
# @return [Webmachine::
|
|
9
|
-
attr_reader :
|
|
8
|
+
# @return [Webmachine::Application] returns the application
|
|
9
|
+
attr_reader :application
|
|
10
10
|
|
|
11
|
-
# @
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# @param [Webmachine::Configuration] configuration the application's
|
|
15
|
-
# configuration.
|
|
16
|
-
# @param [Webmachine::Dispatcher] dispatcher the application's dispatcher.
|
|
17
|
-
def initialize(configuration, dispatcher)
|
|
18
|
-
@configuration = configuration
|
|
19
|
-
@dispatcher = dispatcher
|
|
11
|
+
# @param [Webmachine::Application] application the application
|
|
12
|
+
def initialize(application)
|
|
13
|
+
@application = application
|
|
20
14
|
end
|
|
21
15
|
|
|
22
16
|
# Create a new adapter and run it.
|
|
23
|
-
def self.run(
|
|
24
|
-
new(
|
|
17
|
+
def self.run(application)
|
|
18
|
+
new(application).run
|
|
25
19
|
end
|
|
26
20
|
|
|
27
21
|
# Start the adapter.
|