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:
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.
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 |