/
reel.rb
112 lines (95 loc) · 3.69 KB
/
reel.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
require 'reel'
require 'webmachine/version'
require 'webmachine/headers'
require 'webmachine/request'
require 'webmachine/response'
require 'webmachine/dispatcher'
require 'set'
module Webmachine
module Adapters
class Reel < Adapter
# Used to override default Reel server options (useful in testing)
DEFAULT_OPTIONS = {}
def run
@options = DEFAULT_OPTIONS.merge({
:port => application.configuration.port,
:host => application.configuration.ip
}).merge(application.configuration.adapter_options)
if extra_verbs = application.configuration.adapter_options[:extra_verbs]
@extra_verbs = Set.new(extra_verbs.map(&:to_s).map(&:upcase))
else
@extra_verbs = Set.new
end
if @options[:ssl]
unless @options[:ssl][:cert] && @options[:ssl][:key]
raise ArgumentError, 'Certificate or Private key missing for HTTPS Server'
end
@server = ::Reel::Server::HTTPS.supervise(@options[:host], @options[:port], @options[:ssl], &method(:process))
else
@server = ::Reel::Server::HTTP.supervise(@options[:host], @options[:port], &method(:process))
end
Celluloid::Actor.join(@server)
end
def process(connection)
connection.each_request do |request|
# Users of the adapter can configure a custom WebSocket handler
if request.websocket?
if handler = @options[:websocket_handler]
handler.call(request.websocket)
else
# Pretend we don't know anything about the WebSocket protocol
# FIXME: This isn't strictly what RFC 6455 would have us do
request.respond :bad_request, "WebSockets not supported"
end
next
end
# Optional support for e.g. WebDAV verbs not included in Webmachine's
# state machine. Do the "Railsy" thing and handle them like POSTs
# with a magical parameter
if @extra_verbs.include?(request.method)
method = "POST"
param = "_method=#{request.method}"
uri = request_uri(request.url, request.headers, param)
else
method = request.method
uri = request_uri(request.url, request.headers)
end
wm_headers = Webmachine::Headers[request.headers.dup]
wm_request = Webmachine::Request.new(method, uri, wm_headers, request.body)
wm_response = Webmachine::Response.new
application.dispatcher.dispatch(wm_request, wm_response)
fixup_headers(wm_response)
fixup_callable_encoder(wm_response)
request.respond ::Reel::Response.new(wm_response.code,
wm_response.headers,
wm_response.body)
end
end
def request_uri(path, headers, extra_query_params = nil)
path_parts = path.split('?')
uri_hash = {path: path_parts.first}
uri_hash[:query] = path_parts.last if path_parts.length == 2
if extra_query_params
if uri_hash[:query]
uri_hash[:query] << "&#{extra_query_params}"
else
uri_hash[:query] = extra_query_params
end
end
URI::HTTP.build(uri_hash)
end
def fixup_headers(response)
response.headers.each do |key, value|
if value.is_a?(Array)
response.headers[key] = value.join(", ")
end
end
end
def fixup_callable_encoder(response)
if response.body.is_a?(Streaming::CallableEncoder)
response.body = [response.body.call]
end
end
end
end
end