lib/lita/rack_app.rb in lita-2.7.2 vs lib/lita/rack_app.rb in lita-3.0.0
- old
+ new
@@ -1,114 +1,36 @@
module Lita
# A +Rack+ application to serve routes registered by handlers.
class RackApp
- # The character that separates the pieces of a URL's path component.
- PATH_SEPARATOR = "/"
-
- # A +Struct+ representing a route's destination handler and method name.
- RouteMapping = Struct.new(:handler, :method_name)
-
- # All registered paths. Used to respond to HEAD requests.
- # @return [Array<String>] The array of paths.
- attr_reader :all_paths
-
# The currently running robot.
# @return [Lita::Robot] The robot.
attr_reader :robot
- # A hash mapping HTTP request methods and paths to handlers and methods.
- # @return [Hash] The mapping.
- attr_reader :routes
+ # An +HttpRouter+ used for dispatch.
+ # @return [HttpRouter] The router.
+ attr_reader :router
# @param robot [Lita::Robot] The currently running robot.
def initialize(robot)
@robot = robot
- @routes = Hash.new { |h, k| h[k] = {} }
+ @router = HttpRouter.new
compile
end
+ # Entry point for Lita's HTTP routes. Invokes the Rack application.
+ # @param env [Hash] A Rack environment.
+ # @return [void]
def call(env)
- request = Rack::Request.new(env)
- mapping = get_mapping(request)
-
- if mapping
- serve(mapping, request)
- elsif request.head? && all_paths.include?(request.path)
- Lita.logger.info "HTTP HEAD #{request.path} was a 204."
- [204, {}, []]
- else
- Lita.logger.info <<-LOG.chomp
-HTTP #{request.request_method} #{request.path} was a 404.
-LOG
- [404, {}, ["Route not found."]]
- end
+ env["lita.robot"] = robot
+ router.call(env)
end
- # Creates a +Rack+ application from the compiled routes.
- # @return [Rack::Builder] The +Rack+ application.
- def to_app
- app = Rack::Builder.new
- app.run(self)
- app
- end
-
private
- # Collect all registered paths. Used for responding to HEAD requests.
- def collect_paths
- @all_paths = routes.values.map { |hash| hash.keys.first }.uniq
- end
-
- # Registers routes in the route mapping for each handler's defined routes.
+ # Registers routes in the router for each handler's defined routes.
def compile
Lita.handlers.each do |handler|
- handler.http_routes.each { |route| register_route(handler, route) }
+ handler.http_routes.each { |route| router.add_route(route) }
end
- collect_paths
- end
-
- def get_mapping(request)
- routes[request.request_method][request.path]
- end
-
- # Registers a route.
- def register_route(handler, route)
- cleaned_path = clean_path(route.path)
-
- if @routes[route.http_method][cleaned_path]
- Lita.logger.fatal <<-ERR.chomp
-#{handler.name} attempted to register an HTTP route that was already \
-registered: #{route.http_method} "#{cleaned_path}"
-ERR
- abort
- end
-
- Lita.logger.debug <<-LOG.chomp
-Registering HTTP route: #{route.http_method} #{cleaned_path} to \
-#{handler}##{route.method_name}.
-LOG
- @routes[route.http_method][cleaned_path] = RouteMapping.new(
- handler,
- route.method_name
- )
- end
-
- def serve(mapping, request)
- Lita.logger.info <<-LOG.chomp
-Routing HTTP #{request.request_method} #{request.path} to \
-#{mapping.handler}##{mapping.method_name}.
-LOG
- response = Rack::Response.new
- instance = mapping.handler.new(robot)
- instance.public_send(mapping.method_name, request, response)
- response.finish
- end
-
- # Ensures that paths begin with one slash and do not end with one.
- def clean_path(path)
- path.strip!
- path.chop! while path.end_with?(PATH_SEPARATOR)
- path = path[1..-1] while path.start_with?(PATH_SEPARATOR)
- "/#{path}"
end
end
end