class Merb::Request
Constants
- METHODS
Attributes
:api: private
:api: private
:api: private
Public Class Methods
Memoizes the new request object into env so we can memoize things into ivars in the request
Parameters¶ ↑
- env<Hash>
-
A rack environment
- *args<Array>
-
Other arguments passed to the superclass
Returns¶ ↑
- Merb::Request
-
The new Merb::Request
:api: public
# File lib/merb-core/dispatch/request.rb, line 53 def self.new(env, *args) if self == Merb::Request env["merb.request"] ||= super else super end end
Public Instance Methods
Notes¶ ↑
Processes the return value of a deferred router block and returns the current route params for the current request evaluation
:api: private
# File lib/merb-core/dispatch/request.rb, line 147 def _process_block_return(retval) # If the return value is an array, then it is a redirect # so we must set the request as a redirect and extract # the redirect params and return it as a hash so that the # dispatcher can handle it matched! if retval.is_a?(Array) retval end
Returns the controller object for initialization and dispatching the request.
Returns¶ ↑
- Class
-
The controller class matching the routed request,
e.g. Posts.
:api: private
# File lib/merb-core/dispatch/request.rb, line 69 def controller unless params[:controller] raise ControllerExceptions::NotFound, "Route matched, but route did not specify a controller.\n" + "Did you forgot to add :controller => \"people\" or :controller " + "segment to route definition?\nHere is what's specified:\n" + route.inspect end path = [params[:namespace], params[:controller]].compact.join(Merb::Const::SLASH) controller = path.snake_case.to_const_string begin Object.full_const_get(controller) rescue NameError => e msg = "Controller class not found for controller `#{path}'" Merb.logger.warn!(msg) raise ControllerExceptions::NotFound, msg end end
Parameters¶ ↑
- tld_length<Fixnum>
-
Number of domains levels to inlclude in the top level domain. Defaults to 1.
Returns¶ ↑
- String
-
The full domain name without the port number.
:api: public
# File lib/merb-core/dispatch/request.rb, line 610 def domain(tld_length = 1) host.split(Merb::Const::DOT).last(1 + tld_length).join(Merb::Const::DOT).sub(/:\d+$/,'') end
# File lib/merb-core/dispatch/request.rb, line 89 def exceptions env["merb.exceptions"] end
Notes¶ ↑
Find route using requested URI and merges route parameters (:action, :controller and named segments) into request params hash.
:api: private
# File lib/merb-core/dispatch/request.rb, line 136 def find_route! @route, @route_params = Merb::Router.route_for(self) params.merge! @route_params if @route_params.is_a?(Hash) end
Handles request routing and action dispatch
@return [Array[Integer, Hash, each]] A Rack response
@api private
# File lib/merb-core/dispatch/dispatcher.rb, line 46 def handle @start = env["merb.request_start"] = Time.now Merb.logger.info { "Started request handling: #{start.to_s}" } find_route! return rack_response if handled? klass = controller unless klass < Controller raise NotFound, "Controller '#{klass}' not found.\n" "If Merb tries to find a controller for static files, " "you may need to check your Rackup file, see the Problems " "section at: http://wiki.merbivore.com/pages/rack-middleware" end Merb.logger.debug { "Routed to: #{klass::_filter_params(params).inspect}" } if klass.abstract? raise NotFound, "The '#{klass}' controller has no public actions" end dispatch_action(klass, params[:action]) rescue Object => exception dispatch_exception(exception) end
Sets the request as matched. This will abort evaluating any further deferred procs.
:api: private
# File lib/merb-core/dispatch/request.rb, line 160 def matched! @matched = true end
Checks whether or not the request has been matched to a route.
:api: private
# File lib/merb-core/dispatch/request.rb, line 167 def matched? @matched end
Returns¶ ↑
- Symbol
-
The name of the request method, e.g. :get.
Notes¶ ↑
If the method is post, then the blocks specified in http_method_overrides will be checked for the masquerading method. The block will get the controller yielded to it. The first matching workaround wins. To disable this behavior, set http_method_overrides = []
:api: public
# File lib/merb-core/dispatch/request.rb, line 105 def method @method ||= begin request_method = @env[Merb::Const::REQUEST_METHOD].downcase.to_sym case request_method when :get, :head, :put, :delete, :options request_method when :post m = nil self.class.http_method_overrides.each do |o| m ||= o.call(self); break if m end m.downcase! if m METHODS.include?(m) ? m.to_sym : :post else raise "Unknown REQUEST_METHOD: #{@env[Merb::Const::REQUEST_METHOD]}" end end end
Returns¶ ↑
- Mash
-
All request parameters.
Notes¶ ↑
The order of precedence for the params is XML, JSON, multipart, body and request string.
:api: public
# File lib/merb-core/dispatch/request.rb, line 310 def params @params ||= begin h = body_and_query_params.merge(route_params) h.merge!(multipart_params) if self.class.parse_multipart_params && multipart_params h.merge!(json_params) if self.class.parse_json_params && json_params h.merge!(xml_params) if self.class.parse_xml_params && xml_params h end end
Returns¶ ↑
- String
-
The URI without the query string. Strips trailing “/” and reduces duplicate “/” to a single “/”.
:api: public
# File lib/merb-core/dispatch/request.rb, line 554 def path # Merb::Const::SLASH is / # Merb::Const::QUESTION_MARK is ? path = (uri.empty? ? Merb::Const::SLASH : uri.split(Merb::Const::QUESTION_MARK).first).squeeze(Merb::Const::SLASH) path = path[0..-2] if (path[-1] == ?/) && path.size > 1 path end
Returns¶ ↑
- (Array, Hash)
-
the route params for the matched route.
Notes¶ ↑
If the response is an Array then it is considered a direct Rack response to be sent back as a response. Otherwise, the #route_params is a Hash with routing data (controller, action, et al).
:api: private
# File lib/merb-core/dispatch/request.rb, line 180 def rack_response @route_params end
Returns¶ ↑
- String
-
The remote IP address.
:api: public
# File lib/merb-core/dispatch/request.rb, line 364 def remote_ip return @env[Merb::Const::HTTP_CLIENT_IP] if @env.include?(Merb::Const::HTTP_CLIENT_IP) if @env.include?(Merb::Const::HTTP_X_FORWARDED_FOR) then remote_ips = @env[Merb::Const::HTTP_X_FORWARDED_FOR].split(',').reject do |ip| ip =~ Merb::Const::LOCAL_IP_REGEXP end return remote_ips.first.strip unless remote_ips.empty? end return @env[Merb::Const::REMOTE_ADDR] end
Parameters¶ ↑
- tld_length<Fixnum>
-
Number of domains levels to inlclude in the top level domain. Defaults to 1.
Returns¶ ↑
- Array
-
All the subdomain parts of the host.
:api: public
# File lib/merb-core/dispatch/request.rb, line 596 def subdomains(tld_length = 1) parts = host.split(Merb::Const::DOT) parts[0..-(tld_length+2)] end
Private Instance Methods
Returns¶ ↑
- Mash
-
The parameters gathered from the query string and the request body, with parameters in the body taking precedence.
:api: private
# File lib/merb-core/dispatch/request.rb, line 231 def body_and_query_params # ^-- FIXME a better name for this method @body_and_query_params ||= begin h = query_params h.merge!(body_params) if body_params h.to_mash end end
Parameters passed in the body of the request. Ajax calls from prototype.js and other libraries pass content this way.
Returns¶ ↑
- Hash
-
The parameters passed in the body.
:api: private
# File lib/merb-core/dispatch/request.rb, line 217 def body_params @body_params ||= begin if content_type && content_type.match(Merb::Const::FORM_URL_ENCODED_REGEXP) # or content_type.nil? Merb::Parse.query(raw_post) end end end
Setup the controller and call the chosen action
@param klass [Merb::Controller] The controller class to dispatch to. @param action [Symbol] The action to dispatch. @param status [Integer] The status code to respond with.
@return [Array[Integer, Hash, each]] A Rack response
@api private
# File lib/merb-core/dispatch/dispatcher.rb, line 84 def dispatch_action(klass, action_name, status=200) @env["merb.status"] = status @env["merb.action_name"] = action_name if Dispatcher.use_mutex @@mutex.synchronize { klass.call(env) } else klass.call(env) end end
Re-route the request to the Exception controller if it is available
You can handle exceptions by implementing actions for specific exceptions such as not_found or for entire classes of exceptions such as client_error. You can also implement handlers for exceptions outside the Merb exception hierarchy (e.g. StandardError is caught in standard_error).
@param exception [Object] The exception object that was created when
trying to dispatch the original controller.
@return [Array[Integer, Hash, each]] A Rack response
@api private
# File lib/merb-core/dispatch/dispatcher.rb, line 109 def dispatch_exception(exception) if(exception.is_a?(Merb::ControllerExceptions::Base) && !exception.is_a?(Merb::ControllerExceptions::ServerError)) Merb.logger.info(Merb.exception(exception)) else Merb.logger.error(Merb.exception(exception)) end exceptions = env["merb.exceptions"] = [exception] begin e = exceptions.first if action_name = e.action_name dispatch_action(Exceptions, action_name, e.class.status) else dispatch_action(Dispatcher::DefaultException, :index, e.class.status) end rescue Object => dispatch_issue if e.same?(dispatch_issue) || exceptions.size > 5 dispatch_action(Dispatcher::DefaultException, :index, e.class.status) else Merb.logger.error("Dispatching #{e.class} raised another error.") Merb.logger.error(Merb.exception(dispatch_issue)) exceptions.unshift dispatch_issue retry end end end
Returns¶ ↑
- Hash
-
Parameters from body if this is a JSON request.
Notes¶ ↑
If the JSON object parses as a Hash, it will be merged with the parameters hash. If it parses to anything else (such as an Array, or if it inflates to an Object) it will be accessible via the inflated_object parameter.
:api: private
# File lib/merb-core/dispatch/request.rb, line 274 def json_params @json_params ||= begin if Merb::Const::JSON_MIME_TYPE_REGEXP.match(content_type) begin jobj = JSON.parse(raw_post) jobj = jobj.to_mash if jobj.is_a?(Hash) rescue JSON::ParserError jobj = Mash.new end jobj.is_a?(Hash) ? jobj : { :inflated_object => jobj } end end end
Raises¶ ↑
- ControllerExceptions::MultiPartParseError
-
Unable to parse the multipart form data.
Returns¶ ↑
- Hash
-
The parsed multipart parameters.
:api: private
# File lib/merb-core/dispatch/request.rb, line 248 def multipart_params @multipart_params ||= begin # if the content-type is multipart # parse the multipart. Otherwise return {} if (Merb::Const::MULTIPART_REGEXP =~ content_type) Merb::Parse.multipart(@body, $1, content_length) else {} end rescue ControllerExceptions::MultiPartParseError => e @multipart_params = {} raise e end end