Parent

Methods

Class/Module Index [+]

Quicksearch

Rack::MatrixParams

Public Class Methods

new(app) click to toggle source
# File lib/sinatra/rack_matrix_params.rb, line 23
def initialize(app)
  @app = app
end

Public Instance Methods

call(env) click to toggle source

This will allow to use 'matrix' params in requests, like:

example.com/library;section=nw/books;topic=money;binding=hardcover

Will result in this params matrix:

> params['section'] = 'nw'

> params['topic'] = 'money'

> params['binding'] = 'hardcover'

All HTTP methods are supported, in case of POST they will be passed as a regular <form> parameters.

# File lib/sinatra/rack_matrix_params.rb, line 40
def call(env)
  # Copy PATH_INFO to REQUEST_URI if Rack::Test
  env['REQUEST_URI'] = env['PATH_INFO'] if env['rack.test']
  env['REQUEST_PATH'] = env['PATH_INFO'] if env['rack.test']

  # Split URI to components and then extract ;var=value pairs
  uri_components = env['REQUEST_URI'].split('/')
  matrix_params = {}
  uri_components.each do |component|
    sub_components, value = component.split(/\;(\w+)\=/), nil
    next unless sub_components.first  # Skip subcomponent if it's empty (usually /)
    while param=sub_components.pop do
      if value
        matrix_params[sub_components.first] ||= {}
        matrix_params[sub_components.first].merge!(
                                                   param => value
                                                   )
        value=nil
        next
      else
        value = param.gsub(/\?.*$/, '')
      end
    end
  end

  # Two things need to happen to make matrix params work:
  #     (1) the parameters need to be appended to the 'normal' params
  #         for the request. 'Normal' really depends on the content
  #         type of the request, which does not seem accessible from
  #         Middleware, so we use the existence of
  #         rack.request.form_hash in the environment to distinguish
  #         between basic and application/x-www-form-urlencoded
  #         requests
  #     (2) the parameters need to be stripped from the appropriate
  #         path related env variables, so that request dispatching
  #         does not trip over them

  # (1) Rewrite current path by stripping all matrix params from it
  if env['REQUEST_PATH'] == '/'
    env['REQUEST_URI'] = env['REQUEST_PATH']
    env['REQUEST_PATH'] = env['PATH_INFO']
  end

  # This is needed for OpenShift deployment / Passenger
  if env['REQUEST_PATH']
    env['REQUEST_PATH'] = env['REQUEST_PATH'].gsub(/;([^\/]*)/, '').gsub(/\?(.*)$/, '')
    env['PATH_INFO'] = env['REQUEST_PATH']
  end

  # (2) Append the matrix params to the 'normal' request params
  # FIXME: Make this work for multipart/form-data
  if env['rack.request.form_hash']
    # application/x-www-form-urlencoded, most likely a POST
    env['rack.request.form_hash'].merge!(matrix_params)
  else
    # For other methods it's more complicated
    if env['REQUEST_METHOD']!='POST' and not matrix_params.keys.empty?
      env['QUERY_STRING'].gsub!(/;([^\/]*)/, '')
      new_params = matrix_params.collect do |component, params|
        params.collect { |k,v| "#{component}[#{k}]=#{CGI::escape(v.to_s)}" }
      end.flatten
      # Add matrix params as a regular GET params
      env['QUERY_STRING'] += '&' if not env['QUERY_STRING'].empty?
      env['QUERY_STRING'] += "#{new_params.join('&')}"
    end
  end
  @app.call(env)
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.