21

Using the following Sinatra app

get '/app' do
  content_type :json
  {"params" => params}.to_json
end

Invoking:

/app?param1=one&param2=two&param2=alt

Gives the following result:

{"params":{"param1":"one","param2":"alt"}}

Params has only two keys, param1 & param2.

I understand Sinatra is setting params as a hash, but it does not represent all of the URL request.

Is there a way in Sinatra to get a list of all URL parameters sent in the request?

necrobious
  • 305
  • 1
  • 3
  • 8

4 Answers4

22

Any request in rack

get '/app' do
  params = request.env['rack.request.query_hash']
end
unclepotap
  • 321
  • 2
  • 3
17

I believe by default params of the same name will be overwritten by the param that was processed last.

You could either setup params2 as an array of sorts

...&param2[]=two&param2[]=alt

Or parse the query string vs the Sinatra provided params hash.

nowk
  • 32,822
  • 2
  • 35
  • 40
11

kwon suggests to parse the query string. You can use CGI to parse it as follows:

require 'cgi'

get '/app' do
  content_type :json
  {"params" => CGI::parse(request.query_string)}.to_json
end

Invoking:

/app?param1=one&param2=two&param2=alt

Gives the following result:

{"params":{"param1":["one"],"param2":["two","alt"]}}

Lysann Schlegel
  • 886
  • 10
  • 16
4

You can create a helper to make the process more friendly:

require 'cgi'

helpers do      
  def request_params_repeats
    params = {}
    request.env["rack.input"].read.split('&').each do |pair|
      kv = pair.split('=').map{|v| CGI.unescape(v)}
      params.merge!({kv[0]=> kv.length > 1 ? kv[1] : nil }) {|key, o, n| o.is_a?(Array) ? o << n : [o,n]}
    end
    params
  end
end

You can then access the parameters in your get block:

get '/app' do
  content_type :json
  request_params_repeats.to_json
end
ewalk
  • 1,438
  • 1
  • 10
  • 15