Permalink
Fetching contributors…
Cannot retrieve contributors at this time
114 lines (96 sloc) 3.73 KB
require 'webmachine/adapter'
require 'webmachine/constants'
require 'set'
require 'celluloid/current'
require 'reel'
require 'webmachine/headers'
require 'webmachine/request'
require 'webmachine/response'
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_METHOD
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