webmachine 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +13 -11
- data/README.md +85 -89
- data/Rakefile +0 -1
- data/documentation/adapters.md +39 -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 +215 -0
- data/documentation/how-it-works.md +76 -0
- data/documentation/routes.md +97 -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 +37 -21
- data/lib/webmachine/adapters/reel.rb +21 -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/constants.rb +75 -0
- data/lib/webmachine/decision/conneg.rb +12 -10
- data/lib/webmachine/decision/flow.rb +31 -21
- data/lib/webmachine/decision/fsm.rb +10 -18
- data/lib/webmachine/decision/helpers.rb +9 -37
- data/lib/webmachine/dispatcher.rb +13 -10
- data/lib/webmachine/dispatcher/route.rb +18 -8
- data/lib/webmachine/errors.rb +7 -1
- data/lib/webmachine/header_negotiation.rb +25 -0
- data/lib/webmachine/headers.rb +7 -2
- data/lib/webmachine/locale/en.yml +7 -5
- data/lib/webmachine/media_type.rb +10 -8
- data/lib/webmachine/request.rb +44 -15
- data/lib/webmachine/resource.rb +1 -1
- data/lib/webmachine/resource/callbacks.rb +6 -4
- data/lib/webmachine/spec/IO_response.body +1 -0
- data/lib/webmachine/spec/adapter_lint.rb +70 -36
- data/lib/webmachine/spec/test_resource.rb +10 -4
- data/lib/webmachine/streaming/fiber_encoder.rb +1 -5
- data/lib/webmachine/streaming/io_encoder.rb +6 -0
- 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 +9 -9
- data/spec/webmachine/adapter_spec.rb +14 -15
- data/spec/webmachine/adapters/httpkit_spec.rb +10 -0
- data/spec/webmachine/adapters/rack_spec.rb +6 -6
- data/spec/webmachine/adapters/reel_spec.rb +15 -11
- 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 +48 -42
- data/spec/webmachine/decision/falsey_spec.rb +4 -4
- data/spec/webmachine/decision/flow_spec.rb +194 -144
- data/spec/webmachine/decision/fsm_spec.rb +17 -17
- data/spec/webmachine/decision/helpers_spec.rb +20 -20
- data/spec/webmachine/dispatcher/route_spec.rb +73 -27
- data/spec/webmachine/dispatcher_spec.rb +34 -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 +33 -33
- data/spec/webmachine/resource/authentication_spec.rb +6 -6
- data/spec/webmachine/response_spec.rb +12 -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 +48 -206
- 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,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.
|
data/lib/webmachine/adapters.rb
CHANGED
@@ -5,8 +5,7 @@ module Webmachine
|
|
5
5
|
# Contains classes and modules that connect Webmachine to Ruby
|
6
6
|
# application servers.
|
7
7
|
module Adapters
|
8
|
-
autoload :Mongrel, 'webmachine/adapters/mongrel'
|
9
8
|
autoload :Reel, 'webmachine/adapters/reel'
|
10
|
-
autoload :
|
9
|
+
autoload :HTTPkit, 'webmachine/adapters/httpkit'
|
11
10
|
end
|
12
11
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'webmachine/adapter'
|
2
|
+
require 'webmachine/constants'
|
3
|
+
require 'webmachine/version'
|
4
|
+
require 'httpkit'
|
5
|
+
require 'webmachine/version'
|
6
|
+
require 'webmachine/response'
|
7
|
+
require 'webmachine/request'
|
8
|
+
require 'webmachine/headers'
|
9
|
+
|
10
|
+
module Webmachine
|
11
|
+
module Adapters
|
12
|
+
class HTTPkit < Adapter
|
13
|
+
VERSION_STRING = "#{Webmachine::SERVER_STRING} HTTPkit/#{::HTTPkit::VERSION}".freeze
|
14
|
+
|
15
|
+
def options
|
16
|
+
@options ||= {
|
17
|
+
:address => application.configuration.ip,
|
18
|
+
:port => application.configuration.port,
|
19
|
+
:handlers => [
|
20
|
+
::HTTPkit::Server::TimeoutsHandler.new,
|
21
|
+
::HTTPkit::Server::KeepAliveHandler.new,
|
22
|
+
self
|
23
|
+
]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
::HTTPkit.start do
|
29
|
+
::HTTPkit::Server.start(options)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Called by HTTPkit::Server for every request
|
34
|
+
def serve(request, served)
|
35
|
+
response = Webmachine::Response.new
|
36
|
+
application.dispatcher.dispatch(convert_request(request), response)
|
37
|
+
|
38
|
+
served.fulfill(convert_response(response))
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Converts HTTPkit::Request to Webmachine::Request
|
44
|
+
def convert_request(request)
|
45
|
+
Webmachine::Request.new(
|
46
|
+
request.http_method.to_s.upcase,
|
47
|
+
request.uri,
|
48
|
+
Webmachine::Headers[request.headers.dup],
|
49
|
+
request.body)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Converts Webmachine::Response to HTTPkit::Response
|
53
|
+
def convert_response(response)
|
54
|
+
response.headers[SERVER] = VERSION_STRING
|
55
|
+
|
56
|
+
|
57
|
+
::HTTPkit::Response.new(
|
58
|
+
response.code.to_i,
|
59
|
+
response.headers,
|
60
|
+
convert_body(response.body))
|
61
|
+
end
|
62
|
+
|
63
|
+
# HTTPkit::Body accepts strings and enumerables, i.e. Webmachine's
|
64
|
+
# Callable, Enumerable, IO, and Fiber encoders are supported.
|
65
|
+
def convert_body(body)
|
66
|
+
if body.respond_to?(:call)
|
67
|
+
[body.call]
|
68
|
+
else
|
69
|
+
body || ''
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -1,17 +1,20 @@
|
|
1
|
+
require 'webmachine/adapter'
|
1
2
|
require 'rack'
|
2
|
-
require 'webmachine/
|
3
|
+
require 'webmachine/constants'
|
3
4
|
require 'webmachine/headers'
|
4
5
|
require 'webmachine/request'
|
5
6
|
require 'webmachine/response'
|
6
|
-
require 'webmachine/
|
7
|
+
require 'webmachine/version'
|
7
8
|
require 'webmachine/chunked_body'
|
8
9
|
|
9
10
|
module Webmachine
|
10
11
|
module Adapters
|
11
12
|
# A minimal "shim" adapter to allow Webmachine to interface with Rack. The
|
12
13
|
# intention here is to allow Webmachine to run under Rack-compatible
|
13
|
-
# web-servers, like unicorn and pow
|
14
|
-
#
|
14
|
+
# web-servers, like unicorn and pow.
|
15
|
+
# The adapter expects your Webmachine application to be mounted at the root path -
|
16
|
+
# it will NOT allow you to nest your Webmachine application at an arbitrary path
|
17
|
+
# eg. map "/api" { run MyWebmachineAPI }
|
15
18
|
#
|
16
19
|
# To use this adapter, create a config.ru file and populate it like so:
|
17
20
|
#
|
@@ -26,7 +29,7 @@ module Webmachine
|
|
26
29
|
# all "just work".
|
27
30
|
#
|
28
31
|
# And for development or testing your application can be run with Rack's
|
29
|
-
# builtin Server identically to the
|
32
|
+
# builtin Server identically to the WEBrick adapter with:
|
30
33
|
#
|
31
34
|
# MyApplication.run
|
32
35
|
#
|
@@ -34,22 +37,22 @@ module Webmachine
|
|
34
37
|
# Used to override default Rack server options (useful in testing)
|
35
38
|
DEFAULT_OPTIONS = {}
|
36
39
|
|
40
|
+
REQUEST_URI = 'REQUEST_URI'.freeze
|
41
|
+
VERSION_STRING = "#{Webmachine::SERVER_STRING} Rack/#{::Rack.version}".freeze
|
42
|
+
NEWLINE = "\n".freeze
|
43
|
+
|
37
44
|
# Start the Rack adapter
|
38
45
|
def run
|
39
46
|
options = DEFAULT_OPTIONS.merge({
|
40
47
|
:app => self,
|
41
|
-
:Port => configuration.port,
|
42
|
-
:Host => configuration.ip
|
43
|
-
}).merge(configuration.adapter_options)
|
48
|
+
:Port => application.configuration.port,
|
49
|
+
:Host => application.configuration.ip
|
50
|
+
}).merge(application.configuration.adapter_options)
|
44
51
|
|
45
52
|
@server = ::Rack::Server.new(options)
|
46
53
|
@server.start
|
47
54
|
end
|
48
55
|
|
49
|
-
def shutdown
|
50
|
-
@server.server.shutdown if @server
|
51
|
-
end
|
52
|
-
|
53
56
|
# Handles a Rack-based request.
|
54
57
|
# @param [Hash] env the Rack environment
|
55
58
|
def call(env)
|
@@ -57,26 +60,28 @@ module Webmachine
|
|
57
60
|
|
58
61
|
rack_req = ::Rack::Request.new env
|
59
62
|
request = Webmachine::Request.new(rack_req.request_method,
|
60
|
-
|
63
|
+
env[REQUEST_URI],
|
61
64
|
headers,
|
62
65
|
RequestBody.new(rack_req))
|
63
66
|
|
64
67
|
response = Webmachine::Response.new
|
65
|
-
|
68
|
+
application.dispatcher.dispatch(request, response)
|
66
69
|
|
67
|
-
response.headers[
|
70
|
+
response.headers[SERVER] = VERSION_STRING
|
68
71
|
|
69
72
|
rack_status = response.code
|
70
|
-
rack_headers = response.headers.flattened(
|
73
|
+
rack_headers = response.headers.flattened(NEWLINE)
|
71
74
|
rack_body = case response.body
|
72
75
|
when String # Strings are enumerable in ruby 1.8
|
73
76
|
[response.body]
|
74
77
|
else
|
75
|
-
if response.body
|
78
|
+
if (io_body = IO.try_convert(response.body))
|
79
|
+
io_body
|
80
|
+
elsif response.body.respond_to?(:call)
|
76
81
|
Webmachine::ChunkedBody.new(Array(response.body.call))
|
77
82
|
elsif response.body.respond_to?(:each)
|
78
83
|
# This might be an IOEncoder with a Content-Length, which shouldn't be chunked.
|
79
|
-
if response.headers[
|
84
|
+
if response.headers[TRANSFER_ENCODING] == "chunked"
|
80
85
|
Webmachine::ChunkedBody.new(response.body)
|
81
86
|
else
|
82
87
|
response.body
|
@@ -91,6 +96,8 @@ module Webmachine
|
|
91
96
|
end
|
92
97
|
|
93
98
|
class RackResponse
|
99
|
+
ONE_FIVE = '1.5'.freeze
|
100
|
+
|
94
101
|
def initialize(body, status, headers)
|
95
102
|
@body = body
|
96
103
|
@status = status
|
@@ -98,8 +105,8 @@ module Webmachine
|
|
98
105
|
end
|
99
106
|
|
100
107
|
def finish
|
101
|
-
@headers[
|
102
|
-
@headers.delete(
|
108
|
+
@headers[CONTENT_TYPE] ||= TEXT_HTML if rack_release_enforcing_content_type
|
109
|
+
@headers.delete(CONTENT_TYPE) if response_without_body
|
103
110
|
[@status, @headers, @body]
|
104
111
|
end
|
105
112
|
|
@@ -110,7 +117,7 @@ module Webmachine
|
|
110
117
|
end
|
111
118
|
|
112
119
|
def rack_release_enforcing_content_type
|
113
|
-
::Rack.release <
|
120
|
+
::Rack.release < ONE_FIVE
|
114
121
|
end
|
115
122
|
end
|
116
123
|
|
@@ -123,6 +130,15 @@ module Webmachine
|
|
123
130
|
@request = request
|
124
131
|
end
|
125
132
|
|
133
|
+
# Rack Servers differ in the way you can access their request bodys.
|
134
|
+
# While some allow you to directly get a Ruby IO object others don't.
|
135
|
+
# You have to check the methods they expose, like #gets, #read, #each, #rewind and maybe others.
|
136
|
+
# See: https://github.com/rack/rack/blob/rack-1.5/lib/rack/lint.rb#L296
|
137
|
+
# @return [IO] the request body
|
138
|
+
def to_io
|
139
|
+
@request.body
|
140
|
+
end
|
141
|
+
|
126
142
|
# Converts the body to a String so you can work with the entire
|
127
143
|
# thing.
|
128
144
|
# @return [String] the request body as a string
|
@@ -1,40 +1,41 @@
|
|
1
|
+
require 'webmachine/adapter'
|
2
|
+
require 'webmachine/constants'
|
3
|
+
require 'set'
|
1
4
|
require 'reel'
|
2
|
-
require 'webmachine/version'
|
3
5
|
require 'webmachine/headers'
|
4
6
|
require 'webmachine/request'
|
5
7
|
require 'webmachine/response'
|
6
|
-
require 'webmachine/dispatcher'
|
7
|
-
require 'set'
|
8
8
|
|
9
9
|
module Webmachine
|
10
10
|
module Adapters
|
11
11
|
class Reel < Adapter
|
12
12
|
# Used to override default Reel server options (useful in testing)
|
13
13
|
DEFAULT_OPTIONS = {}
|
14
|
-
|
14
|
+
|
15
15
|
def run
|
16
16
|
@options = DEFAULT_OPTIONS.merge({
|
17
|
-
:port => configuration.port,
|
18
|
-
:host => configuration.ip
|
19
|
-
}).merge(configuration.adapter_options)
|
17
|
+
:port => application.configuration.port,
|
18
|
+
:host => application.configuration.ip
|
19
|
+
}).merge(application.configuration.adapter_options)
|
20
20
|
|
21
|
-
if extra_verbs = configuration.adapter_options[:extra_verbs]
|
21
|
+
if extra_verbs = application.configuration.adapter_options[:extra_verbs]
|
22
22
|
@extra_verbs = Set.new(extra_verbs.map(&:to_s).map(&:upcase))
|
23
23
|
else
|
24
24
|
@extra_verbs = Set.new
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
if @options[:ssl]
|
28
|
+
unless @options[:ssl][:cert] && @options[:ssl][:key]
|
29
|
+
raise ArgumentError, 'Certificate or Private key missing for HTTPS Server'
|
30
|
+
end
|
31
|
+
@server = ::Reel::Server::HTTPS.supervise(@options[:host], @options[:port], @options[:ssl], &method(:process))
|
32
|
+
else
|
33
|
+
@server = ::Reel::Server::HTTP.supervise(@options[:host], @options[:port], &method(:process))
|
34
|
+
end
|
28
35
|
|
29
|
-
# FIXME: this will no longer work on Ruby 2.0. We need Celluloid.trap
|
30
|
-
trap("INT") { @server.terminate; exit 0 }
|
31
36
|
Celluloid::Actor.join(@server)
|
32
37
|
end
|
33
38
|
|
34
|
-
def shutdown
|
35
|
-
@server.terminate! if @server
|
36
|
-
end
|
37
|
-
|
38
39
|
def process(connection)
|
39
40
|
connection.each_request do |request|
|
40
41
|
# Users of the adapter can configure a custom WebSocket handler
|
@@ -54,7 +55,7 @@ module Webmachine
|
|
54
55
|
# state machine. Do the "Railsy" thing and handle them like POSTs
|
55
56
|
# with a magical parameter
|
56
57
|
if @extra_verbs.include?(request.method)
|
57
|
-
method =
|
58
|
+
method = POST_METHOD
|
58
59
|
param = "_method=#{request.method}"
|
59
60
|
uri = request_uri(request.url, request.headers, param)
|
60
61
|
else
|
@@ -64,8 +65,9 @@ module Webmachine
|
|
64
65
|
|
65
66
|
wm_headers = Webmachine::Headers[request.headers.dup]
|
66
67
|
wm_request = Webmachine::Request.new(method, uri, wm_headers, request.body)
|
68
|
+
|
67
69
|
wm_response = Webmachine::Response.new
|
68
|
-
|
70
|
+
application.dispatcher.dispatch(wm_request, wm_response)
|
69
71
|
|
70
72
|
fixup_headers(wm_response)
|
71
73
|
fixup_callable_encoder(wm_response)
|
@@ -77,13 +79,9 @@ module Webmachine
|
|
77
79
|
end
|
78
80
|
|
79
81
|
def request_uri(path, headers, extra_query_params = nil)
|
80
|
-
host_parts = headers.fetch('Host').split(':')
|
81
82
|
path_parts = path.split('?')
|
82
|
-
|
83
|
-
uri_hash =
|
84
|
-
|
85
|
-
uri_hash[:port] = host_parts.last.to_i if host_parts.length == 2
|
86
|
-
uri_hash[:query] = path_parts.last if path_parts.length == 2
|
83
|
+
uri_hash = {path: path_parts.first}
|
84
|
+
uri_hash[:query] = path_parts.last if path_parts.length == 2
|
87
85
|
|
88
86
|
if extra_query_params
|
89
87
|
if uri_hash[:query]
|