Reputation: 26640
A web site which protocol I can't influence sends me POST requests where are multiple parameters with same name "t".
Here is my request.raw_post
:
--===13978193024621189109088990673===
Content-Disposition: form-data; name="t"
Content-Type: text/plain; charset=UTF-8
thevalue1
--===13978193024621189109088990673===
Content-Disposition: form-data; name="t"
Content-Type: text/plain; charset=UTF-8
thevalue2
--===13978193024621189109088990673===
Content-Disposition: form-data; name="t"
Content-Type: text/plain; charset=UTF-8
thevalue3
--===13978193024621189109088990673===
Content-Disposition: form-data; name="t"
Content-Type: text/plain; charset=UTF-8
thevalue4
--===13978193024621189109088990673===
Content-Disposition: form-data; name="t"
Content-Type: text/plain; charset=UTF-8
thevalue5
--===13978193024621189109088990673===
Content-Disposition: form-data; name="t"
Content-Type: text/plain; charset=UTF-8
thevalue6
Standard params
collection lists only the last parameter.
How to get all the values?
A way to reproduce this request is:
<form action="/updateinfo" method="post" enctype="multipart/form-data">
<input type="text" name="t" value="thevalue1"><br>
<input type="text" name="t" value="thevalue2"><br>
<input type="text" name="t" value="thevalue3"><br>
<input type="text" name="t" value="thevalue4"><br>
<input type="text" name="t" value="thevalue5"><br>
<input type="text" name="t" value="thevalue6"><br>
<input type="submit">
</form>
Upvotes: 3
Views: 8330
Reputation: 26640
Finally I found and used multipart-parser
gem. It lacks documentation, so here is the code I used:
require 'multipart_parser/reader'
module MultiParams
def parse_multi_params(request)
parts={}
reader = MultipartParser::Reader.new(MultipartParser::Reader::extract_boundary_value(request.headers['CONTENT_TYPE']))
reader.on_part do |part|
pn = part.name.to_sym
part.on_data do |partial_data|
if parts[pn].nil?
parts[pn] = partial_data
else
parts[pn] = [parts[pn]] unless parts[pn].kind_of?(Array)
parts[pn] << partial_data
end
end
end
reader.write request.raw_post
reader.ended? or raise Exception, 'truncated multipart message'
parts
end
end
Usage in a controller:
require 'multi_params'
class MyController < ApplicationController
include MultiParams
def my_method
mp = parse_multi_params(request)
process_params(mp[:t])
end
end
Upvotes: 5
Reputation: 10630
Please take a look how rack parses incoming parameters and converts into hash. You can take raw_request
and put it through your own params parser that would be very similar to racks implementation, with the addition to convert parameter t
directly to an array. something like this:
def normalize_params(params, name, v = nil)
name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
k = $1 || ''
after = $' || ''
return if k.empty?
if after == "" && k == 't'
params[k] ||= []
params[k] << v
elsif == ""
params[k] = v
elsif after == "[]"
params[k] ||= []
params[k] << v
elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
child_key = $1
params[k] ||= []
if params_hash_type?(params[k].last)
&& !params[k].last.key?(child_key)
normalize_params(params[k].last, child_key, v)
else
params[k] << normalize_params(params.class.new, child_key, v)
end
else
params[k] ||= params.class.new
params[k] = normalize_params(params[k], after, v)
end
return params
end
Upvotes: 0