lib/hanami/action/rack.rb in hanami-controller-1.0.0.beta1 vs lib/hanami/action/rack.rb in hanami-controller-1.0.0.beta2
- old
+ new
@@ -8,16 +8,40 @@
module Action
# Rack integration API
#
# @since 0.1.0
module Rack
+ # Rack SPEC response code
+ #
+ # @since 1.0.0.beta2
+ # @api private
+ RESPONSE_CODE = 0
+
+ # Rack SPEC response headers
+ #
+ # @since 1.0.0.beta2
+ # @api private
+ RESPONSE_HEADERS = 1
+
+ # Rack SPEC response body
+ #
+ # @since 1.0.0.beta2
+ # @api private
+ RESPONSE_BODY = 2
+
# The default HTTP response code
#
# @since 0.1.0
# @api private
DEFAULT_RESPONSE_CODE = 200
+ # Not Found
+ #
+ # @since 1.0.0.beta2
+ # @api private
+ NOT_FOUND = 404
+
# The default Rack response body
#
# @since 0.1.0
# @api private
DEFAULT_RESPONSE_BODY = []
@@ -34,10 +58,23 @@
#
# @since 0.3.2
# @api private
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
+ # The Content-Length HTTP header
+ #
+ # @since 1.0.0.beta2
+ # @api private
+ CONTENT_LENGTH = 'Content-Length'.freeze
+
+ # The non-standard HTTP header to pass the control over when a resource
+ # cannot be found by the current endpoint
+ #
+ # @since 1.0.0.beta2
+ # @api private
+ X_CASCADE = 'X-Cascade'.freeze
+
# HEAD request
#
# @since 0.3.2
# @api private
HEAD = 'HEAD'.freeze
@@ -255,10 +292,11 @@
body = Array(body) unless body.respond_to?(:each)
@_body = body
end
# Send a file as response.
+ # <tt>This method only sends files from the public directory</tt>
#
# It automatically handle the following cases:
#
# * <tt>Content-Type</tt> and <tt>Content-Length</tt>
# * File Not found (returns a 404)
@@ -280,15 +318,43 @@
# # ...
# send_file Pathname.new('path/to/file')
# end
# end
def send_file(path)
- result = File.new(path, self.class.configuration.public_directory).call(@_env)
- headers.merge!(result[1])
- halt result[0], result[2]
+ _send_file(
+ File.new(path, self.class.configuration.public_directory).call(@_env)
+ )
end
+ # Send a file as response from anywhere in the file system.
+ #
+ # @see Hanami::Action::Rack#send_file
+ #
+ # @param path [String, Pathname] path to the file to be sent
+ # @return [void]
+ #
+ # @since 1.0.0.beta2
+ #
+ # @example
+ # require 'hanami/controller'
+ #
+ # class Show
+ # include Hanami::Action
+ #
+ # def call(params)
+ # # ...
+ # unsafe_send_file Pathname.new('/tmp/path/to/file')
+ # end
+ # end
+ def unsafe_send_file(path)
+ directory = self.class.configuration.root_directory if Pathname.new(path).relative?
+
+ _send_file(
+ File.new(path, directory).call(@_env)
+ )
+ end
+
# Check if the current request is a HEAD
#
# @return [TrueClass,FalseClass] the result of the check
#
# @since 0.3.2
@@ -300,9 +366,23 @@
#
# @api private
# @since 0.4.4
def request_method
@_env[REQUEST_METHOD]
+ end
+
+ # @since 1.0.0.beta2
+ # @api private
+ def _send_file(response)
+ headers.merge!(response[RESPONSE_HEADERS])
+
+ if response[RESPONSE_CODE] == NOT_FOUND
+ headers.delete(X_CASCADE)
+ headers.delete(CONTENT_LENGTH)
+ halt NOT_FOUND
+ else
+ halt response[RESPONSE_CODE], response[RESPONSE_BODY]
+ end
end
end
end
end