Class: Rack::MatrixParams
- Inherits:
-
Object
- Object
- Rack::MatrixParams
- Defined in:
- lib/sinatra/rack_matrix_params.rb
Instance Method Summary collapse
-
#call(env) ⇒ Object
This will allow to use 'matrix' params in requests, like:.
-
#initialize(app) ⇒ MatrixParams
constructor
A new instance of MatrixParams.
Constructor Details
#initialize(app) ⇒ MatrixParams
Returns a new instance of MatrixParams.
23 24 25 |
# File 'lib/sinatra/rack_matrix_params.rb', line 23 def initialize(app) @app = app end |
Instance Method Details
#call(env) ⇒ Object
This will allow to use 'matrix' params in requests, like:
http://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
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/sinatra/rack_matrix_params.rb', line 39 def call(env) # This ugly hack should fix the issue with Rack::Test where # these two variables are empty and Rack::Test will always # return 404. # if env['rack.test'] env['REQUEST_URI'] = env['PATH_INFO'] env['REQUEST_PATH'] = env['PATH_INFO'] end # Split URI to components and then extract ;var=value pairs matrix_params = {} uri_components = (env['rack.test'] ? env['PATH_INFO'] : env['REQUEST_URI']).split('/') 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 ['REQUEST_PATH', 'REQUEST_URI', 'PATH_INFO'].select { |k| env[k] }.each do |k| env[k] = env[k].remove_matrix_params 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'] = 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 |