class Merb::Request

Constants

METHODS

Attributes

env[RW]

:api: private

route[RW]

:api: private

route_params[R]

:api: private

start[R]

Public Class Methods

new(rack_env) click to toggle source

Initialize the request object.

Parameters

http_request<~params:~[], ~body:IO>

An object like an HTTP Request.

:api: private

# File lib/merb-core/dispatch/request.rb, line 36
def initialize(rack_env)      
  @env  = rack_env
  @body = rack_env[Merb::Const::RACK_INPUT]
  @route_params = {}
end
new(env, *args) click to toggle source

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

Calls superclass method
# 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

_process_block_return(retval) click to toggle source

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
accept() click to toggle source

Returns

String

The accepted response types. Defaults to “/”.

:api: private

# File lib/merb-core/dispatch/request.rb, line 512
def accept
  @env[Merb::Const::HTTP_ACCEPT].blank? ? "*/*" : @env[Merb::Const::HTTP_ACCEPT]
end
accept_charset() click to toggle source

Returns

String

The accepted character sets.

:api: public

# File lib/merb-core/dispatch/request.rb, line 488
def accept_charset
  @env[Merb::Const::HTTP_ACCEPT_CHARSET]
end
accept_encoding() click to toggle source

Returns

String

The accepted encodings.

:api: private

# File lib/merb-core/dispatch/request.rb, line 440
def accept_encoding
  @env[Merb::Const::HTTP_ACCEPT_ENCODING]
end
accept_language() click to toggle source

Returns

String

The accepted language.

:api: public

# File lib/merb-core/dispatch/request.rb, line 464
def accept_language
  @env[Merb::Const::HTTP_ACCEPT_LANGUAGE]
end
ajax?()
Alias for: xml_http_request?
cache_control() click to toggle source

Returns

String

HTTP cache control.

:api: public

# File lib/merb-core/dispatch/request.rb, line 456
def cache_control
  @env[Merb::Const::HTTP_CACHE_CONTROL]
end
connection() click to toggle source

Returns

String

The HTTP connection.

:api: private

# File lib/merb-core/dispatch/request.rb, line 520
def connection
  @env[Merb::Const::HTTP_CONNECTION]
end
content_length() click to toggle source

Returns

Fixnum

The request content length.

:api: public

# File lib/merb-core/dispatch/request.rb, line 544
def content_length
  @content_length ||= @env[Merb::Const::CONTENT_LENGTH].to_i
end
content_type() click to toggle source

Returns

String

The request content type.

:api: private

# File lib/merb-core/dispatch/request.rb, line 536
def content_type
  @env[Merb::Const::UPCASE_CONTENT_TYPE]
end
controller() click to toggle source

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
domain(tld_length = 1) click to toggle source

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
exceptions() click to toggle source
# File lib/merb-core/dispatch/request.rb, line 89
def exceptions
  env["merb.exceptions"]
end
find_route!() click to toggle source

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
full_uri() click to toggle source

Returns

String

The full URI, including protocol and host

:api: public

# File lib/merb-core/dispatch/request.rb, line 408
def full_uri
  protocol + "://" + host + uri
end
gateway() click to toggle source

Returns

String

The gateway.

:api: public

# File lib/merb-core/dispatch/request.rb, line 504
def gateway
  @env[Merb::Const::GATEWAY_INTERFACE]
end
handle() click to toggle source

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
handled?() click to toggle source

If @route_params is an Array, then it will be the rack response. In this case, the request is considered handled.

Returns

Boolean

true if @route_params is an Array, false otherwise.

:api: private

# File lib/merb-core/dispatch/request.rb, line 191
def handled?
  @route_params.is_a?(Array)
end
host() click to toggle source

Returns

String

The full hostname including the port.

:api: public

# File lib/merb-core/dispatch/request.rb, line 582
def host
  @env[Merb::Const::HTTP_X_FORWARDED_HOST] || @env[Merb::Const::HTTP_HOST] ||
    @env[Merb::Const::SERVER_NAME]
end
if_modified_since() click to toggle source

Returns

Value of If-Modified-Since request header.

:api: private

# File lib/merb-core/dispatch/request.rb, line 626
def if_modified_since
  if time = @env[Merb::Const::HTTP_IF_MODIFIED_SINCE]
    Time.rfc2822(time)
  end
end
if_none_match() click to toggle source

Returns

Value of If-None-Match request header.

:api: private

# File lib/merb-core/dispatch/request.rb, line 618
def if_none_match
  @env[Merb::Const::HTTP_IF_NONE_MATCH]
end
keep_alive() click to toggle source

Returns

String

Value of HTTP_KEEP_ALIVE.

:api: public

# File lib/merb-core/dispatch/request.rb, line 480
def keep_alive
  @env[Merb::Const::HTTP_KEEP_ALIVE]
end
matched!() click to toggle source

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
matched?() click to toggle source

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
message() click to toggle source

Returns

String

Returns the redirect message Base64 unencoded.

:api: public

# File lib/merb-core/dispatch/request.rb, line 324
def message
  return {} unless params[:_message]
  begin
    Marshal.load(params[:_message].unpack("m").first)
  rescue ArgumentError, TypeError
    {}
  end
end
method() click to toggle source

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
params() click to toggle source

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
path() click to toggle source

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
path_info() click to toggle source

Returns

String

The path info.

:api: public

# File lib/merb-core/dispatch/request.rb, line 566
def path_info
  @path_info ||= Merb::Parse.unescape(@env[Merb::Const::PATH_INFO])
end
port() click to toggle source

Returns

Fixnum

The server port.

:api: public

# File lib/merb-core/dispatch/request.rb, line 574
def port
  @env[Merb::Const::SERVER_PORT].to_i
end
protocol() click to toggle source

Returns

String

The protocol, i.e. either “https” or “http” depending on the HTTPS header.

:api: public

# File lib/merb-core/dispatch/request.rb, line 384
def protocol
  ssl? ? Merb::Const::HTTPS : Merb::Const::HTTP
end
query_string() click to toggle source

Returns

String

The query string.

:api: private

# File lib/merb-core/dispatch/request.rb, line 528
def query_string
  @env[Merb::Const::QUERY_STRING]
end
rack_response() click to toggle source

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
raw_post() click to toggle source

Returns

String

The raw post.

:api: private

# File lib/merb-core/dispatch/request.rb, line 345
def raw_post
  @body.rewind if @body.respond_to?(:rewind)
  @raw_post ||= @body.read
end
referer() click to toggle source

Returns

String

The HTTP referer.

:api: public

# File lib/merb-core/dispatch/request.rb, line 400
def referer
  @env[Merb::Const::HTTP_REFERER]
end
remote_ip() click to toggle source

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
reset_params!() click to toggle source

Notes

Resets the params to a nil value.

:api: private

# File lib/merb-core/dispatch/request.rb, line 337
def reset_params!
  @params = nil
end
script_name() click to toggle source

Returns

String

The script name.

:api: public

# File lib/merb-core/dispatch/request.rb, line 448
def script_name
  @env[Merb::Const::SCRIPT_NAME]
end
server_name() click to toggle source

Returns

String

The server name.

:api: public

# File lib/merb-core/dispatch/request.rb, line 432
def server_name
  @env[Merb::Const::SERVER_NAME]
end
server_software() click to toggle source

Returns

String

The server software.

:api: public

# File lib/merb-core/dispatch/request.rb, line 472
def server_software
  @env[Merb::Const::SERVER_SOFTWARE]
end
ssl?() click to toggle source

Returns

Boolean:

True if the request is an SSL request.

:api: public

# File lib/merb-core/dispatch/request.rb, line 392
def ssl?
  @env[Merb::Const::UPCASE_HTTPS] == 'on' || @env[Merb::Const::HTTP_X_FORWARDED_PROTO] == Merb::Const::HTTPS
end
subdomains(tld_length = 1) click to toggle source

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
uri() click to toggle source

Returns

String

The request URI.

:api: public

# File lib/merb-core/dispatch/request.rb, line 416
def uri
  @env[Merb::Const::REQUEST_PATH] || @env[Merb::Const::REQUEST_URI] || path_info
end
user_agent() click to toggle source

Returns

String

The HTTP user agent.

:api: public

# File lib/merb-core/dispatch/request.rb, line 424
def user_agent
  @env[Merb::Const::HTTP_USER_AGENT]
end
version() click to toggle source

Returns

String

The HTTP version

:api: private

# File lib/merb-core/dispatch/request.rb, line 496
def version
  @env[Merb::Const::HTTP_VERSION]
end
xhr?()
Alias for: xml_http_request?
xml_http_request?() click to toggle source

Returns

Boolean

If the request is an XML HTTP request.

:api: public

# File lib/merb-core/dispatch/request.rb, line 354
def xml_http_request?
  not Merb::Const::XML_HTTP_REQUEST_REGEXP.match(@env[Merb::Const::HTTP_X_REQUESTED_WITH]).nil?
end
Also aliased as: xhr?, ajax?

Private Instance Methods

body_and_query_params() click to toggle source

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
body_params() click to toggle source

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
dispatch_action(klass, action_name, status=200) click to toggle source

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
dispatch_exception(exception) click to toggle source

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
json_params() click to toggle source

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
multipart_params() click to toggle source

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
query_params() click to toggle source

Returns

Hash

Parameters passed from the URL like ?blah=hello.

:api: private

# File lib/merb-core/dispatch/request.rb, line 206
def query_params
  @query_params ||= Merb::Parse.query(query_string || '')
end
xml_params() click to toggle source

Returns

Hash

Parameters from body if this is an XML request.

:api: private

# File lib/merb-core/dispatch/request.rb, line 292
def xml_params
  @xml_params ||= begin
    if Merb::Const::XML_MIME_TYPE_REGEXP.match(content_type)
      Hash.from_xml(raw_post) rescue Mash.new
    end
  end
end